cmake/*.h !filter
cmake/*.cu !filter
cmake/*.cuh !filter
-cmake/FindCUDA/*.cmake !filter
docs/doxygen/Doxyfile-*.cmakein !filter
docs/doxygen/*.cpp !filter
docs/doxygen/examples/*.cpp filter=clangformat
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-cmake_minimum_required(VERSION 3.9.6)
-if(POLICY CMP0074) #3.12
- cmake_policy(SET CMP0074 NEW)
-endif()
+cmake_minimum_required(VERSION 3.13)
+cmake_policy(SET CMP0074 NEW) # From CMake 3.12
cmake_policy(SET CMP0068 NEW) # From CMake-3.9
# CMake modules/macros are in a subdirectory to keep this file cleaner
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform)
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- # Providing a default value >=10.9 helps to find modern C++ compatibility,
+ # Providing a default value >=10.14 helps to find modern C++ compatibility,
# such as by defaulting to the Clang libc++ instead of libstdc++.
- set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9 CACHE STRING
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14 CACHE STRING
"OS X deployment target affects default SDK version and compiler flags."
FORCE)
# By default, limit the binary architecture to a single 64-bit build.
project(Gromacs)
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(LibStdCpp)
+# Python is first referenced in gmxVersionInfo, so we perform the search early
+# to find a suitable installation for all components.
+include(gmxPythonDiscovery)
# Set up common version variables, as well as general information about
# the build tree (whether the build is from a source package or from a git
# repository). Also declares a few functions that will be used for generating
mark_as_advanced(GMX_BUILD_OWN_FFTW)
mark_as_advanced(GMX_DISABLE_FFTW_MEASURE)
-gmx_option_multichoice(
- GMX_QMMM_PROGRAM
- "QM package for QM/MM"
- None
- none gaussian mopac gamess orca)
-
gmx_dependent_cache_variable(GMX_SIMD_REF_FLOAT_WIDTH "Reference SIMD single precision width" STRING "4" "GMX_SIMD STREQUAL REFERENCE")
gmx_dependent_cache_variable(GMX_SIMD_REF_DOUBLE_WIDTH "Reference SIMD double precision width" STRING "2" "GMX_SIMD STREQUAL REFERENCE")
include(gmxManageSimd)
gmx_manage_simd()
-include(gmxManageCycleCounters)
-gmx_manage_cycle_counters()
-
-# Process QM/MM Settings
-if(${GMX_QMMM_PROGRAM} STREQUAL "GAUSSIAN")
- set(GMX_QMMM_GAUSSIAN 1)
-elseif(${GMX_QMMM_PROGRAM} STREQUAL "MOPAC")
- set(GMX_QMMM_MOPAC 1)
-elseif(${GMX_QMMM_PROGRAM} STREQUAL "GAMESS")
- set(GMX_QMMM_GAMESS 1)
-elseif(${GMX_QMMM_PROGRAM} STREQUAL "ORCA")
- set(GMX_QMMM_ORCA 1)
-elseif(${GMX_QMMM_PROGRAM} STREQUAL "NONE")
- # nothing to do
-else()
- gmx_invalid_option_value(GMX_QMMM_PROGRAM)
-endif()
-
-
##################################################
# Process FFT library settings
##################################################
message("CMAKE_EXE_LINKER_FLAGS: ${FFT_LINKER_FLAGS} ${MPI_LINKER_FLAGS}")
message("CMAKE_SHARED_LINKER_FLAGS: ${FFT_LINKER_FLAGS} ${MPI_LINKER_FLAGS}")
endif()
+# Allow `admin` directory to be easily conveyed to nested CMake commands.
+set(GMX_ADMIN_DIR ${CMAKE_SOURCE_DIR}/admin)
########################################################################
# Specify install locations
endif()
# TODO: Determine control flow and defaults for package installation and testing use cases.
-# Ref: http://redmine.gromacs.org/issues/2896
+# Ref: https://gitlab.com/gromacs/gromacs/-/issues/2896
option(GMX_PYTHON_PACKAGE "Configure gmxapi Python package" OFF)
mark_as_advanced(GMX_PYTHON_PACKAGE)
if (NOT GMX_BUILD_MDRUN_ONLY)
- # Note: Though only documented as an output variable, PYTHON_EXECUTABLE is
- # also effective as a CMake input variable to effectively hint the location
- # of the Python interpreter. This may be helpful in environments with both
- # Python 2 and Python 3 on the default PATH.
- # Ref: https://cmake.org/cmake/help/latest/module/FindPythonInterp.html
- if(FIND_PACKAGE_MESSAGE_DETAILS_PythonInterp)
- # Keep quiet on subsequent runs of cmake
- set(PythonInterp_FIND_QUIETLY ON)
- endif()
- # Older CMake versions might not search for Python newer than 3.7.
- set(Python_ADDITIONAL_VERSIONS 3.8)
- if(GMX_PYTHON_PACKAGE)
- find_package(PythonInterp 3.5 REQUIRED)
- # Note: PythonLibs will be found later by pybind11.
- # TODO: (issue #2998) When CMake >= 3.12 is required, update detection.
- # I.e. find_package(Python3 3.5 COMPONENTS Interpreter Development REQUIRED)
- else()
- find_package(PythonInterp 3.5)
- endif()
find_package(ImageMagick QUIET COMPONENTS convert)
include(gmxTestImageMagick)
GMX_TEST_IMAGEMAGICK(IMAGE_CONVERT_POSSIBLE)
Questions? Contact Christian R. Trott (crtrott@sandia.gov)
-18. pybind11 release 2.2.4 from https://github.com/pybind/pybind11
+18. pybind11 release 2.5.0 from https://github.com/pybind/pybind11
==================================================================
Files: python_packaging/src/external/pybind/*
20. Reference implementation of std::optional
=============================================
-Used with minor modifications from commit a08fda6c674ae4c9f of
+Used with minor modifications from commit 096ce6d7e45ef184d of
https://github.com/martinmoene/optional-lite.git, which is licensed as below.
Boost Software License - Version 1.0 - August 17th, 2003
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-# These options need to match the node label in Jenkins and the
-# capabilities in releng/agents.py for the agent where the analysis is
-# intended to run.
-build_options = ['clang-8', 'clang-static-analyzer-8']
-
-# Policy global variables
-use_stdlib_through_env_vars = False
-
-def do_build(context):
- cmake_opts = {
- 'CMAKE_BUILD_TYPE': 'Debug',
- # Build tests as part of the all target.
- 'GMX_DEVELOPER_BUILD': 'ON',
- 'GMX_GPU': 'OFF',
- 'GMX_OPENMP': 'OFF',
- 'GMX_SIMD': 'None',
- 'GMX_USE_RDTSCP': 'OFF',
- 'GMX_FFT_LIBRARY': 'fftpack',
- 'GMX_CLANG_ANALYZER' : 'ON'
- }
- context.env.append_to_env_var('CXXFLAGS', '-stdlib=libc++')
-
- context.run_cmake(cmake_opts)
- context.build_target(target=None)
- context.process_clang_analyzer_results()
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-def do_build(context):
- context.env.set_env_var('CLANG_FORMAT', context.env.get_clang_format_command('7'))
- clangformat_log = context.workspace.get_path_for_logfile('clang-format.log', category='clang-format')
- cmd = ['admin/clang-format.sh', 'update', '--rev=HEAD^', '--warnings=' + clangformat_log]
- ret = context.run_cmd(cmd, use_return_code=True)
- if ret == 1:
- with open(clangformat_log, 'r') as f:
- warnings = f.readlines()
- if len(warnings) <= 5:
- details = [x.rstrip() for x in warnings]
- else:
- format_count = 0
- for w in warnings:
- if 'clang-format performed' in w:
- format_count += 1
- details = []
- if format_count > 0:
- details.append('fixed formatting issues in {0} files'.format(format_count))
- elif ret != 0:
- raise BuildError('clang-format.sh failed to run')
-
- context.workspace.upload_revision(project=Project.GROMACS, file_glob='*')
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-def do_build(context):
- context.env.set_env_var('CLANG_FORMAT', context.env.get_clang_format_command('7'))
- clangformat_log = context.workspace.get_path_for_logfile('clang-format.log', category='clang-format')
- copyright_log = context.workspace.get_path_for_logfile('copyright.log', category='copyright')
- cmd = ['admin/clang-format.sh', 'check', '--rev=HEAD^', '--warnings=' + clangformat_log]
- ret = context.run_cmd(cmd, use_return_code=True)
- if ret == 1:
- with open(clangformat_log, 'r') as f:
- warnings = f.readlines()
- if len(warnings) <= 5:
- details = [x.rstrip() for x in warnings]
- else:
- format_count = 0
- for w in warnings:
- if 'needs formatting' in w:
- format_count += 1
- details = []
- if format_count > 0:
- details.append('formatting issues in {0} files'.format(format_count))
- context.mark_unstable(reason='clang-format.sh found issues', details=details)
- elif ret != 0:
- raise BuildError('clang-format.sh failed to run')
-
- cmd = ['admin/copyright.sh', 'check', '--rev=HEAD^', '--warnings=' + copyright_log]
- ret = context.run_cmd(cmd, use_return_code=True)
- if ret == 1:
- with open(copyright_log, 'r') as f:
- warnings = f.readlines()
- if len(warnings) <= 5:
- details = [x.rstrip() for x in warnings]
- else:
- cpyear_count = 0
- cpheader_count = 0
- for w in warnings:
- if 'copyright year' in w:
- cpyear_count += 1
- if 'copyright header' in w:
- cpheader_count += 1
- details = []
- if cpyear_count > 0:
- details.append('copyright year missing in {0} files'.format(cpyear_count))
- if cpheader_count > 0:
- details.append('copyright header issues in {0} files'.format(cpheader_count))
- context.mark_unstable(reason='copyright.sh found issues', details=details)
- elif ret != 0:
- raise BuildError('copyright.sh failed to run')
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import os.path
-
-build_options = ['gcc-7', 'gcov-7']
-extra_projects = [Project.REGRESSIONTESTS]
-
-def do_build(context):
- cmake_opts=dict()
- cmake_opts['CMAKE_BUILD_TYPE'] = 'Debug'
- cmake_opts['GMX_BUILD_FOR_COVERAGE'] = 'ON'
- cmake_opts['CMAKE_C_FLAGS'] = '--coverage -g'
- cmake_opts['CMAKE_CXX_FLAGS'] = '--coverage -g'
- cmake_opts['GMX_GPU'] = 'OFF'
- # Ideally, this would be Reference, but running the regression tests is way
- # too slow that way (and also with None)...
- cmake_opts['GMX_SIMD'] = 'SSE4.1'
- cmake_opts['GMX_USE_RDTSCP'] = 'DETECT'
-
- context.env.set_env_var('GMX_NO_TERM', '1')
-
- context.run_cmake(cmake_opts)
- context.build_target(target=None)
- context.build_target(target='tests')
-
- context.run_ctest(args=['--output-on-failure'])
-
- context.env.prepend_path_env(os.path.join(context.workspace.build_dir, 'bin'))
- context.chdir(context.workspace.get_project_dir(Project.REGRESSIONTESTS))
- cmd = ['perl', 'gmxtest.pl', '-xml', 'all', '-nt', '2']
- context.run_cmd(cmd, failure_message='Regression tests failed to execute')
-
- context.process_coverage_results(exclude=['^src/external/'])
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import os
-import re
-
-build_options = ['doxygen-1.8.5']
-build_out_of_source = True
-
-extra_options = {
- 'source-md5': Option.string
-}
-
-def do_build(context):
- cmake_opts = {
- 'GMX_BUILD_HELP': 'ON',
- 'GMX_BUILD_MANUAL': 'ON',
- 'SOURCE_MD5SUM': context.opts.source_md5,
- 'CMAKE_BUILD_TYPE': 'Debug',
- 'GMX_GPU': 'OFF',
- 'GMX_OPENMP': 'OFF',
- 'GMX_SIMD': 'None',
- 'GMX_USE_RDTSCP': 'OFF'
- }
- release = (context.job_type == JobType.RELEASE)
- if release:
- cmake_opts['GMX_BUILD_TARBALL'] = 'ON'
- elif context.job_type == JobType.GERRIT:
- cmake_opts['GMX_COMPACT_DOXYGEN'] = 'ON'
- cmake_opts['DOXYGEN_EXECUTABLE'] = context.env.doxygen_command
- context.run_cmake(cmake_opts)
-
- # we keep the individual build targets here to ensure some
- # granularity of the resulting error messages (if any).
- # it would be possible to run everything at once with
- # target=webpage, but then debugging a failed build would
- # become exceedingly tedious
- context.build_target(target='sphinx-input', parallel=True,
- failure_string='Generating Sphinx input failed',
- continue_on_failure=True)
- context.build_target(target='sphinx-programs', parallel=True,
- failure_string='Running gmx help -export rst failed',
- continue_on_failure=True)
-
- context.build_target(target='manual', parallel=True,
- target_descr='PDF manual', continue_on_failure=True)
- logfile = os.path.join(context.workspace.build_dir, 'docs/manual/gromacs.log')
- if os.path.isfile(logfile):
- with open(logfile, 'r') as f:
- manual_log = f.read()
- if re.search(r'LaTeX Warning: Reference .* on page .* undefined', manual_log):
- context.mark_unstable('undefined references in PDF manual')
- context.publish_logs([logfile])
-
- # check-source is not necessary for a release build, and building these
- # separately causes many of the Doxygen targets to get built twice if run
- # from a tarball.
- if not release:
- context.build_target(target='doxygen-all', parallel=True,
- target_descr='Doxygen documentation', continue_on_failure=True)
- context.build_target(target='check-source', parallel=True,
- failure_string='check-source failed to run', continue_on_failure=True)
- logs = []
- for target in ('check-source', 'doxygen-xml', 'doxygen-user',
- 'doxygen-lib', 'doxygen-full'):
- logfile = os.path.join(context.workspace.build_dir,
- 'docs/doxygen/{0}.log'.format(target))
- if os.path.isfile(logfile) and os.stat(logfile).st_size > 0:
- context.mark_unstable('{0} produced warnings'.format(target))
- logs.append(logfile)
- context.publish_logs(logs, category='doxygen')
- if context.failed:
- return
-
- if context.failed:
- return
-
- sphinx_targets = [ ('webpage-sphinx', 'html', 'HTML') ]
- if not release:
- sphinx_targets.extend((
- ('man', 'man', 'man page'),
- ('install-guide', 'install', 'install-guide')
- ))
- logs = []
- for target, log, descr in sphinx_targets:
- context.build_target(target=target, parallel=True,
- failure_string='Sphinx: {0} generation failed'.format(descr),
- continue_on_failure=True)
- logfile = os.path.join(context.workspace.build_dir,
- 'docs/sphinx-{0}.log'.format(log))
- if os.path.isfile(logfile) and os.stat(logfile).st_size > 0:
- context.mark_unstable('Sphinx: {0} generation produced warnings'.format(descr))
- logs.append(logfile)
- context.publish_logs(logs, category='sphinx')
- if context.failed:
- return
-
- context.build_target(target='webpage', parallel=True)
- if context.failed:
- return
-
- ignore_urls = ['html-full', 'html-user', 'html-lib', '.tar.gz', '_sources']
- cmd = ['linkchecker', 'docs/html/index.html', '-f',
- context.workspace.get_project_dir(Project.GROMACS) + '/docs/linkcheckerrc',
- '-Fxml']
- for url in ignore_urls:
- cmd.extend(['--ignore-url', url])
-
- context.run_cmd(cmd, ignore_failure=False)
-
- logfile = os.path.join(context.workspace.build_dir,
- 'docs/linkchecker-out.xml')
- if os.path.isfile(logfile):
- with open(logfile, 'r') as f:
- manual_log = f.read()
- if re.search(r'URLError:', manual_log):
- context.mark_unstable('non resolvable URL in webpage')
- if re.search(r'warnings', manual_log):
- context.mark_unstable('empty pages in web documentation')
- context.publish_logs([logfile], category='webpage')
-
- if context.failed:
- return
-
- if release:
- version_info = context.read_cmake_variable_file('VersionInfo.cmake')
- version = version_info['GMX_VERSION_STRING']
- package_name = 'website-' + version
- context.make_archive(package_name, root_dir='docs/html', prefix=package_name)
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2016, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import json
-
-def do_build(context):
- cmd = [context.env.cmake_command, '-P', 'cmake/gmxVersionInfo.cmake']
- info_json = context.run_cmd(cmd, use_output=True)
- values = json.loads(info_json)
- context.set_version_info(values['version'], values['regressiontest-md5sum'])
+++ /dev/null
-# This matrix is intended to permit Jenkins:
-# - nigtly testing of the GPU direct communations experimental features in the 2020 release
-# - on-demand testing of the GPU direct communication code path
-# This is neceassary due to:
-# i) the limitations of the integration tests which only test the deafult code-path
-# ii) limitations of the regresssion tests which are not able to rerun update with a
-# different offload mode unless the default is observed to be GPU.
-#
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-#
-# Both configurations currently target bs_nix1204, for better load
-# balance with pre-submit matrix, which makes heavier use of
-# bs_nix1310 agent.
-
-# Test an older version of CUDA
-# Test MPI with CUDA
-# Test multiple PP ranks with separate PME rank
-# Test with thread-MPI (library MPI not supported initially)
-# Test GPU comm features in the above combination
-gcc-5 gpuhw=nvidia cuda-9.0 npme=1 nranks=3 thread-mpi openmp gpucomm
-
-# Test newest gcc supported by newest CUDA at time of release
-# Test multiple PP ranks without separate PME rank
-# Test thread-MPI with CUDA
-# Test GPU comm features in the above combination
-gcc-8 gpuhw=nvidia nranks=2 gpu_id=1 cuda-10.1 thread-mpi openmp cmake-3.10.0 release-with-assert simd=avx2_256 hwloc libhwloc-2.0.4 gpucomm
-
-# Test non-default use of mdrun -gpu_id
-# Test GPU-sharing among 4 PP ranks
-# Test no hwloc build, tests internal CPU topology detection (mainly for x86)
-# Test GPU comm features in the above combination
-gcc-7 gpuhw=nvidia nranks=4 gpu_id=1 cuda-10.0 no-hwloc release-with-assert gpucomm
-
-# Test CUDA build on a agent with no CUDA devices
-# Test without TNG support
-# Test GPU comm features in the above combination
-gcc-7 gpuhw=none cuda-10.0 openmp no-tng release-with-assert gpucomm
-
-# Test OpenCL build with gpudev features
-# Test GPU comm on the OpenCL path where it is unsupported
-clang-8 openmp gpuhw=amd opencl-1.2 clFFT-2.14 simd=None gpucomm
-
-# Test a non-GPU build with the gpucomm optiom set
-gcc-8 double x11 no-tng fftpack simd=sse4.1 gpucomm
+++ /dev/null
-# This matrix is intended to permit Jenkins:
-# - nigtly testing of the GPU update features in the 2020 release
-# - on-demand testing of the GPU update code path
-# This is neceassary due to:
-# i) the limitations of the integration tests which only test the deafult code-path
-# ii) limitations of the regresssion tests which are not able to rerun update with a
-# different offload mode unless the default is observed to be GPU.
-#
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-
-# Test GPU update-constraints features on a single PP+PME rank
-gcc-8 gpuhw=nvidia nranks=1 gpu_id=1 cuda-10.1 thread-mpi openmp cmake-3.10.0 release-with-assert simd=avx2_256 hwloc libhwloc-2.0.4 gpuupdate
-
-# Test GPU update-constraints features in a CUDA build without CUDA devices
-gcc-7 gpuhw=none cuda-10.0 openmp no-tng release-with-assert gpuupdate
-
-# Test GPU update-constraints on the OpenCL path where it is unsupported
-clang-8 openmp gpuhw=amd opencl-1.2 clFFT-2.14 simd=None gpuupdate
-
-# Test GPU update-constraints features with multiple PP ranks and one PME rank
-# Note: this should fall back correctly to the CPU codepath
-gcc-5 gpuhw=nvidia cuda-9.0 cmake-3.9.6 thread-mpi npme=1 nranks=3 release-with-assert gpuupdate
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import os.path
-
-# Policy global variables
-use_stdlib_through_env_vars = False
-
-# These are accessible later in the script, just like other declared
-# options, via e.g. context.opts.release. Keep these in alphabetical
-# order for more convenient rebasing
-extra_options = {
- 'asan': Option.simple,
- 'buildfftw': Option.simple,
- 'clang_cuda': Option.bool,
- 'double': Option.simple,
- 'fftpack': Option.simple,
- 'gpu_id': Option.string,
- 'hwloc': Option.bool,
- 'mdrun-only': Option.simple,
- 'mkl': Option.simple,
- 'mpiinplace': Option.bool,
- 'npme': Option.string,
- 'nranks': Option.string,
- 'openmp': Option.bool,
- 'reference': Option.simple,
- 'release': Option.simple,
- 'release-with-assert': Option.simple,
- 'release-with-debug-info': Option.simple,
- 'static': Option.simple,
- 'thread-mpi': Option.bool,
- 'tng' : Option.bool,
- # The following options cater for testing code in Jenkins that is
- # currently behind feature flags in master branch.
- 'gpubufferops' : Option.bool,
- 'gpucomm': Option.bool,
- 'gpuupdate': Option.bool,
-}
-
-extra_projects = [Project.REGRESSIONTESTS]
-
-def do_build(context):
- cmake_opts = dict()
- cmake_opts['GMX_COMPILER_WARNINGS'] = 'ON'
- cmake_opts['GMX_DEFAULT_SUFFIX'] = 'OFF'
- cmake_opts['CMAKE_BUILD_TYPE'] = 'Debug'
- cmake_opts['GMX_USE_RDTSCP'] = 'DETECT'
-
- if not context.opts.msvc and not context.opts.mdrun_only and not context.opts.static:
- cmake_opts['GMXAPI'] = 'ON'
-
- if context.opts.reference:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'Reference'
- elif context.opts['release']:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'Release'
- elif context.opts['release-with-assert']:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'RelWithAssert'
- elif context.opts['release-with-debug-info']:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'RelWithDebInfo'
- elif context.opts.asan:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'ASAN'
- elif context.opts.tsan:
- cmake_opts['CMAKE_BUILD_TYPE'] = 'TSAN'
-
- if context.opts.static:
- cmake_opts['BUILD_SHARED_LIBS'] = 'OFF'
-
- if context.opts.phi:
- cmake_opts['CMAKE_TOOLCHAIN_FILE'] = 'Platform/XeonPhi'
-
- if context.opts.double:
- cmake_opts['GMX_DOUBLE'] = 'ON'
-
- if context.opts.simd is None:
- cmake_opts['GMX_SIMD'] = 'None'
- else:
- cmake_opts['GMX_SIMD'] = context.opts.simd
- if context.opts.cuda or context.opts.opencl:
- cmake_opts['GMX_GPU'] = 'ON'
- if context.opts.opencl:
- context.env.set_env_var('CUDA_PATH', context.env.cuda_root)
- cmake_opts['GMX_USE_OPENCL'] = 'ON'
- else:
- cmake_opts['CUDA_TOOLKIT_ROOT_DIR'] = context.env.cuda_root
- if context.opts.clang_cuda:
- cmake_opts['GMX_CLANG_CUDA'] = 'ON'
- else:
- cmake_opts['CUDA_HOST_COMPILER'] = context.env.cuda_host_compiler
- else:
- cmake_opts['GMX_GPU'] = 'OFF'
- if context.opts.thread_mpi is False:
- cmake_opts['GMX_THREAD_MPI'] = 'OFF'
- if context.opts.mpi:
- cmake_opts['GMX_MPI'] = 'ON'
- if context.opts.mpiinplace is False:
- cmake_opts['GMX_MPI_IN_PLACE'] = 'OFF'
- if context.opts.openmp is False:
- cmake_opts['GMX_OPENMP'] = 'OFF'
- if context.opts.tng is False:
- cmake_opts['GMX_USE_TNG'] = 'OFF'
-
- if context.opts.mkl:
- cmake_opts['GMX_FFT_LIBRARY'] = 'mkl'
- elif context.opts.fftpack:
- cmake_opts['GMX_FFT_LIBRARY'] = 'fftpack'
- elif context.opts.buildfftw:
- cmake_opts['GMX_BUILD_OWN_FFTW'] = 'ON'
- cmake_opts['GMX_BUILD_OWN_FFTW_URL'] = 'ftp://ftp.gromacs.org/misc/fftw-3.3.8.tar.gz'
- cmake_opts['GMX_BUILD_OWN_FFTW_MD5'] = '8aac833c943d8e90d51b697b27d4384d'
- if context.opts.mkl or context.opts.atlas or context.opts.armpl:
- cmake_opts['GMX_EXTERNAL_BLAS'] = 'ON'
- cmake_opts['GMX_EXTERNAL_LAPACK'] = 'ON'
- if context.opts.clFFT:
- cmake_opts['GMX_EXTERNAL_CLFFT'] = 'ON'
- cmake_opts['clFFT_ROOT'] = context.env.clFFT_root
-
- if context.opts.armpl:
- cmake_opts['FFTWF_LIBRARY'] = os.path.join(context.env.armpl_dir, 'lib/libarmpl_lp64.so')
- cmake_opts['FFTWF_INCLUDE_DIR'] = os.path.join(context.env.armpl_dir, 'include')
- cmake_opts['GMX_BLAS_USER'] = os.path.join(context.env.armpl_dir, 'lib/libarmpl_lp64.so')
- cmake_opts['GMX_LAPACK_USER'] = os.path.join(context.env.armpl_dir, 'lib/libarmpl_lp64.so')
-
- if context.opts.hwloc is False:
- cmake_opts['GMX_HWLOC'] = 'OFF'
- elif context.opts.hwloc is True:
- cmake_opts['GMX_HWLOC'] = 'ON'
- else:
- cmake_opts['GMX_HWLOC'] = 'AUTO'
-
- if context.opts.tng is False:
- cmake_opts['GMX_USE_TNG'] = 'OFF'
-
- if context.opts.x11:
- cmake_opts['GMX_X11'] = 'ON'
-
- if context.opts.tidy:
- cmake_opts['GMX_CLANG_TIDY'] = 'ON'
- cmake_opts['CLANG_TIDY'] = context.env.cxx_compiler.replace("clang++", "clang-tidy")
-
- # At least hwloc on Jenkins produces a massive amount of reports about
- # memory leaks, which cannot be reasonably suppressed because ASAN cannot
- # produce a reasonable stack trace for them.
- if context.opts.asan:
- cmake_opts['GMX_HWLOC'] = 'OFF'
-
- if context.opts.gpubufferops:
- context.env.set_env_var('GMX_USE_GPU_BUFFER_OPS', "1")
-
- # GPU comm flag enables both DD and PP-PME comm as well as buffer ops (hard dependency)
- if context.opts.gpucomm:
- context.env.set_env_var('GMX_USE_GPU_BUFFER_OPS', "1")
- context.env.set_env_var('GMX_GPU_DD_COMMS', "1")
- context.env.set_env_var('GMX_GPU_PME_PP_COMMS', "1")
-
- # GPU update flag changes the default for '-update auto' to GPU
- if context.opts.gpuupdate:
- context.env.set_env_var('GMX_FORCE_UPDATE_DEFAULT_GPU', "1")
-
- regressiontests_path = context.workspace.get_project_dir(Project.REGRESSIONTESTS)
-
- if context.job_type == JobType.RELEASE:
- cmake_opts['REGRESSIONTEST_PATH'] = regressiontests_path
- else:
- if context.opts.mdrun_only:
- cmake_opts['GMX_BUILD_MDRUN_ONLY'] = 'ON'
-
- # The build configuration has constructed the environment of the
- # context so that a particular c++ standard library can be used,
- # which may come from a different installation of gcc. Here, we
- # tell CMake how to react to this.
- #
- # TODO Once gerrit 9051 and 9053 are both submitted on master,
- # remove the hasattr part of the predicate, which will then be
- # redundant.
- if hasattr(context.env, 'gcc_exe') and context.env.gcc_exe is not None:
- cmake_opts['GMX_GPLUSPLUS_PATH'] = context.env.gcc_exe
- # TODO are these needed?
- # gcc_exe_dirname = os.path.dirname(self.gcc_exe)
- # gcc_toolchain_path = os.path.join(gcc_exe_dirname, '..')
- # format_for_linker_flags="-Wl,-rpath,{gcctoolchain}/lib64 -L{gcctoolchain}/lib64"
- # cmake_opts['CMAKE_CXX_LINK_FLAGS'] = format_for_linker_flags.format(gcctoolchain=gcc_toolchain_path)
-
- context.env.set_env_var('GMX_NO_TERM', '1')
-
- context.run_cmake(cmake_opts)
- context.build_target(target=None, keep_going=True)
-
- # TODO: Consider if it would be better to split this into a separate build
- # script, since it is somewhat different, even though it benefits from some
- # of the same build options.
- if context.job_type == JobType.RELEASE:
- context.build_target(target='check', keep_going=True)
- context.build_target(target='install')
- if context.opts.mdrun_only:
- context.workspace.clean_build_dir()
- cmake_opts['REGRESSIONTEST_PATH'] = None
- cmake_opts['GMX_BUILD_MDRUN_ONLY'] = 'ON'
- context.run_cmake(cmake_opts)
- context.build_target(target=None, keep_going=True)
- context.build_target(target='check', keep_going=True)
- context.build_target(target='install')
- gmxrc_cmd = '. ' + os.path.join(context.workspace.install_dir, 'bin', 'GMXRC')
- context.env.run_env_script(gmxrc_cmd)
- cmd = [os.path.join(regressiontests_path, 'gmxtest.pl'), '-nosuffix', 'all']
- if context.opts.mpi:
- cmd += ['-np', '1']
- if context.opts.double:
- cmd += ['-double']
- if context.opts.mdrun_only:
- cmd += ['-mdrun', 'mdrun']
- context.run_cmd(cmd, failure_message='Regression tests failed to execute')
- # TODO: Add testing for building the template.
- # TODO: Generalize the machinery here such that it can easily be used
- # also for non-release builds.
- else:
- context.build_target(target='tests', keep_going=True)
-
- context.run_ctest(args=['--output-on-failure', '--label-exclude', 'SlowTest'], memcheck=context.opts.asan)
-
- context.build_target(target='install')
- # TODO: Consider what could be tested about the installed binaries.
-
- # run OpenCL offline compile tests on clang tidy builds
- if (context.opts.tidy and context.opts.opencl):
- context.build_target(target='ocl_nbnxm_kernels')
-
- if not context.opts.mdrun_only:
- context.env.prepend_path_env(os.path.join(context.workspace.build_dir, 'bin'))
- context.chdir(regressiontests_path)
-
- use_tmpi = not context.opts.mpi and context.opts.thread_mpi is not False
-
- cmd = 'perl gmxtest.pl -mpirun mpirun -xml -nosuffix all'
-
- # setting this stuff below is just a temporary solution,
- # it should all be passed as a proper the runconf from outside
- # The whole mechanism should be rethought in #1587.
- if context.opts.phi:
- cmd += ' -ntomp 28'
- elif context.opts.openmp:
- # OpenMP should always work when compiled in! Currently not set if
- # not explicitly set
- cmd += ' -ntomp 2'
-
- if context.opts.gpuhw == Gpuhw.NONE:
- context.env.set_env_var('GMX_DISABLE_GPU_DETECTION', '1')
-
- if context.opts.gpu_id:
- cmd += ' -gpu_id ' + context.opts.gpu_id
-
- if context.opts.nranks:
- nranks = context.opts.nranks
- else:
- nranks = '2'
-
- if context.opts.npme:
- cmd += ' -npme ' + context.opts.npme
-
- if context.opts.mpi:
- cmd += ' -np ' + nranks
- elif use_tmpi:
- cmd += ' -nt ' + nranks
- if context.opts.double:
- cmd += ' -double'
- if context.opts.asan:
- context.env.set_env_var('ASAN_OPTIONS', 'detect_leaks=0')
- context.run_cmd(cmd, shell=True, failure_message='Regression tests failed to execute')
+++ /dev/null
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-#
-# Other configurations might coincidentally test such configurations
-# (e.g. because they are the current default), but it is appropriate
-# to intend to teach each feature (or a feature combination) exactly
-# once, and for the intent to be reflected precisely in the
-# configuration syntax, so that the configurations are stable even
-# if the defaults change in future.
-#
-# The phrase "at time of release" refers to either the initial
-# GROMACS release from that branch, or the next expected release
-# from that branch. (We will tend not to retroactively support
-# newer infrastructure in CI, unless it's either easy or of
-# high impact.)
-
-# Test clang on ARM v8
-# Test ARM_NEON SIMD
-clang-3.9 no-openmp simd=ARM_NEON_ASIMD release-with-assert
-
-# Test AVX2_256 SIMD
-# Test icc with SIMD in mixed precision in release mode
-# Test icc with MPI
-icc-19 mpi release simd=avx2_256 no-hwloc
-
-# Test AVX_128_FMA SIMD in mixed precision
-# Test build of downloaded FFTW
-gcc-5 openmp simd=avx_128_fma cmake-3.11.4 buildfftw
-
-# Test with SSE2 + double
-gcc-9 simd=sse2 fftpack double
-
-# Test OpenMP with clang-tidy
-# Test AVX2_256 SIMD with clang-tidy
-# Test OpenCL build with clang-tidy
-# Test offline OpenCL kernel build with clang-tidy
-clang-8 simd=avx2_256 opencl-1.2 cmake-3.14.5 tidy
+++ /dev/null
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-#
-# Other configurations might coincidentally test such configurations
-# (e.g. because they are the current default), but it is appropriate
-# to intend to teach each feature (or a feature combination) exactly
-# once, and for the intent to be reflected precisely in the
-# configuration syntax, so that the configurations are stable even
-# if the defaults change in future.
-
-# Test on ARM v7
-# Test ARM_NEON SIMD
-gcc-5 simd=ARM_NEON no-hwloc release-with-assert
-
-# Test on ARM v8
-# Test ARM_NEON_ASIMD SIMD
-gcc-5 simd=ARM_NEON_ASIMD release-with-assert
-
-# Test the mdrun-only build
-# Test newest gcc at time of release
-# TODO In combination with gmx from another build, arrange to run regressiontests
-gcc-9 mpi no-openmp fftpack mdrun-only
-
-# Test MPMD PME with thread-MPI
-# Test oldest supported icc
-# Test icc with AVX256 in double precision in release mode
-icc-17 simd=avx_256 npme=1 nranks=2 no-openmp double fftpack release
-
-# Test CUDA build on a agent with no CUDA devices
-# Test without TNG support
-gcc-7 gpuhw=none cuda-10.0 openmp no-tng release-with-assert
-
-# Test non-default GMX_PREFER_STATIC_LIBS behavior
-# TODO enable this
-# msvc-2017 double no-threadmpi no-prefer-static-libs release-with-assert
-
-# Test newest icc at time of release
-# TODO Reinstate this when SIMD exp works again
-# Test icc with SIMD in mixed precision in release mode
-icc-19 simd=none mkl release
-
-# Test SSE4.1 SIMD
-# Test single-rank GPU
-# Test clang host and device compilation, with OpenMP and CUDA
-# NOTE: using release-with-assert as debug build trigers some ptx warnings
-clang-8 simd=sse4.1 openmp nranks=1 gpuhw=nvidia cuda-10.0 clang_cuda release-with-assert
-
-# Test MPMD PME with library MPI
-# Test clang + OpenMP
-# Test clang in double precision
-# Test AVX_128_FMA SIMD + Double (Important for Simd4N=Simd4 and sizeof(SimdInt32)!=4*GMX_SIMD_REAL_WIDTH)
-clang-8 double openmp simd=avx_128_fma npme=1 nranks=2 mpi
-
-# Test SSE2 SIMD
-# Test CMAKE_BUILD_TYPE=Release
-# Test OpenCL
-# Test bundled clFFT (developed by AMD) on NVIDIA OpenCL
-gcc-6 npme=1 nranks=2 opencl-1.2 gpuhw=nvidia simd=sse2 release
-
-# Test non-default use of mdrun -gpu_id
-# Test GPU-sharing among 4 PP ranks
-# Test no hwloc build, tests internal CPU topology detection (mainly for x86)
-# Test clang host compilation with CUDA on Linux
-clang-8 gpuhw=nvidia openmp nranks=4 gpu_id=1 cuda-10.1 no-hwloc release-with-assert
-
-# Test ARM HPC compier toolchain with gcc-7
-#gcc-7 armhpc-18.2 openmp simd=ARM_NEON_ASIMD release
-
-# Test ARM HPC compier toolchain with armclang (most recent version at the time if the release)
-# TODO: upgrade to 19.3 before that lands (ref #3011)
-# Test ARMPL for FFTs
-# Test linking against ARMPL for BLAS/LAPACK
-armclang-19.3 armhpc-19.3 armpl openmp simd=ARM_NEON_ASIMD release-with-assert
-
-# TODO
-# Add SIMD + OpenMP + CUDA asan build
-# Add OpenMP + CUDA + device sharing TSAN build
-# Test statically linked hwloc support (if/when it can work well)
-# Test 3D DD (2D is partially covered in regressiontests)
-# Test mdrun -tunepme (e.g. with relaxed tolerances, for now)
-# Consider testing of other CMake option paths
-# Test behaviour when dlopen is not present
+++ /dev/null
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-#
-# Other configurations might coincidentally test such configurations
-# (e.g. because they are the current default), but it is appropriate
-# to intend to teach each feature (or a feature combination) exactly
-# once, and for the intent to be reflected precisely in the
-# configuration syntax, so that the configurations are stable even
-# if the defaults change in future.
-#
-# The phrase "at time of release" refers to either the initial
-# GROMACS release from that branch, or the next expected release
-# from that branch. (We will tend not to retroactively support
-# newer infrastructure in CI, unless it's either easy or of
-# high impact.)
-
-# Test oldest supported gcc
-# Test oldest supported CUDA
-# Test oldest supported Ubuntu
-# Test MPI with CUDA
-# Test MPI with gcc
-# Test MPMD PME with library MPI
-gcc-5 gpuhw=nvidia cuda-9.0 cmake-3.9.6 mpi npme=1 nranks=2 openmp
-
-# Test newest cmake at time of release
-# Test non-default use of mdrun -gpu_id
-# Test newest gcc supported by newest CUDA at time of release
-# Test thread-MPI with CUDA
-# Test SIMD implementation of pair search for GPU code-path
-# Test hwloc-2 support
-gcc-8 gpuhw=nvidia gpu_id=1 cuda-10.1 thread-mpi openmp cmake-3.15.1 release-with-assert simd=avx2_256 hwloc libhwloc-2.0.4
-
-# Test with libcxx
-# Test with ThreadSanitizer + OpenMP + SIMD
-clang-7 no-hwloc tsan libcxx-7 openmp cmake-3.12.1 simd=avx2_256
-
-# Test on MacOS (the gcc-8 and/or x11 flags implicitly steer jobs to the OSX agent)
-# Test X11 build
-# Test gcc in double precision
-# Test without TNG support
-# Test 128-bit SIMD in double precision (to cover SimdInt32 support better)
-# Test fftpack fallback
-gcc-8 double x11 no-tng fftpack simd=sse4.1
-
-# Test oldest supported clang (while avoiding AVX codegen issues in it)
-# Test without OpenMP
-# Test thread-MPI
-# Test with TNG support
-clang-3.6 simd=sse2 thread-mpi no-openmp fftpack cmake-3.11.4 tng
-
-# Test newest clang at time of release
-# Test with AddressSanitizer (without OpenMP, see below)
-clang-8 no-openmp asan cmake-3.11.4
-
-# Test with clang-tidy (without OpenMP)
-clang-8 no-openmp cmake-3.12.1 tidy
-
-# Test oldest supported MSVC on Windows
-# Test newest supported MSVC on Windows
-msvc-2017 openmp release-with-assert
-
-# Test newest icc at the time of release
-# Test icc without SIMD in double precision in release mode
-# Test MKL
-# Test without any MPI
-# Test on CentOS (because cmake-3.9.6 is available there)
-icc-19 no-thread-mpi double openmp mkl cmake-3.9.6 simd=none release
-
-# Test oldest supported cmake
-# Test NVIDIA OpenCL
-# Test external clFFT (for build speed)
-# Test MPI + OpenCL
-# Test AVX2_256 SIMD
-# Test without MPI_IN_PLACE
-gcc-6 openmp gpuhw=nvidia opencl-1.2 clFFT-2.14 cmake-3.9.6 mpi no-mpiinplace simd=avx2_256
-
-# Test AMD OpenCL
-# Test external clFFT (for build speed)
-# Test AVX2_256 SIMD
-# Test newest gcc at time of release
-# Test hwloc-1 support
-gcc-9 openmp simd=avx2_256 gpuhw=amd opencl-1.2 clFFT-2.14 hwloc libhwloc-1.11.2 cmake-3.14.5
-
-# TODO
-# Add OpenMP support to ASAN build (but libomp.so in clang-4 reports leaks, so might need a suitable build or suppression)
-# Test newest supported LTS Ubuntu
-# Test AVX-512 when hardware is available
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2016,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import os.path
-
-build_options = ['gcc-5', 'cmake-3.9.6']
-extra_projects = [Project.REGRESSIONTESTS]
-
-def run_build(context, cmake_opts):
- context.chdir(context.workspace.build_dir)
- context.run_cmake(cmake_opts)
- context.build_target(target=None)
-
- context.chdir(context.workspace.get_project_dir(Project.REGRESSIONTESTS))
- cmd = ['perl', 'gmxtest.pl', 'all']
- if cmake_opts['GMX_DOUBLE'] == 'ON':
- cmd += ['-double']
- context.run_cmd(cmd, failure_message='Regression tests failed to execute')
-
-def do_build(context):
- cmake_opts=dict()
- cmake_opts['CMAKE_BUILD_TYPE'] = 'Reference'
- context.env.set_env_var('GMX_NO_TERM', '1')
- context.env.prepend_path_env(os.path.join(context.workspace.build_dir, 'bin'))
-
- cmake_opts['GMX_DOUBLE'] = 'ON'
- run_build(context, cmake_opts)
-
- cmake_opts['GMX_DOUBLE'] = 'OFF'
- run_build(context, cmake_opts)
-
- context.workspace.upload_revision(project=Project.REGRESSIONTESTS, file_glob='*reference*')
+++ /dev/null
-# Comment line(s) preceding each configuration document the main
-# intent behind that configuration, so that we can correctly judge
-# whether to preserve that during maintenance decisions.
-#
-# Other configurations might coincidentally test such configurations
-# (e.g. because they are the current default), but it is appropriate
-# to intend to teach each feature (or a feature combination) exactly
-# once, and for the intent to be reflected precisely in the
-# configuration syntax, so that the configurations are stable even
-# if the defaults change in future.
-#
-# The phrase "at time of release" refers to either the initial
-# GROMACS release from that branch, or the next expected release
-# from that branch. (We will tend not to retroactively support
-# newer infrastructure in CI, unless it's either easy or of
-# high impact.)
-#
-# These configurations will be used to build and test the tarballs
-# before the releases. These all build in release mode (ie with
-# minimal assertions, as we intend the code to be built and used
-# by end users).
-
-# Test mpi support
-# Test mdrun-only build
-gcc-9 mpi mdrun-only release
-
-# Test static linking with gcc
-# Test newest gcc at time of release
-gcc-9 static release
-
-# Test double precision
-# Test with newest supported Intel compiler
-icc-19 double release
-
-# Test static linking with clang
-# Test double precision
-# Test newest supported clang version
-clang-8 static double release cmake-3.10.0
-
-# Test oldest supported gcc at time of release
-# Test with GPU support
-# Test with newest CUDA at time of release
-gcc-5 gpuhw=nvidia cuda-10.0 release
-
-# Test with OpenCL support
-gcc-8 simd=avx2_256 gpuhw=amd opencl-1.2 release
-
-# TODO items
-# Avoid specifying cmake versions just to move jobs away from bs_nix-amd
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-import os.path
-
-build_out_of_source = True
-
-def do_build(context):
- cmake_opts = {
- 'GMX_BUILD_HELP': 'ON',
- 'CMAKE_BUILD_TYPE': 'Debug',
- 'GMX_SIMD': 'None',
- 'GMX_USE_RDTSCP': 'OFF',
- 'GMX_THREAD_MPI': 'OFF',
- 'GMX_OPENMP': 'OFF',
- 'GMX_GPU': 'OFF'
- }
- if context.params.get('RELEASE', Parameter.bool):
- cmake_opts['GMX_BUILD_TARBALL'] = 'ON'
-
- context.run_cmake(cmake_opts)
- context.build_target(target='gmx')
- context.build_target(target='man')
- context.build_target(target='completion')
- context.build_target(target='install-guide')
- context.build_target(target='reference_checksum')
-
- context.build_target(target='package_source')
-
- cpack_config_path = os.path.join(context.workspace.build_dir, 'CPackSourceConfig.cmake')
- cpack_config = context.read_cmake_variable_file(cpack_config_path)
- package_name = cpack_config['CPACK_PACKAGE_FILE_NAME'] + '.tar.gz'
- version = cpack_config['CPACK_PACKAGE_VERSION']
- context.write_package_info(Project.GROMACS, package_name, version)
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-def do_build(context):
- context.env.set_env_var('UNCRUSTIFY', context.env.get_uncrustify_command())
- uncrustify_log = context.workspace.get_path_for_logfile('uncrustify.log', category='uncrustify')
- copyright_log = context.workspace.get_path_for_logfile('copyright.log', category='copyright')
- cmd = ['admin/uncrustify.sh', 'check', '--rev=HEAD^', '--warnings=' + uncrustify_log]
- ret = context.run_cmd(cmd, use_return_code=True)
- if ret == 1:
- with open(uncrustify_log, 'r') as f:
- warnings = f.readlines()
- if len(warnings) <= 5:
- details = [x.rstrip() for x in warnings]
- else:
- uncrustify_count = 0
- for w in warnings:
- if 'needs uncrustify' in w:
- uncrustify_count += 1
- details = []
- if uncrustify_count > 0:
- details.append('formatting issues in {0} files'.format(uncrustify_count))
- context.mark_unstable(reason='uncrustify.sh found issues', details=details)
- elif ret != 0:
- raise BuildError('uncrustify.sh failed to run')
-
- cmd = ['admin/copyright.sh', 'check', '--rev=HEAD^', '--warnings=' + copyright_log]
- ret = context.run_cmd(cmd, use_return_code=True)
- if ret == 1:
- with open(copyright_log, 'r') as f:
- warnings = f.readlines()
- if len(warnings) <= 5:
- details = [x.rstrip() for x in warnings]
- else:
- cpyear_count = 0
- cpheader_count = 0
- for w in warnings:
- if 'copyright year' in w:
- cpyear_count += 1
- if 'copyright header' in w:
- cpheader_count += 1
- details = []
- if cpyear_count > 0:
- details.append('copyright year missing in {0} files'.format(cpyear_count))
- if cpheader_count > 0:
- details.append('copyright header issues in {0} files'.format(cpheader_count))
- context.mark_unstable(reason='copyright.sh found issues', details=details)
- elif ret != 0:
- raise BuildError('copyright.sh failed to run')
action="check-workdir"
declare -a diffargs
-baserev="HEAD"
+baserev="origin/master"
force=
format_mode=check
warning_file=
if [ -z "$RUN_CLANG_TIDY" ]
then
echo "Please set the path to run-clang-tidy using the git hook"
- echo "git config hooks.runclangtidypath /path/to/run-clang-tidy-8.py"
+ echo "git config hooks.runclangtidypath /path/to/run-clang-tidy-9.py"
echo "or by setting an environment variable, e.g."
- echo "RUN_CLANG_TIDY=/path/to/run-clang-tidy-8.py"
+ echo "RUN_CLANG_TIDY=/path/to/run-clang-tidy-9.py"
exit 2
fi
if ! which "$RUN_CLANG_TIDY" 1>/dev/null
then
- echo "run-clang-tidy-8.py not found: $RUN_CLANG_TIDY"
+ echo "run-clang-tidy-9.py not found: $RUN_CLANG_TIDY"
exit 2
fi
fi
tags[${#tags[@]}]=$tag
python3 $SCRIPT --cmake 3.15.7 --llvm 8 --opencl intel --mpi openmpi | docker build -t $tag -
-tag="gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020"
+tag="gromacs/cmake-3.9.6-llvm-8-amdopencl-openmpi:2020"
tags[${#tags[@]}]=$tag
-python3 $SCRIPT --ubuntu 16.04 --cmake 3.9.6 --llvm 3.6 --opencl amd --mpi openmpi | docker build -t $tag -
+python3 $SCRIPT --cmake 3.9.6 --llvm 8 --opencl amd --mpi openmpi | docker build -t $tag -
-tag=gromacs/ci-docs-llvm:2020
+tag="gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master"
tags[${#tags[@]}]=$tag
-python3 $SCRIPT --llvm --doxygen | docker build -t $tag -
+python3 $SCRIPT --cmake 3.15.7 --gcc 8 --cuda 10.1 --opencl --clfft --mpi openmpi \
+| docker build -t $tag -
-tag=gromacs/ci-docs-gcc:2020
+tag="gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.13.0 --gcc 7 --opencl amd --clfft --mpi openmpi | docker build -t $tag -
+
+tag="gromacs/cmake-3.13.0-llvm-8-tsan:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.13.0 --llvm 8 --tsan | docker build -t $tag -
+
+tag="gromacs/cmake-3.15.7-llvm-8-cuda-10.0-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.15.7 --llvm 8 --cuda 10.0 --mpi openmpi | docker build -t $tag -
+
+tag="gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.15.7 --llvm 8 --cuda 10.1 --mpi openmpi | docker build -t $tag -
+
+tag="gromacs/cmake-3.15.7-llvm-9-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.15.7 --llvm 9 --mpi openmpi | docker build -t $tag -
+
+tag="gromacs/cmake-3.13.0-llvm-9-intelopencl-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.13.0 --llvm 9 --opencl intel --mpi openmpi | docker build -t $tag -
+
+tag="gromacs/cmake-3.13.0-llvm-9-amdopencl-openmpi:master"
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.13.0 --llvm 9 --opencl amd --mpi openmpi | docker build -t $tag -
+
+tag=gromacs/ci-docs-llvm:master
+tags[${#tags[@]}]=$tag
+python3 $SCRIPT --cmake 3.17.2 --llvm --doxygen | docker build -t $tag -
+
+tag=gromacs/ci-docs-gcc:master
tags[${#tags[@]}]=$tag
python3 $SCRIPT --gcc --doxygen | docker build -t $tag -
"""
# TODO: Try using distutils.version.StrictVersion.
-parser.add_argument('--cmake', type=str, default='3.9.6',
- choices=['3.9.6', '3.11.4', '3.15.7'],
+parser.add_argument('--cmake', type=str, default='3.13.0',
+ choices=['3.9.6', '3.11.4', '3.13.0', '3.14.7', '3.15.7', '3.16.6', '3.17.2'],
help='Selection of CMake version to provide to base image')
compiler_group = parser.add_mutually_exclusive_group()
compiler_group.add_argument('--gcc', type=int, nargs='?', const=7, default=7,
help='Select LLVM compiler tool chain. '
'Some checking is implemented to avoid incompatible combinations')
compiler_group.add_argument('--icc', type=int, nargs='?', const=19, default=None,
- choices=[19],
+ choices=[19, 20],
help='Select Intel compiler tool chain. '
'Some checking is implemented to avoid incompatible combinations')
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
action="check-workdir"
declare -a diffargs
-baserev="HEAD"
+baserev="origin/master"
force=
copyright_mode=update
warning_file=
+++ /dev/null
-# Make an image that has the basic dependencies for building GROMACS.
-# This is the same for all other build images and gets used by those.
-
-# Some optional GROMACS dependencies are obtained from the
-# distribution, e.g. fftw3, hwloc, blas and lapack so that the build
-# is as fast as possible.
-FROM ubuntu:18.04
-ENV DEBIAN_FRONTEND=noninteractive
-WORKDIR /tmp
-RUN \
- apt-get update && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- build-essential \
- ccache \
- cmake \
- git \
- libfftw3-dev \
- libhwloc-dev \
- liblapack-dev \
- moreutils \
- ninja-build \
- python3-pip \
- rsync \
- wget \
- xsltproc \
- && \
- rm -rf /var/lib/apt/lists/* && \
- rm -rf /var/cache/apt/archives/*
+++ /dev/null
-#!/bin/bash
-
-export TARGET=$0
-export TARGET_VERSION=$1
-export MATRIX="$TARGET-$TARGET_VERSION"
-export SLUG="ci-$MATRIX"
-
-docker login
-
-tags[0]=gromacs/base:2020
-docker pull ${tags[0]} || true
-docker build -t ${tags[0]} --cache-from ${tags[0]} base
-
-tool=clang
-for tool_version in 6 7 8; do
- MATRIX="$tool-$tool_version"
- SLUG="ci-$MATRIX"
- tag=gromacs/$SLUG:2020
- tags[${#tags[@]}]=$tag
- docker build \
- -t $tag \
- --build-arg TOOL_VERSION=$tool_version \
- ci-$tool
-done
-
-tool=gcc
-for tool_version in 5 6 7 8; do
- MATRIX="$tool-$tool_version"
- SLUG="ci-$MATRIX"
- tag=gromacs/$SLUG:2020
- tags[${#tags[@]}]=$tag
- docker build \
- -t $tag \
- --build-arg TOOL_VERSION=$tool_version \
- ci-$tool
-done
-
-tag=gromacs/ci-docs-clang:2020
-tags[${#tags[@]}]=$tag
-docker build -t $tag \
- ci-docs-clang
-
-tag=gromacs/ci-docs-gcc:2020
-tags[${#tags[@]}]=$tag
-docker build -t $tag \
- ci-docs-gcc
-
-for tag in ${tags[@]}; do
- docker push $tag
-done
+++ /dev/null
-# Make an image that has the dependencies for building GROMACS with clang.
-# Note when specifying TOOL_VERSION that clang 6.0 packages use the minor version
-# in the name, while 7 and 8 do not.
-FROM gromacs/base:2020
-WORKDIR /tmp
-ARG TOOL_VERSION
-RUN \
- apt-get update && \
- apt_version=$TOOL_VERSION && \
- if [ "$TOOL_VERSION" -lt "7" ] ; then apt_version="$apt_version.0"; fi && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- apt-utils \
- software-properties-common \
- gpg-agent && \
- wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
- apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-$apt_version main" && \
- apt-get -qq update && \
- apt-get -qqy --no-install-suggests --no-install-recommends install \
- clang++-$apt_version \
- clang-tools-$apt_version \
- libomp-dev && \
- if [ "$apt_version" != "$TOOL_VERSION" ] ; then \
- ln -s /usr/bin/clang-$apt_version /usr/bin/clang-$TOOL_VERSION; \
- ln -s /usr/bin/clang++-$apt_version /usr/bin/clang++-$TOOL_VERSION; \
- ln -s /usr/bin/clang-format-$apt_version /usr/bin/clang-format-$TOOL_VERSION; \
- ln -s /usr/bin/clang-tidy-$apt_version /usr/bin/clang-tidy-$TOOL_VERSION; fi && \
- rm -rf /var/lib/apt/lists/* && \
- rm -rf /var/cache/apt/archives/*
+++ /dev/null
-# Make an image that has the dependencies for building GROMACS documentation.
-
-# Make an intermediate image that can build a static Doxygen 1.8.5 that other
-# containers will be able to use.
-
-FROM ubuntu:18.04 as doxygen-builder
-ENV DEBIAN_FRONTEND=noninteractive
-WORKDIR /tmp
-RUN \
- apt-get update && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- bison \
- build-essential \
- gcc \
- m4 \
- wget \
- && \
- wget --no-check-certificate https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/flex/2.5.35-10ubuntu3/flex_2.5.35.orig.tar.gz && \
- tar xf flex_2.5.35.orig.tar.gz && \
- cd flex-2.5.35 && \
- ./configure --prefix=/tmp/install-of-flex --disable-shared && \
- make -j && make install && cd .. && rm -rf flex* && \
- wget --no-check-certificate https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/doxygen/1.8.5-1/doxygen_1.8.5.orig.tar.gz && \
- tar xf doxygen_1.8.5.orig.tar.gz && \
- cd doxygen-1.8.5 && \
- ./configure --flex /tmp/install-of-flex/bin/flex --static && \
- make -j && make install && cd .. && rm -rf doxygen* && \
- rm -rf /var/lib/apt/lists/*
-
-# The ImageMagick package from apt has highly secure settings by
-# default, suitable for use behind a webserver, which we don't
-# need. So we use sed to remove those.
-# We also install it separatly because it pulls in some dependencies
-# that are needed for the documentation build.
-
-FROM gromacs/ci-clang-7:2020
-WORKDIR /tmp
-COPY --from=doxygen-builder /usr/local/bin/* /usr/local/bin/
-RUN \
- apt-get update && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- graphviz \
- linkchecker \
- mscgen \
- texlive-latex-base \
- texlive-latex-extra \
- texlive-fonts-recommended \
- texlive-fonts-extra && \
- apt-get -y install imagemagick && \
- rm -rf /var/lib/apt/lists/*
-RUN \
- sed -i \
- '/\"XPS\"/d;/\"PDF\"/d;/\"PS\"/d;/\"EPS\"/d;/disable ghostscript format types/d' \
- /etc/ImageMagick-6/policy.xml && \
- pip3 install sphinx==1.6.1
+++ /dev/null
-# Make an image that has the dependencies for building GROMACS documentation.
-
-# Make an intermediate image that can build a static Doxygen 1.8.5 that other
-# containers will be able to use.
-
-FROM ubuntu:18.04 as doxygen-builder
-ENV DEBIAN_FRONTEND=noninteractive
-WORKDIR /tmp
-RUN \
- apt-get update && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- bison \
- build-essential \
- gcc \
- m4 \
- wget \
- && \
- wget --no-check-certificate https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/flex/2.5.35-10ubuntu3/flex_2.5.35.orig.tar.gz && \
- tar xf flex_2.5.35.orig.tar.gz && \
- cd flex-2.5.35 && \
- ./configure --prefix=/tmp/install-of-flex --disable-shared && \
- make -j && make install && cd .. && rm -rf flex* && \
- wget --no-check-certificate https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/doxygen/1.8.5-1/doxygen_1.8.5.orig.tar.gz && \
- tar xf doxygen_1.8.5.orig.tar.gz && \
- cd doxygen-1.8.5 && \
- ./configure --flex /tmp/install-of-flex/bin/flex --static && \
- make -j && make install && cd .. && rm -rf doxygen* && \
- rm -rf /var/lib/apt/lists/*
-
-# The ImageMagick package from apt has highly secure settings by
-# default, suitable for use behind a webserver, which we don't
-# need. So we use sed to remove those.
-# We also install it separatly because it pulls in some dependencies
-# that are needed for the documentation build.
-
-FROM gromacs/ci-gcc-7:2020
-WORKDIR /tmp
-COPY --from=doxygen-builder /usr/local/bin/* /usr/local/bin/
-RUN \
- apt-get update && \
- apt-get -y -q=2 --no-install-suggests --no-install-recommends install \
- graphviz \
- linkchecker \
- mscgen \
- texlive-latex-base \
- texlive-latex-extra \
- texlive-fonts-recommended \
- texlive-fonts-extra && \
- apt-get -y install imagemagick && \
- rm -rf /var/lib/apt/lists/*
-RUN \
- sed -i \
- '/\"XPS\"/d;/\"PDF\"/d;/\"PS\"/d;/\"EPS\"/d;/disable ghostscript format types/d' \
- /etc/ImageMagick-6/policy.xml && \
- pip3 install sphinx==1.6.1
+++ /dev/null
-# Make an image that has the basic dependencies for building GROMACS.
-# This is the same for all other build images and gets used by those.
-
-# Some optional GROMACS dependencies are obtained from the
-# distribution, e.g. fftw3, hwloc, blas and lapack so that the build
-# is as fast as possible.
-FROM nvidia/cuda:10.2-devel as cuda-ci-basic-dependencies
-ENV DEBIAN_FRONTEND=noninteractive
-WORKDIR /tmp
-RUN \
- apt-get update && \
- apt-get install -y \
- cmake \
- git \
- ninja-build \
- ccache \
- build-essential \
- wget \
- moreutils \
- rsync \
- libfftw3-dev \
- libhwloc-dev \
- liblapack-dev \
- xsltproc \
- python3-pip
-
-# Make an image that has the dependencies for building GROMACS with gcc-8.
-FROM cuda-ci-basic-dependencies as ci-gcc-8-cuda-10.2
-WORKDIR /tmp
-RUN apt-get -qqy --no-install-suggests --no-install-recommends install \
- gcc-8 \
- g++-8 && \
- rm -rf /var/lib/apt/lists/*
+++ /dev/null
-# Make an image that has the dependencies for building GROMACS with gcc.
-
-
-FROM gromacs/base:2020
-WORKDIR /tmp
-ARG TOOL_VERSION
-RUN \
- apt-get update && \
- apt-get -qqy --no-install-suggests --no-install-recommends install \
- gcc-$TOOL_VERSION \
- g++-$TOOL_VERSION && \
- rm -rf /var/lib/apt/lists/* && \
- rm -rf /var/cache/apt/archives/*
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To disable the hook temporarily for a commit, set NO_FORMAT_CHECK environment
# variable. For example,
# NO_FORMAT_CHECK=1 git commit -a
-# You can also run git commit --no-verify, but that also disables other hooks,
-# such as the Change-Id hook used by Gerrit.
+# You can also run git commit --no-verify, but that also disables other hooks.
#
-# See docs/dev-manual/uncrustify.rst for more details.
+# See docs/dev-manual/code-formatting.rst for more details.
if [ ! -z "$NO_FORMAT_CHECK" ]
then
# Redirect output to stderr.
exec 1>&2
-uncrustify_mode=off
+clangtidy_mode=`git config hooks.clangtidymode`
clangformat_mode=`git config hooks.clangformatmode`
copyright_mode=`git config hooks.copyrightmode`
-if [ -z "$uncrustify_mode" ]
+if [ -z "$clangtidy_mode" ]
then
- uncrustify_mode=off
+ clangtidy_mode=off
fi
if [ -z "$clangformat_mode" ]
then
copyright_mode=off
fi
-if [[ -f admin/uncrustify.sh && \
- ( "$uncrustify_mode" != "off" ) ]]
+if [[ -f admin/clang-tidy.sh && \
+ ( "$clangtidy_mode" != "off" ) ]]
then
- uncrustify_path=`git config hooks.uncrustifypath`
- if [ -z "$uncrustify_path" ]
+ runclangtidy_path=`git config hooks.runclangtidypath`
+ if [ -z "$runclangtidy_path" ]
then
- echo "Please set the path to uncrustify using 'git config hooks.uncrustifypath'."
- echo "Note that you need a custom version of uncrustify."
+ echo "Please set the path to run-clang-tidy using 'git config hooks.runclangtidypath'."
+ echo "Note that you need at least clang-tidy-9."
exit 1
fi
- export UNCRUSTIFY="$uncrustify_path"
- admin/uncrustify.sh check-index --rev=$against \
- --uncrustify="$uncrustify_mode"
+ export RUN_CLANG_TIDY="$runclangtidy_path"
+ admin/clang-tidy.sh check-index --rev=$against \
+ --tidy="$clangtidy_mode"
stat=$?
if [ $stat -eq 1 ] ; then
exit 1
elif [ $stat -ne 0 ] ; then
- echo "Source code formatting check with uncrustify failed"
+ echo "Source code checking with clang-tidy failed"
exit 1
fi
fi
KUBERNETES_MEMORY_LIMIT: 2Gi
# Always clone the default version for this branch, master in this case
script:
- - export REGTESTBRANCH=release-2020
+ - export REGTESTBRANCH=master
- if [[ ! -d regressiontests ]] ; then
mkdir regressiontests ;
cd regressiontests ;
- if [[ $GROMACS_RELEASE != "true" ]] ; then
REGTESTNAME=$REGTESTNAME-dev ;
fi
- - export REGTESTBRANCH=release-2020
+ - export REGTESTBRANCH=master
- if [[ $CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_REF_NAME == "release-20"[1-2][0-9] ]] ; then
export REGTESTBRANCH=$CI_COMMIT_REF_NAME ;
fi
- .use-ccache
- .before_script:default
- .docs:build
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
variables:
KUBERNETES_CPU_LIMIT: 4
KUBERNETES_CPU_REQUEST: 2
- .gromacs:base:configure
- .before_script:default
# TODO (#3480) this should be organized more like the current documentation.py script
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
stage: configure-build
cache: {}
variables:
- .before_script:default
- .rules:nightly-only-for-release
# TODO (#3480) this should be organized more like the current documentation.py script
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
stage: release-configure
cache: {}
variables:
.docs:build:
# TODO (#3480) this should be organized more like the current documentation.py script
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
script:
- cd $BUILD_DIR
- cmake --build . --target gmx -- -j8
- .gromacs:base:build
- .before_script:default
# TODO (#3480) this should be organized more like the current documentation.py script
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
cache: {}
variables:
KUBERNETES_CPU_LIMIT: 4
KUBERNETES_MEMORY_LIMIT: 8Gi
KUBERNETES_EXTENDED_RESOURCE_NAME: ""
KUBERNETES_EXTENDED_RESOURCE_LIMIT: 0
- CACHE_FALLBACK_KEY: "$CI_JOB_NAME-$CI_JOB_STAGE-release-2020"
+ CACHE_FALLBACK_KEY: "$CI_JOB_NAME-$CI_JOB_STAGE-master"
BUILD_DIR: build
INSTALL_DIR: install
- CMAKE_GMXAPI_OPTIONS: "-DGMX_PYTHON_PACKAGE=OFF"
-# TODO: Get these from updated Docker images.
+ CMAKE_GMXAPI_OPTIONS: ""
# Our generic before_script to install dependencies and prepare the ccache directory.
.before_script:default:
extends:
- .variables:default
- .use-ccache
- - .use-gcc:base
+ - .use-clang:base
- .rules:basic-push
stage: pre-build
- image: gromacs/cmake-3.9.6-gcc-5-cuda-9.0-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
tags: []
variables:
KUBERNETES_CPU_LIMIT: 8
CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug"
CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF"
CMAKE_GMXAPI_OPTIONS: "-DGMX_PYTHON_PACKAGE=OFF"
- COMPILER_MAJOR_VERSION: 5
+ COMPILER_MAJOR_VERSION: 9
BUILD_DIR: simple-build
script:
- echo $CMAKE_COMPILER_SCRIPT
extends:
- .gromacs:base:configure
- .use-gcc:base
+ - .use-opencl
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=AVX2_256"
- CMAKE_GPU_OPTIONS: "-DGMX_GPU=ON -DGMX_USE_OPENCL=ON"
+ CMAKE_EXTRA_OPTIONS: "-DGMX_EXTERNAL_CLFFT=ON"
COMPILER_MAJOR_VERSION: 7
-gromacs:gcc-6:configure:
+gromacs:gcc-8-cuda-10.1:configure:
extends:
- .gromacs:base:configure
- .use-gcc:base
- - .use-opencl
+ - .use-cuda
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
variables:
CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=SSE4.1"
- COMPILER_MAJOR_VERSION: 6
- CMAKE_EXTRA_OPTIONS: "-DGMX_EXTERNAL_CLFFT=ON"
+ COMPILER_MAJOR_VERSION: 8
gromacs:clang-TSAN:configure:
extends:
- .gromacs:base:configure
- .use-clang:base
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
variables:
COMPILER_MAJOR_VERSION: 8
CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=TSAN"
variables:
COMPILER_MAJOR_VERSION: 8
-gromacs:clang-3.6:configure:
+gromacs:clang-9:configure:
extends:
- - .gromacs:base:configure
- - .use-clang:base
- - .use-mpi
- - .rules:merge-requests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ - .gromacs:base:configure
+ - .use-clang:base
+ - .use-mpi
+ - .rules:merge-requests
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
variables:
- COMPILER_MAJOR_VERSION: "3.6"
- CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=ON"
- CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=SSE4.1"
- CMAKE_EXTRA_OPTIONS: "-DGMX_OPENMP=OFF"
+ COMPILER_MAJOR_VERSION: 9
+ CMAKE_PRECISION_OPTIONS: -DGMX_DOUBLE=ON
gromacs:clang-static-analyzer:configure:
extends:
- .gromacs:base:configure
- .use-clang:base
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
variables:
CMAKE_COMPILER_SCRIPT: "-DCMAKE_CXX_COMPILER=/usr/local/libexec/c++-analyzer -DCMAKE_C_COMPILER=gcc"
CMAKE_EXTRA_OPTIONS: "-DGMX_CLANG_ANALYZER=ON -DGMX_OPENMP=OFF -DGMX_USE_RDTSCP=OFF -DGMX_FFT_LIBRARY=fftpack -DGMX_DEVELOPER_BUILD=ON"
- .gromacs:base:configure
- .use-clang:base
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
variables:
COMPILER_MAJOR_VERSION: 8
CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=ASAN"
-gromacs:gcc-6:release:configure:
+gromacs:gcc-8-cuda-10.1:release:configure:
extends:
- .gromacs:base:release:configure
- .use-gcc:base
+ - .use-mpi
- .use-cuda
- .rules:nightly-only-for-release
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
variables:
- COMPILER_MAJOR_VERSION: 6
+ COMPILER_MAJOR_VERSION: 8
RELEASE_BUILD_DIR: release-builds-gcc
CMAKE_EXTRA_OPTIONS: "-DGMX_BUILD_MDRUN_ONLY=ON"
CMAKE_BUILD_TYPE_OPTIONS : "-DCMAKE_BUILD_TYPE=RelWithDebug"
- .gromacs:base:release:configure
- .use-gcc:base
- .rules:nightly-only-for-release
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
COMPILER_MAJOR_VERSION: 7
RELEASE_BUILD_DIR: release-builds-gcc
- regressiontests:package
- prepare-release-version
-gromacs:clang-3.6:release:configure:
+gromacs:clang-9:release:configure:
extends:
- .gromacs:base:release:configure
- .use-clang:base
- .use-mpi
- .rules:nightly-only-for-release
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
variables:
- COMPILER_MAJOR_VERSION: "3.6"
+ COMPILER_MAJOR_VERSION: 9
RELEASE_BUILD_DIR: release-builds-clang
CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=ON"
- CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=SSE4.1"
CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithAssert"
- CMAKE_EXTRA_OPTIONS: "-DGMX_OPENMP=OFF"
dependencies:
- archive:package
- regressiontests:package
- prepare-release-version
-gromacs:clang-8:release:configure:
+gromacs:clang-8-cuda-10.1:release:configure:
extends:
- .gromacs:base:release:configure
- .use-clang:base
- .use-cuda
- .rules:nightly-only-for-release
- image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:master
variables:
COMPILER_MAJOR_VERSION: 8
RELEASE_BUILD_DIR: release-builds-clang
- .before_script:default
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
needs:
- job: gromacs:gcc-7:configure
artifacts: true
-gromacs:gcc-6:build:
+gromacs:gcc-8-cuda-10.1:build:
extends:
- .variables:default
- .gromacs:base:build
- .before_script:default
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
needs:
- - job: gromacs:gcc-6:configure
+ - job: gromacs:gcc-8-cuda-10.1:configure
gromacs:clang-TSAN:build:
extends:
- .use-clang:base
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-TSAN:configure
- .use-clang:base
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-ASAN:configure
- .use-clang:base
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-static-analyzer:configure
needs:
- job: gromacs:clang-8:configure
-gromacs:clang-3.6:build:
+gromacs:clang-9:build:
extends:
- .variables:default
- .gromacs:base:build
- .before_script:default
- .use-ccache
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
needs:
- - job: gromacs:clang-3.6:configure
+ - job: gromacs:clang-9:configure
-gromacs:gcc-6:release:build:
+gromacs:gcc-8-cuda-10.1:release:build:
extends:
- .variables:default
- .gromacs:base:build
stage: release-build
variables:
BUILD_DIR: release-builds-gcc
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
needs:
- - job: gromacs:gcc-6:release:configure
+ - job: gromacs:gcc-8-cuda-10.1:release:configure
gromacs:gcc-7:release:build:
extends:
stage: release-build
variables:
BUILD_DIR: release-builds-gcc
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
needs:
- job: gromacs:gcc-7:release:configure
-gromacs:clang-3.6:release:build:
+gromacs:clang-9:release:build:
extends:
- .variables:default
- .gromacs:base:build
stage: release-build
variables:
BUILD_DIR: release-builds-clang
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
needs:
- - job: gromacs:clang-3.6:release:configure
+ - job: gromacs:clang-9:release:configure
-gromacs:clang-8:release:build:
+gromacs:clang-8-cuda-10.1:release:build:
extends:
- .variables:default
- .gromacs:base:build
stage: release-build
variables:
BUILD_DIR: release-builds-clang
- image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:master
needs:
- - job: gromacs:clang-8:release:configure
+ - job: gromacs:clang-8-cuda-10.1:release:configure
# Jobs running during test stage
extends:
- .gromacs:base:test
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
KUBERNETES_EXTENDED_RESOURCE_NAME: "amd.com/gpu"
KUBERNETES_EXTENDED_RESOURCE_LIMIT: 1
needs:
- job: gromacs:gcc-7:build
-gromacs:gcc-6:test:
+gromacs:gcc-8-cuda-10.1:test:
extends:
- .gromacs:base:test
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
variables:
KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
KUBERNETES_EXTENDED_RESOURCE_LIMIT: 1
needs:
- - job: gromacs:gcc-6:build
+ - job: gromacs:gcc-8-cuda-10.1:build
gromacs:clang-8:test:
extends:
extends:
- .gromacs:base:test
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-TSAN:build
- .gromacs:base:test
- .use-clang:base
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
variables:
CTEST_RUN_MODE: "ExperimentalMemCheck"
needs:
- job: gromacs:clang-ASAN:build
-gromacs:clang-3.6:test:
+gromacs:clang-9:test:
extends:
- .gromacs:base:test
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
needs:
- - job: gromacs:clang-3.6:build
+ - job: gromacs:clang-9:build
gromacs:gcc-7:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
KUBERNETES_EXTENDED_RESOURCE_NAME: "amd.com/gpu"
KUBERNETES_EXTENDED_RESOURCE_LIMIT: 1
- job: gromacs:gcc-7:build
- job: regressiontests:prepare
-gromacs:gcc-6:regressiontest:
+gromacs:gcc-8-cuda-10.1:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
variables:
KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
KUBERNETES_EXTENDED_RESOURCE_LIMIT: 1
REGRESSIONTEST_TOTAL_RANK_NUMBER: 2
REGRESSIONTEST_OMP_RANK_NUMBER: 1
needs:
- - job: gromacs:gcc-6:build
+ - job: gromacs:gcc-8-cuda-10.1:build
- job: regressiontests:prepare
gromacs:clang-8:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-TSAN:build
- job: regressiontests:prepare
- .gromacs:base:regressiontest
- .use-clang:base
- .rules:merge-requests
- image: gromacs/cmake-3.15.7-llvm-8-tsan:2020
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
needs:
- job: gromacs:clang-ASAN:build
- job: regressiontests:prepare
-gromacs:clang-3.6:regressiontest:
+gromacs:clang-9:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:merge-requests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
variables:
REGRESSIONTEST_DOUBLE: "-double"
- REGRESSIONTEST_OMP_RANK_NUMBER: 0
REGRESSIONTEST_PARALLEL: "-np"
needs:
- - job: gromacs:clang-3.6:build
+ - job: gromacs:clang-9:build
- job: regressiontests:prepare
-gromacs:gcc-6:release:test:
+gromacs:gcc-8-cuda-10.1:release:test:
extends:
- .gromacs:base:test
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.9.6-gcc-6-cuda-10.1-nvidiaopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.15.7-gcc-8-cuda-10.1-nvidiaopencl-clfft-openmpi:master
variables:
BUILD_DIR: release-builds-gcc
needs:
- - job: gromacs:gcc-6:release:configure
- - job: gromacs:gcc-6:release:build
+ - job: gromacs:gcc-8-cuda-10.1:release:configure
+ - job: gromacs:gcc-8-cuda-10.1:release:build
gromacs:gcc-7:release:test:
extends:
- .gromacs:base:test
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
BUILD_DIR: release-builds-gcc
needs:
- job: gromacs:gcc-7:release:configure
- job: gromacs:gcc-7:release:build
-gromacs:clang-3.6:release:test:
+gromacs:clang-9:release:test:
extends:
- .gromacs:base:test
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
variables:
BUILD_DIR: release-builds-clang
needs:
- - job: gromacs:clang-3.6:release:configure
- - job: gromacs:clang-3.6:release:build
+ - job: gromacs:clang-9:release:configure
+ - job: gromacs:clang-9:release:build
-gromacs:clang-8:release:test:
+gromacs:clang-8-cuda-10.1:release:test:
extends:
- .gromacs:base:test
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:master
variables:
BUILD_DIR: release-builds-clang
needs:
- - job: gromacs:clang-8:release:configure
- - job: gromacs:clang-8:release:build
+ - job: gromacs:clang-8-cuda-10.1:release:configure
+ - job: gromacs:clang-8-cuda-10.1:release:build
gromacs:gcc-7:release:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.9.6-gcc-7-amdopencl-clfft-openmpi:2020
+ image: gromacs/cmake-3.13.0-gcc-7-amdopencl-clfft-openmpi:master
variables:
BUILD_DIR: release-builds-gcc
needs:
- job: gromacs:gcc-7:release:build
- job: regressiontests:package
-gromacs:clang-3.6:release:regressiontest:
+gromacs:clang-9:release:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.9.6-llvm-3.6-amdopencl-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
variables:
BUILD_DIR: release-builds-clang
REGRESSIONTEST_DOUBLE: "-double"
- REGRESSIONTEST_OMP_RANK_NUMBER: 0
REGRESSIONTEST_PARALLEL: "-np"
needs:
- - job: gromacs:clang-3.6:release:build
+ - job: gromacs:clang-9:release:build
- job: regressiontests:package
-gromacs:clang-8:release:regressiontest:
+gromacs:clang-8-cuda-10.1:release:regressiontest:
extends:
- .gromacs:base:regressiontest
- .rules:nightly-only-for-release
stage: release-tests
- image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi:master
variables:
BUILD_DIR: release-builds-clang
KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
REGRESSIONTEST_OMP_RANK_NUMBER: 1
needs:
- - job: gromacs:clang-8:release:build
+ - job: gromacs:clang-8-cuda-10.1:release:build
- job: regressiontests:package
- .gromacs:base:configure
- .use-clang:base
- .rules:basic-push
- image: gromacs/cmake-3.11.4-llvm-8-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
tags: []
variables:
- COMPILER_MAJOR_VERSION: 8
+ COMPILER_MAJOR_VERSION: 9
BUILD_DIR: build-clang-tidy
CMAKE_EXTRA_OPTIONS: -DCLANG_TIDY=clang-tidy-$COMPILER_MAJOR_VERSION -DGMX_CLANG_TIDY=ON -DGMX_COMPILER_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
- .gromacs:base:configure
- .use-clang:base
- .rules:nightly-not-for-release
- image: gromacs/cmake-3.11.4-llvm-8-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
tags: []
variables:
- COMPILER_MAJOR_VERSION: 8
+ COMPILER_MAJOR_VERSION: 9
BUILD_DIR: build-clang-tidy
CMAKE_EXTRA_OPTIONS: -DCLANG_TIDY=clang-tidy-$COMPILER_MAJOR_VERSION -DGMX_CLANG_TIDY=ON -DGMX_COMPILER_WARNINGS=ON
- .variables:default
- .rules:nightly-not-for-release
stage: source-check
- image: gromacs/cmake-3.11.4-llvm-8-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
needs:
- job: clang-tidy:configure-schedule
variables:
- .variables:default
- .rules:basic-push
stage: source-check
- image: gromacs/cmake-3.11.4-llvm-8-openmpi:2020
+ image: gromacs/cmake-3.15.7-llvm-9-openmpi:master
tags: []
needs:
- job: clang-tidy:configure-push
variables:
- COMPILER_MAJOR_VERSION: 8
+ COMPILER_MAJOR_VERSION: 9
BUILD_DIR: build-clang-tidy
EXTRA_INSTALLS: clang-tidy-$COMPILER_MAJOR_VERSION
KUBERNETES_CPU_LIMIT: 4
KUBERNETES_CPU_REQUEST: 2
KUBERNETES_MEMORY_LIMIT: 4Gi
script:
- - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git release-2020 && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
+ # TODO (issue #3272) `master` is not appropriate for use on release-xxxx branches, how should we handle that?
+ - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git master && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
- HEAD_REV=$(git show -s --pretty=format:"%h" HEAD)
- if [[ "$REV" == "$HEAD_REV" ]] ; then
REV="HEAD~1" ;
- .rules:basic-push
cache: {}
stage: pre-build
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
tags: []
variables:
COMPILER_MAJOR_VERSION: 7
KUBERNETES_MEMORY_LIMIT: 2Gi
EXTRA_INSTALLS: clang-format-$COMPILER_MAJOR_VERSION
script:
- - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git release-2020 && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
+ # TODO (issue #3272) `master` is not appropriate for use on release-xxxx branches, how should we handle that?
+ - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git master && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
- HEAD_REV=$(git show -s --pretty=format:"%h" HEAD)
- if [[ "$REV" == "$HEAD_REV" ]] ; then
REV="HEAD~1" ;
- .rules:basic-push
cache: {}
stage: pre-build
- image: gromacs/ci-docs-llvm:2020
+ image: gromacs/ci-docs-llvm:master
tags: []
variables:
KUBERNETES_CPU_LIMIT: 1
KUBERNETES_CPU_REQUEST: 1
KUBERNETES_MEMORY_LIMIT: 2Gi
script:
- - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git release-2020 && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
+ # TODO (issue #3272) `master` is not appropriate for use on release-xxxx branches, how should we handle that?
+ - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git master && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
- HEAD_REV=$(git show -s --pretty=format:"%h" HEAD)
- if [[ "$REV" == "$HEAD_REV" ]] ; then
REV="HEAD~1" ;
+#!/bin/bash
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016, by the GROMACS development team, led by
+# Copyright (c) 2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-import json
-
-extra_options = {
- 'md5sum': Option.string
-}
-
-def do_build(context):
- info_path = 'cmake/gmxVersionInfo.cmake'
- cmd = [context.env.cmake_command, '-P', info_path]
- info_json = context.run_cmd(cmd, use_output=True)
- values = json.loads(info_json)
- old_md5sum = values['regressiontest-md5sum']
- new_md5sum = context.opts.md5sum
- if new_md5sum != old_md5sum:
- context.replace_in_file(info_path, r'set\(REGRESSIONTEST_MD5SUM "(\w*)"',
- lambda x: do_replacement(x, new_md5sum))
- context.workspace.upload_revision(project=Project.GROMACS, file_glob=info_path)
+# Finds copyright statements that have more than five years, such as
+#
+# ... Copyright (c) 2012,2013,2016,2017,2018,2019, by the GROMACS ...
+#
+# and splits them into multiple lines, like
+#
+# ... Copyright (c) 2012,2013,2016,2017,2018, by the GROMACS development team.
+# ... Copyright (c) 2019, by the GROMACS development team, led by
+#
+# so that the copyright checker recognizes the second line as one that can be extended.
+# This will need to be re-rerun every few years as the length of the last line grows.
-def do_replacement(match, new_md5sum):
- result = match.group(0)
- start = match.start(1) - match.start(0)
- end = match.end(1) - match.end(0)
- return result[:start] + new_md5sum + result[end:]
+sed -i 's/\( \?.\) Copyright (c) \([0-9][0-9][0-9][0-9],[0-9][0-9][0-9][0-9],[0-9][0-9][0-9][0-9],[0-9][0-9][0-9][0-9],[0-9][0-9][0-9][0-9]\),\([0-9][0-9][0-9][0-9],.*,\) by the GROMACS/\1 Copyright (c) \2 by the GROMACS development team.\n\1 Copyright (c) \3 by the GROMACS/g' $(git grep -l "by the GROMACS")
+++ /dev/null
-# Uncrustify 0.59
-
-#
-# General options
-#
-
-# The type of line endings
-newlines = auto # auto/lf/crlf/cr
-
-# The original size of tabs in the input
-input_tab_size = 4 # number
-
-# The size of tabs in the output (only used if align_with_tabs=true)
-output_tab_size = 4 # number
-
-# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn)
-string_escape_char = 92 # number
-
-# Alternate string escape char for Pawn. Only works right before the quote char.
-string_escape_char2 = 0 # number
-
-# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list<list<B>>=val);'.
-# If true (default), 'assert(x<0 && y>=3)' will be broken.
-# Improvements to template detection may make this option obsolete.
-tok_split_gte = false # false/true
-
-# Control what to do with the UTF-8 BOM (recommend 'remove')
-utf8_bom = ignore # ignore/add/remove/force
-
-# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8
-utf8_byte = false # false/true
-
-# Force the output encoding to UTF-8
-utf8_force = false # false/true
-
-#
-# Indenting
-#
-
-# The number of columns to indent per level.
-# Usually 2, 3, 4, or 8.
-indent_columns = 4 # number
-
-# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents.
-# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level
-indent_continue = 0 # number
-
-# How to use tabs when indenting code
-# 0=spaces only
-# 1=indent with tabs to brace level, align with spaces
-# 2=indent and align with tabs, using spaces when not on a tabstop
-indent_with_tabs = 0 # number
-
-# Comments that are not a brace level are indented with tabs on a tabstop.
-# Requires indent_with_tabs=2. If false, will use spaces.
-indent_cmt_with_tabs = false # false/true
-
-# Whether to indent strings broken by '\' so that they line up
-indent_align_string = false # false/true
-
-# The number of spaces to indent multi-line XML strings.
-# Requires indent_align_string=True
-indent_xml_string = 0 # number
-
-# Spaces to indent '{' from level
-indent_brace = 0 # number
-
-# Whether braces are indented to the body level
-indent_braces = false # false/true
-
-# Disabled indenting function braces if indent_braces is true
-indent_braces_no_func = true # false/true
-
-# Disabled indenting class braces if indent_braces is true
-indent_braces_no_class = true # false/true
-
-# Disabled indenting struct braces if indent_braces is true
-indent_braces_no_struct = true # false/true
-
-# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.
-indent_brace_parent = false # false/true
-
-# Whether the 'namespace' body is indented
-indent_namespace = false # false/true
-
-# The number of spaces to indent a namespace block
-indent_namespace_level = 0 # number
-
-# If the body of the namespace is longer than this number, it won't be indented.
-# Requires indent_namespace=true. Default=0 (no limit)
-indent_namespace_limit = 0 # number
-
-# Whether the 'extern "C"' body is indented
-indent_extern = false # false/true
-
-# Whether the 'class' body is indented
-indent_class = false # false/true
-
-# Whether to indent the stuff after a leading class colon
-indent_class_colon = true # false/true
-
-# Virtual indent from the ':' for member initializers. Default is 2
-indent_ctor_init_leading = 2 # number
-
-# Additional indenting for constructor initializer list
-indent_ctor_init = 0 # number
-
-# False=treat 'else\nif' as 'else if' for indenting purposes
-# True=indent the 'if' one level
-indent_else_if = false # false/true
-
-# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute
-indent_var_def_blk = 0 # number
-
-# Indent continued variable declarations instead of aligning.
-indent_var_def_cont = false # false/true
-
-# True: force indentation of function definition to start in column 1
-# False: use the default behavior
-indent_func_def_force_col1 = false # false/true
-
-# True: indent continued function call parameters one indent level
-# False: align parameters under the open paren
-indent_func_call_param = false # false/true
-
-# Same as indent_func_call_param, but for function defs
-indent_func_def_param = false # false/true
-
-# Same as indent_func_call_param, but for function protos
-indent_func_proto_param = false # false/true
-
-# Same as indent_func_call_param, but for class declarations
-indent_func_class_param = false # false/true
-
-# Same as indent_func_call_param, but for class variable constructors
-indent_func_ctor_var_param = false # false/true
-
-# Same as indent_func_call_param, but for templates
-indent_template_param = false # false/true
-
-# Double the indent for indent_func_xxx_param options
-indent_func_param_double = true # false/true
-
-# Indentation column for standalone 'const' function decl/proto qualifier
-indent_func_const = 0 # number
-
-# Indentation column for standalone 'throw' function decl/proto qualifier
-indent_func_throw = 0 # number
-
-# The number of spaces to indent a continued '->' or '.'
-# Usually set to 0, 1, or indent_columns.
-indent_member = 4 # number
-
-# Spaces to indent single line ('//') comments on lines before code
-indent_sing_line_comments = 0 # number
-
-# If set, will indent trailing single line ('//') comments relative
-# to the code instead of trying to keep the same absolute column
-indent_relative_single_line_comments = false # false/true
-
-# Spaces to indent 'case' from 'switch'
-# Usually 0 or indent_columns.
-indent_switch_case = 4 # number
-
-# Spaces to shift the 'case' line, without affecting any other lines
-# Usually 0.
-indent_case_shift = 0 # number
-
-# Spaces to indent '{' from 'case'.
-# By default, the brace will appear under the 'c' in case.
-# Usually set to 0 or indent_columns.
-indent_case_brace = 0 # number
-
-# Whether to indent comments found in first column
-indent_col1_comment = false # false/true
-
-# How to indent goto labels
-# >0 : absolute column where 1 is the leftmost column
-# <=0 : subtract from brace indent
-indent_label = 1 # number
-
-# Same as indent_label, but for access specifiers that are followed by a colon
-indent_access_spec = 1 # number
-
-# Indent the code after an access specifier by one level.
-# If set, this option forces 'indent_access_spec=0'
-indent_access_spec_body = true # false/true
-
-# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)
-indent_paren_nl = false # false/true
-
-# Controls the indent of a close paren after a newline.
-# 0: Indent to body level
-# 1: Align under the open paren
-# 2: Indent to the brace level
-indent_paren_close = 0 # number
-
-# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren
-indent_comma_paren = false # false/true
-
-# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren
-indent_bool_paren = false # false/true
-
-# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones
-indent_first_bool_expr = false # false/true
-
-# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)
-indent_square_nl = false # false/true
-
-# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies
-indent_preserve_sql = false # false/true
-
-# Align continued statements at the '='. Default=True
-# If FALSE or the '=' is followed by a newline, the next line is indent one tab.
-indent_align_assign = false # false/true
-
-# Indent OC blocks at brace level instead of usual rules.
-indent_oc_block = false # false/true
-
-# Minimum indent for subsequent parameters
-indent_oc_msg_colon = 0 # number
-
-#
-# Spacing options
-#
-
-# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
-sp_arith = add # ignore/add/remove/force
-
-# Add or remove space around assignment operator '=', '+=', etc
-sp_assign = add # ignore/add/remove/force
-
-# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign
-sp_cpp_lambda_assign = ignore # ignore/add/remove/force
-
-# Add or remove space after the capture specification in C++11 lambda.
-sp_cpp_lambda_paren = ignore # ignore/add/remove/force
-
-# Add or remove space around assignment operator '=' in a prototype
-sp_assign_default = add # ignore/add/remove/force
-
-# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign.
-sp_before_assign = add # ignore/add/remove/force
-
-# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign.
-sp_after_assign = add # ignore/add/remove/force
-
-# Add or remove space around assignment '=' in enum
-sp_enum_assign = add # ignore/add/remove/force
-
-# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign.
-sp_enum_before_assign = ignore # ignore/add/remove/force
-
-# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign.
-sp_enum_after_assign = ignore # ignore/add/remove/force
-
-# Add or remove space around preprocessor '##' concatenation operator. Default=Add
-sp_pp_concat = add # ignore/add/remove/force
-
-# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator.
-sp_pp_stringify = ignore # ignore/add/remove/force
-
-# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'.
-sp_before_pp_stringify = ignore # ignore/add/remove/force
-
-# Add or remove space around boolean operators '&&' and '||'
-sp_bool = add # ignore/add/remove/force
-
-# Add or remove space around compare operator '<', '>', '==', etc
-sp_compare = add # ignore/add/remove/force
-
-# Add or remove space inside '(' and ')'
-sp_inside_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between nested parens
-sp_paren_paren = ignore # ignore/add/remove/force
-
-# Whether to balance spaces inside nested parens
-sp_balance_nested_parens = false # false/true
-
-# Add or remove space between ')' and '{'
-sp_paren_brace = ignore # ignore/add/remove/force
-
-# Add or remove space before pointer star '*'
-sp_before_ptr_star = ignore # ignore/add/remove/force
-
-# Add or remove space before pointer star '*' that isn't followed by a variable name
-# If set to 'ignore', sp_before_ptr_star is used instead.
-sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force
-
-# Add or remove space between pointer stars '*'
-sp_between_ptr_star = ignore # ignore/add/remove/force
-
-# Add or remove space after pointer star '*', if followed by a word.
-sp_after_ptr_star = ignore # ignore/add/remove/force
-
-# Add or remove space after a pointer star '*', if followed by a func proto/def.
-sp_after_ptr_star_func = ignore # ignore/add/remove/force
-
-# Add or remove space after a pointer star '*', if followed by an open paren (function types).
-sp_ptr_star_paren = ignore # ignore/add/remove/force
-
-# Add or remove space before a pointer star '*', if followed by a func proto/def.
-sp_before_ptr_star_func = ignore # ignore/add/remove/force
-
-# Add or remove space before a reference sign '&'
-sp_before_byref = add # ignore/add/remove/force
-
-# Add or remove space before a reference sign '&' that isn't followed by a variable name
-# If set to 'ignore', sp_before_byref is used instead.
-sp_before_unnamed_byref = ignore # ignore/add/remove/force
-
-# Add or remove space after reference sign '&', if followed by a word.
-sp_after_byref = ignore # ignore/add/remove/force
-
-# Add or remove space after a reference sign '&', if followed by a func proto/def.
-sp_after_byref_func = ignore # ignore/add/remove/force
-
-# Add or remove space before a reference sign '&', if followed by a func proto/def.
-sp_before_byref_func = ignore # ignore/add/remove/force
-
-# Add or remove space between type and word. Default=Force
-sp_after_type = ignore # ignore/add/remove/force
-
-# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('.
-sp_before_template_paren = ignore # ignore/add/remove/force
-
-# Add or remove space in 'template <' vs 'template<'.
-# If set to ignore, sp_before_angle is used.
-sp_template_angle = add # ignore/add/remove/force
-
-# Add or remove space before '<>'
-sp_before_angle = ignore # ignore/add/remove/force
-
-# Add or remove space inside '<' and '>'
-sp_inside_angle = ignore # ignore/add/remove/force
-
-# Add or remove space after '<>'
-sp_after_angle = ignore # ignore/add/remove/force
-
-# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
-sp_angle_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between '<>' and a word as in 'List<byte> m;'
-sp_angle_word = ignore # ignore/add/remove/force
-
-# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add
-sp_angle_shift = add # ignore/add/remove/force
-
-# Permit removal of the space between '>>' in 'foo<bar<int> >' (C++11 only). Default=False
-# sp_angle_shift cannot remove the space without this option.
-sp_permit_cpp11_shift = false # false/true
-
-# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
-sp_before_sparen = add # ignore/add/remove/force
-
-# Add or remove space inside if-condition '(' and ')'
-sp_inside_sparen = remove # ignore/add/remove/force
-
-# Add or remove space before if-condition ')'. Overrides sp_inside_sparen.
-sp_inside_sparen_close = ignore # ignore/add/remove/force
-
-# Add or remove space before if-condition '('. Overrides sp_inside_sparen.
-sp_inside_sparen_open = ignore # ignore/add/remove/force
-
-# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
-sp_after_sparen = ignore # ignore/add/remove/force
-
-# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
-sp_sparen_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between 'invariant' and '(' in the D language.
-sp_invariant_paren = ignore # ignore/add/remove/force
-
-# Add or remove space after the ')' in 'invariant (C) c' in the D language.
-sp_after_invariant_paren = ignore # ignore/add/remove/force
-
-# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
-sp_special_semi = ignore # ignore/add/remove/force
-
-# Add or remove space before ';'. Default=Remove
-sp_before_semi = remove # ignore/add/remove/force
-
-# Add or remove space before ';' in non-empty 'for' statements
-sp_before_semi_for = ignore # ignore/add/remove/force
-
-# Add or remove space before a semicolon of an empty part of a for statement.
-sp_before_semi_for_empty = ignore # ignore/add/remove/force
-
-# Add or remove space after ';', except when followed by a comment. Default=Add
-sp_after_semi = add # ignore/add/remove/force
-
-# Add or remove space after ';' in non-empty 'for' statements. Default=Force
-sp_after_semi_for = force # ignore/add/remove/force
-
-# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; <here> ).
-sp_after_semi_for_empty = ignore # ignore/add/remove/force
-
-# Add or remove space before '[' (except '[]')
-sp_before_square = ignore # ignore/add/remove/force
-
-# Add or remove space before '[]'
-sp_before_squares = ignore # ignore/add/remove/force
-
-# Add or remove space inside a non-empty '[' and ']'
-sp_inside_square = ignore # ignore/add/remove/force
-
-# Add or remove space after ','
-sp_after_comma = add # ignore/add/remove/force
-
-# Add or remove space before ','
-sp_before_comma = remove # ignore/add/remove/force
-
-# Add or remove space between an open paren and comma: '(,' vs '( ,'
-sp_paren_comma = force # ignore/add/remove/force
-
-# Add or remove space before the variadic '...' when preceded by a non-punctuator
-sp_before_ellipsis = ignore # ignore/add/remove/force
-
-# Add or remove space after class ':'
-sp_after_class_colon = add # ignore/add/remove/force
-
-# Add or remove space before class ':'
-sp_before_class_colon = add # ignore/add/remove/force
-
-# Add or remove space before case ':'. Default=Remove
-sp_before_case_colon = remove # ignore/add/remove/force
-
-# Add or remove space between 'operator' and operator sign
-sp_after_operator = remove # ignore/add/remove/force
-
-# Add or remove space between the operator symbol and the open paren, as in 'operator ++('
-sp_after_operator_sym = ignore # ignore/add/remove/force
-
-# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'
-sp_after_cast = ignore # ignore/add/remove/force
-
-# Add or remove spaces inside cast parens
-sp_inside_paren_cast = ignore # ignore/add/remove/force
-
-# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'
-sp_cpp_cast_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'sizeof' and '('
-sp_sizeof_paren = ignore # ignore/add/remove/force
-
-# Add or remove space after the tag keyword (Pawn)
-sp_after_tag = ignore # ignore/add/remove/force
-
-# Add or remove space inside enum '{' and '}'
-sp_inside_braces_enum = ignore # ignore/add/remove/force
-
-# Add or remove space inside struct/union '{' and '}'
-sp_inside_braces_struct = ignore # ignore/add/remove/force
-
-# Add or remove space inside '{' and '}'
-sp_inside_braces = ignore # ignore/add/remove/force
-
-# Add or remove space inside '{}'
-sp_inside_braces_empty = ignore # ignore/add/remove/force
-
-# Add or remove space between return type and function name
-# A minimum of 1 is forced except for pointer return types.
-sp_type_func = ignore # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function declaration
-sp_func_proto_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function definition
-sp_func_def_paren = ignore # ignore/add/remove/force
-
-# Add or remove space inside empty function '()'
-sp_inside_fparens = ignore # ignore/add/remove/force
-
-# Add or remove space inside function '(' and ')'
-sp_inside_fparen = ignore # ignore/add/remove/force
-
-# Add or remove space inside the first parens in the function type: 'void (*x)(...)'
-sp_inside_tparen = ignore # ignore/add/remove/force
-
-# Add or remove between the parens in the function type: 'void (*x)(...)'
-sp_after_tparen_close = ignore # ignore/add/remove/force
-
-# Add or remove space between ']' and '(' when part of a function call.
-sp_square_fparen = ignore # ignore/add/remove/force
-
-# Add or remove space between ')' and '{' of function
-sp_fparen_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function calls
-sp_func_call_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between function name and '()' on function calls without parameters.
-# If set to 'ignore' (the default), sp_func_call_paren is used.
-sp_func_call_paren_empty = ignore # ignore/add/remove/force
-
-# Add or remove space between the user function name and '(' on function calls
-# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file.
-sp_func_call_user_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between a constructor/destructor and the open paren
-sp_func_class_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'return' and '('
-sp_return_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between '__attribute__' and '('
-sp_attribute_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'defined' and '(' in '#if defined (FOO)'
-sp_defined_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'throw' and '(' in 'throw (something)'
-sp_throw_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];'
-sp_after_throw = ignore # ignore/add/remove/force
-
-# Add or remove space between 'catch' and '(' in 'catch (something) { }'
-# If set to ignore, sp_before_sparen is used.
-sp_catch_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'version' and '(' in 'version (something) { }' (D language)
-# If set to ignore, sp_before_sparen is used.
-sp_version_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language)
-# If set to ignore, sp_before_sparen is used.
-sp_scope_paren = ignore # ignore/add/remove/force
-
-# Add or remove space between macro and value
-sp_macro = ignore # ignore/add/remove/force
-
-# Add or remove space between macro function ')' and value
-sp_macro_func = ignore # ignore/add/remove/force
-
-# Add or remove space between 'else' and '{' if on the same line
-sp_else_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between '}' and 'else' if on the same line
-sp_brace_else = ignore # ignore/add/remove/force
-
-# Add or remove space between '}' and the name of a typedef on the same line
-sp_brace_typedef = ignore # ignore/add/remove/force
-
-# Add or remove space between 'catch' and '{' if on the same line
-sp_catch_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between '}' and 'catch' if on the same line
-sp_brace_catch = ignore # ignore/add/remove/force
-
-# Add or remove space between 'finally' and '{' if on the same line
-sp_finally_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between '}' and 'finally' if on the same line
-sp_brace_finally = ignore # ignore/add/remove/force
-
-# Add or remove space between 'try' and '{' if on the same line
-sp_try_brace = ignore # ignore/add/remove/force
-
-# Add or remove space between get/set and '{' if on the same line
-sp_getset_brace = ignore # ignore/add/remove/force
-
-# Add or remove space before the '::' operator
-sp_before_dc = ignore # ignore/add/remove/force
-
-# Add or remove space after the '::' operator
-sp_after_dc = ignore # ignore/add/remove/force
-
-# Add or remove around the D named array initializer ':' operator
-sp_d_array_colon = ignore # ignore/add/remove/force
-
-# Add or remove space after the '!' (not) operator. Default=Remove
-sp_not = remove # ignore/add/remove/force
-
-# Add or remove space after the '~' (invert) operator. Default=Remove
-sp_inv = remove # ignore/add/remove/force
-
-# Add or remove space after the '&' (address-of) operator. Default=Remove
-# This does not affect the spacing after a '&' that is part of a type.
-sp_addr = remove # ignore/add/remove/force
-
-# Add or remove space around the '.' or '->' operators. Default=Remove
-sp_member = remove # ignore/add/remove/force
-
-# Add or remove space after the '*' (dereference) operator. Default=Remove
-# This does not affect the spacing after a '*' that is part of a type.
-sp_deref = remove # ignore/add/remove/force
-
-# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove
-sp_sign = remove # ignore/add/remove/force
-
-# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove
-sp_incdec = remove # ignore/add/remove/force
-
-# Add or remove space before a backslash-newline at the end of a line. Default=Add
-sp_before_nl_cont = add # ignore/add/remove/force
-
-# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
-sp_after_oc_scope = ignore # ignore/add/remove/force
-
-# Add or remove space after the colon in message specs
-# '-(int) f:(int) x;' vs '-(int) f: (int) x;'
-sp_after_oc_colon = ignore # ignore/add/remove/force
-
-# Add or remove space before the colon in message specs
-# '-(int) f: (int) x;' vs '-(int) f : (int) x;'
-sp_before_oc_colon = ignore # ignore/add/remove/force
-
-# Add or remove space after the colon in immutable dictionary expression
-# 'NSDictionary *test = @{@"foo" :@"bar"};'
-sp_after_oc_dict_colon = ignore # ignore/add/remove/force
-
-# Add or remove space before the colon in immutable dictionary expression
-# 'NSDictionary *test = @{@"foo" :@"bar"};'
-sp_before_oc_dict_colon = ignore # ignore/add/remove/force
-
-# Add or remove space after the colon in message specs
-# '[object setValue:1];' vs '[object setValue: 1];'
-sp_after_send_oc_colon = ignore # ignore/add/remove/force
-
-# Add or remove space before the colon in message specs
-# '[object setValue:1];' vs '[object setValue :1];'
-sp_before_send_oc_colon = ignore # ignore/add/remove/force
-
-# Add or remove space after the (type) in message specs
-# '-(int)f: (int) x;' vs '-(int)f: (int)x;'
-sp_after_oc_type = ignore # ignore/add/remove/force
-
-# Add or remove space after the first (type) in message specs
-# '-(int) f:(int)x;' vs '-(int)f:(int)x;'
-sp_after_oc_return_type = ignore # ignore/add/remove/force
-
-# Add or remove space between '@selector' and '('
-# '@selector(msgName)' vs '@selector (msgName)'
-# Also applies to @protocol() constructs
-sp_after_oc_at_sel = ignore # ignore/add/remove/force
-
-# Add or remove space between '@selector(x)' and the following word
-# '@selector(foo) a:' vs '@selector(foo)a:'
-sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force
-
-# Add or remove space inside '@selector' parens
-# '@selector(foo)' vs '@selector( foo )'
-# Also applies to @protocol() constructs
-sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force
-
-# Add or remove space before a block pointer caret
-# '^int (int arg){...}' vs. ' ^int (int arg){...}'
-sp_before_oc_block_caret = ignore # ignore/add/remove/force
-
-# Add or remove space after a block pointer caret
-# '^int (int arg){...}' vs. '^ int (int arg){...}'
-sp_after_oc_block_caret = ignore # ignore/add/remove/force
-
-# Add or remove space between the receiver and selector in a message.
-# '[receiver selector ...]'
-sp_after_oc_msg_receiver = ignore # ignore/add/remove/force
-
-# Add or remove space after @property.
-sp_after_oc_property = ignore # ignore/add/remove/force
-
-# Add or remove space around the ':' in 'b ? t : f'
-sp_cond_colon = add # ignore/add/remove/force
-
-# Add or remove space around the '?' in 'b ? t : f'
-sp_cond_question = add # ignore/add/remove/force
-
-# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here.
-sp_case_label = ignore # ignore/add/remove/force
-
-# Control the space around the D '..' operator.
-sp_range = ignore # ignore/add/remove/force
-
-# Control the spacing after ':' in 'for (TYPE VAR : EXPR)' (Java)
-sp_after_for_colon = ignore # ignore/add/remove/force
-
-# Control the spacing before ':' in 'for (TYPE VAR : EXPR)' (Java)
-sp_before_for_colon = ignore # ignore/add/remove/force
-
-# Control the spacing in 'extern (C)' (D)
-sp_extern_paren = ignore # ignore/add/remove/force
-
-# Control the space after the opening of a C++ comment '// A' vs '//A'
-sp_cmt_cpp_start = ignore # ignore/add/remove/force
-
-# Controls the spaces between #else or #endif and a trailing comment
-sp_endif_cmt = ignore # ignore/add/remove/force
-
-# Controls the spaces after 'new', 'delete', and 'delete[]'
-sp_after_new = ignore # ignore/add/remove/force
-
-# Controls the spaces before a trailing or embedded comment
-sp_before_tr_emb_cmt = ignore # ignore/add/remove/force
-
-# Number of spaces before a trailing or embedded comment
-sp_num_before_tr_emb_cmt = 0 # number
-
-# Control space between a Java annotation and the open paren.
-sp_annotation_paren = ignore # ignore/add/remove/force
-
-#
-# Code alignment (not left column spaces/tabs)
-#
-
-# Whether to keep non-indenting tabs
-align_keep_tabs = false # false/true
-
-# Whether to keep whitespace not required for alignment
-align_keep_extra_space = false # false/true
-
-# Whether to use tabs for aligning
-align_with_tabs = false # false/true
-
-# Whether to bump out to the next tab when aligning
-align_on_tabstop = false # false/true
-
-# Whether to left-align numbers
-align_number_left = false # false/true
-
-# Align variable definitions in prototypes and functions
-align_func_params = true # false/true
-
-# Align parameters in single-line functions that have the same name.
-# The function names must already be aligned with each other.
-align_same_func_call_params = false # false/true
-
-# The span for aligning variable definitions (0=don't align)
-align_var_def_span = 1 # number
-
-# How to align the star in variable definitions.
-# 0=Part of the type 'void * foo;'
-# 1=Part of the variable 'void *foo;'
-# 2=Dangling 'void *foo;'
-align_var_def_star_style = 0 # number
-
-# How to align the '&' in variable definitions.
-# 0=Part of the type
-# 1=Part of the variable
-# 2=Dangling
-align_var_def_amp_style = 0 # number
-
-# The threshold for aligning variable definitions (0=no limit)
-align_var_def_thresh = 0 # number
-
-# The gap for aligning variable definitions
-align_var_def_gap = 1 # number
-
-# Whether to align the colon in struct bit fields
-align_var_def_colon = false # false/true
-
-# Whether to align any attribute after the variable name
-align_var_def_attribute = false # false/true
-
-# Whether to align inline struct/enum/union variable definitions
-align_var_def_inline = false # false/true
-
-# The span for aligning on '=' in assignments (0=don't align)
-align_assign_span = 1 # number
-
-# The threshold for aligning on '=' in assignments (0=no limit)
-align_assign_thresh = 0 # number
-
-# The span for aligning on '=' in enums (0=don't align)
-align_enum_equ_span = 1 # number
-
-# The threshold for aligning on '=' in enums (0=no limit)
-align_enum_equ_thresh = 0 # number
-
-# The span for aligning struct/union (0=don't align)
-align_var_struct_span = 1 # number
-
-# The threshold for aligning struct/union member definitions (0=no limit)
-align_var_struct_thresh = 0 # number
-
-# The gap for aligning struct/union member definitions
-align_var_struct_gap = 1 # number
-
-# The span for aligning struct initializer values (0=don't align)
-align_struct_init_span = 0 # number
-
-# The minimum space between the type and the synonym of a typedef
-align_typedef_gap = 0 # number
-
-# The span for aligning single-line typedefs (0=don't align)
-align_typedef_span = 0 # number
-
-# How to align typedef'd functions with other typedefs
-# 0: Don't mix them at all
-# 1: align the open paren with the types
-# 2: align the function type name with the other type names
-align_typedef_func = 0 # number
-
-# Controls the positioning of the '*' in typedefs. Just try it.
-# 0: Align on typedef type, ignore '*'
-# 1: The '*' is part of type name: typedef int *pint;
-# 2: The '*' is part of the type, but dangling: typedef int *pint;
-align_typedef_star_style = 0 # number
-
-# Controls the positioning of the '&' in typedefs. Just try it.
-# 0: Align on typedef type, ignore '&'
-# 1: The '&' is part of type name: typedef int &pint;
-# 2: The '&' is part of the type, but dangling: typedef int &pint;
-align_typedef_amp_style = 0 # number
-
-# The span for aligning comments that end lines (0=don't align)
-align_right_cmt_span = 3 # number
-
-# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment
-align_right_cmt_mix = true # false/true
-
-# If a trailing comment is more than this number of columns away from the text it follows,
-# it will qualify for being aligned. This has to be > 0 to do anything.
-align_right_cmt_gap = 0 # number
-
-# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore)
-align_right_cmt_at_col = 0 # number
-
-# The span for aligning function prototypes (0=don't align)
-align_func_proto_span = 0 # number
-
-# Minimum gap between the return type and the function name.
-align_func_proto_gap = 0 # number
-
-# Align function protos on the 'operator' keyword instead of what follows
-align_on_operator = false # false/true
-
-# Whether to mix aligning prototype and variable declarations.
-# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options.
-align_mix_var_proto = false # false/true
-
-# Align single-line functions with function prototypes, uses align_func_proto_span
-align_single_line_func = false # false/true
-
-# Aligning the open brace of single-line functions.
-# Requires align_single_line_func=true, uses align_func_proto_span
-align_single_line_brace = false # false/true
-
-# Gap for align_single_line_brace.
-align_single_line_brace_gap = 0 # number
-
-# The span for aligning ObjC msg spec (0=don't align)
-align_oc_msg_spec_span = 0 # number
-
-# Whether to align macros wrapped with a backslash and a newline.
-# This will not work right if the macro contains a multi-line comment.
-align_nl_cont = false # false/true
-
-# # Align macro functions and variables together
-align_pp_define_together = false # false/true
-
-# The minimum space between label and value of a preprocessor define
-align_pp_define_gap = 0 # number
-
-# The span for aligning on '#define' bodies (0=don't align)
-align_pp_define_span = 0 # number
-
-# Align lines that start with '<<' with previous '<<'. Default=true
-align_left_shift = false # false/true
-
-# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align)
-align_oc_msg_colon_span = 0 # number
-
-# If true, always align with the first parameter, even if it is too short.
-align_oc_msg_colon_first = false # false/true
-
-# Aligning parameters in an Obj-C '+' or '-' declaration on the ':'
-align_oc_decl_colon = false # false/true
-
-#
-# Newline adding and removing options
-#
-
-# Whether to collapse empty blocks between '{' and '}'
-nl_collapse_empty_body = false # false/true
-
-# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'
-nl_assign_leave_one_liners = true # false/true
-
-# Don't split one-line braced statements inside a class xx { } body
-nl_class_leave_one_liners = true # false/true
-
-# Don't split one-line enums: 'enum foo { BAR = 15 };'
-nl_enum_leave_one_liners = false # false/true
-
-# Don't split one-line get or set functions
-nl_getset_leave_one_liners = false # false/true
-
-# Don't split one-line function definitions - 'int foo() { return 0; }'
-nl_func_leave_one_liners = true # false/true
-
-# Don't split one-line if/else statements - 'if(a) b++;'
-nl_if_leave_one_liners = false # false/true
-
-# Don't split one-line OC messages
-nl_oc_msg_leave_one_liner = false # false/true
-
-# Add or remove newlines at the start of the file
-nl_start_of_file = ignore # ignore/add/remove/force
-
-# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'
-nl_start_of_file_min = 0 # number
-
-# Add or remove newline at the end of the file
-nl_end_of_file = force # ignore/add/remove/force
-
-# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')
-nl_end_of_file_min = 1 # number
-
-# Add or remove newline between '=' and '{'
-nl_assign_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between '=' and '[' (D only)
-nl_assign_square = ignore # ignore/add/remove/force
-
-# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'
-nl_after_square_assign = ignore # ignore/add/remove/force
-
-# The number of blank lines after a block of variable definitions at the top of a function body
-# 0 = No change (default)
-nl_func_var_def_blk = 0 # number
-
-# The number of newlines before a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_start = 0 # number
-
-# The number of newlines after a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_end = 0 # number
-
-# The maximum consecutive newlines within a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_in = 0 # number
-
-# The number of newlines before a block of variable definitions not at the top of a function body
-# 0 = No change (default)
-nl_var_def_blk_start = 0 # number
-
-# The number of newlines after a block of variable definitions not at the top of a function body
-# 0 = No change (default)
-nl_var_def_blk_end = 0 # number
-
-# The maximum consecutive newlines within a block of variable definitions
-# 0 = No change (default)
-nl_var_def_blk_in = 0 # number
-
-# Add or remove newline between a function call's ')' and '{', as in:
-# list_for_each(item, &list) { }
-nl_fcall_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'enum' and '{'
-nl_enum_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'struct and '{'
-nl_struct_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'union' and '{'
-nl_union_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'if' and '{'
-nl_if_brace = add # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'else'
-nl_brace_else = add # ignore/add/remove/force
-
-# Add or remove newline between 'else if' and '{'
-# If set to ignore, nl_if_brace is used instead
-nl_elseif_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'else' and '{'
-nl_else_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'else' and 'if'
-nl_else_if = ignore # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'finally'
-nl_brace_finally = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'finally' and '{'
-nl_finally_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'try' and '{'
-nl_try_brace = add # ignore/add/remove/force
-
-# Add or remove newline between get/set and '{'
-nl_getset_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'for' and '{'
-nl_for_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'catch' and '{'
-nl_catch_brace = add # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'catch'
-nl_brace_catch = add # ignore/add/remove/force
-
-# Add or remove newline between 'while' and '{'
-nl_while_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'scope (x)' and '{' (D)
-nl_scope_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'unittest' and '{' (D)
-nl_unittest_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'version (x)' and '{' (D)
-nl_version_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'using' and '{'
-nl_using_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between two open or close braces.
-# Due to general newline/brace handling, REMOVE may not work.
-nl_brace_brace = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'do' and '{'
-nl_do_brace = add # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'while' of 'do' statement
-nl_brace_while = remove # ignore/add/remove/force
-
-# Add or remove newline between 'switch' and '{'
-nl_switch_brace = add # ignore/add/remove/force
-
-# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc.
-# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace.
-nl_multi_line_cond = false # false/true
-
-# Force a newline in a define after the macro name for multi-line defines.
-nl_multi_line_define = false # false/true
-
-# Whether to put a newline before 'case' statement
-nl_before_case = false # false/true
-
-# Add or remove newline between ')' and 'throw'
-nl_before_throw = ignore # ignore/add/remove/force
-
-# Whether to put a newline after 'case' statement
-nl_after_case = false # false/true
-
-# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case.
-nl_case_colon_brace = add # ignore/add/remove/force
-
-# Newline between namespace and {
-nl_namespace_brace = add # ignore/add/remove/force
-
-# Add or remove newline between 'template<>' and whatever follows.
-nl_template_class = ignore # ignore/add/remove/force
-
-# Add or remove newline between 'class' and '{'
-nl_class_brace = add # ignore/add/remove/force
-
-# Add or remove newline after each ',' in the constructor member initialization
-nl_class_init_args = ignore # ignore/add/remove/force
-
-# Add or remove newline between return type and function name in a function definition
-nl_func_type_name = remove # ignore/add/remove/force
-
-# Add or remove newline between return type and function name inside a class {}
-# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore.
-nl_func_type_name_class = ignore # ignore/add/remove/force
-
-# Add or remove newline between function scope and name in a definition
-# Controls the newline after '::' in 'void A::f() { }'
-nl_func_scope_name = ignore # ignore/add/remove/force
-
-# Add or remove newline between return type and function name in a prototype
-nl_func_proto_type_name = ignore # ignore/add/remove/force
-
-# Add or remove newline between a function name and the opening '('
-nl_func_paren = remove # ignore/add/remove/force
-
-# Add or remove newline between a function name and the opening '(' in the definition
-nl_func_def_paren = ignore # ignore/add/remove/force
-
-# Add or remove newline after '(' in a function declaration
-nl_func_decl_start = ignore # ignore/add/remove/force
-
-# Add or remove newline after '(' in a function definition
-nl_func_def_start = ignore # ignore/add/remove/force
-
-# Overrides nl_func_decl_start when there is only one parameter.
-nl_func_decl_start_single = ignore # ignore/add/remove/force
-
-# Overrides nl_func_def_start when there is only one parameter.
-nl_func_def_start_single = ignore # ignore/add/remove/force
-
-# Add or remove newline after each ',' in a function declaration
-nl_func_decl_args = ignore # ignore/add/remove/force
-
-# Add or remove newline after each ',' in a function definition
-nl_func_def_args = ignore # ignore/add/remove/force
-
-# Add or remove newline before the ')' in a function declaration
-nl_func_decl_end = ignore # ignore/add/remove/force
-
-# Add or remove newline before the ')' in a function definition
-nl_func_def_end = ignore # ignore/add/remove/force
-
-# Overrides nl_func_decl_end when there is only one parameter.
-nl_func_decl_end_single = ignore # ignore/add/remove/force
-
-# Overrides nl_func_def_end when there is only one parameter.
-nl_func_def_end_single = ignore # ignore/add/remove/force
-
-# Add or remove newline between '()' in a function declaration.
-nl_func_decl_empty = ignore # ignore/add/remove/force
-
-# Add or remove newline between '()' in a function definition.
-nl_func_def_empty = ignore # ignore/add/remove/force
-
-# Whether to put each OC message parameter on a separate line
-# See nl_oc_msg_leave_one_liner
-nl_oc_msg_args = false # false/true
-
-# Add or remove newline between function signature and '{'
-nl_fdef_brace = add # ignore/add/remove/force
-
-# Add or remove a newline between the return keyword and return expression.
-nl_return_expr = ignore # ignore/add/remove/force
-
-# Whether to put a newline after semicolons, except in 'for' statements
-nl_after_semicolon = false # false/true
-
-# Whether to put a newline after brace open.
-# This also adds a newline before the matching brace close.
-nl_after_brace_open = true # false/true
-
-# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is
-# placed between the open brace and a trailing single-line comment.
-nl_after_brace_open_cmt = false # false/true
-
-# Whether to put a newline after a virtual brace open with a non-empty body.
-# These occur in un-braced if/while/do/for statement bodies.
-nl_after_vbrace_open = false # false/true
-
-# Whether to put a newline after a virtual brace open with an empty body.
-# These occur in un-braced if/while/do/for statement bodies.
-nl_after_vbrace_open_empty = false # false/true
-
-# Whether to put a newline after a brace close.
-# Does not apply if followed by a necessary ';'.
-nl_after_brace_close = false # false/true
-
-# Whether to put a newline after a virtual brace close.
-# Would add a newline before return in: 'if (foo) a++; return;'
-nl_after_vbrace_close = false # false/true
-
-# Control the newline between the close brace and 'b' in: 'struct { int a; } b;'
-# Affects enums, unions, and structures. If set to ignore, uses nl_after_brace_close
-nl_brace_struct_var = ignore # ignore/add/remove/force
-
-# Whether to alter newlines in '#define' macros
-nl_define_macro = false # false/true
-
-# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'
-nl_squeeze_ifdef = false # false/true
-
-# Add or remove blank line before 'if'
-nl_before_if = ignore # ignore/add/remove/force
-
-# Add or remove blank line after 'if' statement
-nl_after_if = ignore # ignore/add/remove/force
-
-# Add or remove blank line before 'for'
-nl_before_for = ignore # ignore/add/remove/force
-
-# Add or remove blank line after 'for' statement
-nl_after_for = ignore # ignore/add/remove/force
-
-# Add or remove blank line before 'while'
-nl_before_while = ignore # ignore/add/remove/force
-
-# Add or remove blank line after 'while' statement
-nl_after_while = ignore # ignore/add/remove/force
-
-# Add or remove blank line before 'switch'
-nl_before_switch = ignore # ignore/add/remove/force
-
-# Add or remove blank line after 'switch' statement
-nl_after_switch = ignore # ignore/add/remove/force
-
-# Add or remove blank line before 'do'
-nl_before_do = ignore # ignore/add/remove/force
-
-# Add or remove blank line after 'do/while' statement
-nl_after_do = ignore # ignore/add/remove/force
-
-# Whether to double-space commented-entries in struct/enum
-nl_ds_struct_enum_cmt = false # false/true
-
-# Whether to double-space before the close brace of a struct/union/enum
-# (lower priority than 'eat_blanks_before_close_brace')
-nl_ds_struct_enum_close_brace = false # false/true
-
-# Add or remove a newline around a class colon.
-# Related to pos_class_colon, nl_class_init_args, and pos_comma.
-nl_class_colon = ignore # ignore/add/remove/force
-
-# Change simple unbraced if statements into a one-liner
-# 'if(b)\n i++;' => 'if(b) i++;'
-nl_create_if_one_liner = false # false/true
-
-# Change simple unbraced for statements into a one-liner
-# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'
-nl_create_for_one_liner = false # false/true
-
-# Change simple unbraced while statements into a one-liner
-# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'
-nl_create_while_one_liner = false # false/true
-
-#
-# Positioning options
-#
-
-# The position of arithmetic operators in wrapped expressions
-pos_arith = lead # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of assignment in wrapped expressions.
-# Do not affect '=' followed by '{'
-pos_assign = lead # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of boolean operators in wrapped expressions
-pos_bool = lead # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of comparison operators in wrapped expressions
-pos_compare = lead # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of conditional (b ? t : f) operators in wrapped expressions
-pos_conditional = lead # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of the comma in wrapped expressions
-pos_comma = trail # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of the comma in the constructor initialization list
-pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-# The position of colons between constructor and member initialization
-pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
-
-#
-# Line Splitting options
-#
-
-# Try to limit code width to N number of columns
-code_width = 0 # number
-
-# Whether to fully split long 'for' statements at semi-colons
-ls_for_split_full = false # false/true
-
-# Whether to fully split long function protos/calls at commas
-ls_func_split_full = false # false/true
-
-# Whether to split lines as close to code_width as possible and ignore some groupings
-ls_code_width = false # false/true
-
-#
-# Blank line options
-#
-
-# The maximum consecutive newlines
-nl_max = 0 # number
-
-# The number of newlines after a function prototype, if followed by another function prototype
-nl_after_func_proto = 0 # number
-
-# The number of newlines after a function prototype, if not followed by another function prototype
-nl_after_func_proto_group = 0 # number
-
-# The number of newlines after '}' of a multi-line function body
-nl_after_func_body = 0 # number
-
-# The number of newlines after '}' of a multi-line function body in a class declaration
-nl_after_func_body_class = 0 # number
-
-# The number of newlines after '}' of a single line function body
-nl_after_func_body_one_liner = 0 # number
-
-# The minimum number of newlines before a multi-line comment.
-# Doesn't apply if after a brace open or another multi-line comment.
-nl_before_block_comment = 0 # number
-
-# The minimum number of newlines before a single-line C comment.
-# Doesn't apply if after a brace open or other single-line C comments.
-nl_before_c_comment = 0 # number
-
-# The minimum number of newlines before a CPP comment.
-# Doesn't apply if after a brace open or other CPP comments.
-nl_before_cpp_comment = 0 # number
-
-# Whether to force a newline after a multi-line comment.
-nl_after_multiline_comment = false # false/true
-
-# The number of newlines after '}' or ';' of a struct/enum/union definition
-nl_after_struct = 0 # number
-
-# The number of newlines after '}' or ';' of a class definition
-nl_after_class = 0 # number
-
-# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# Will not change the newline count if after a brace open.
-# 0 = No change.
-nl_before_access_spec = 0 # number
-
-# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# 0 = No change.
-nl_after_access_spec = 0 # number
-
-# The number of newlines between a function def and the function comment.
-# 0 = No change.
-nl_comment_func_def = 0 # number
-
-# The number of newlines after a try-catch-finally block that isn't followed by a brace close.
-# 0 = No change.
-nl_after_try_catch_finally = 0 # number
-
-# The number of newlines before and after a property, indexer or event decl.
-# 0 = No change.
-nl_around_cs_property = 0 # number
-
-# The number of newlines between the get/set/add/remove handlers in C#.
-# 0 = No change.
-nl_between_get_set = 0 # number
-
-# Add or remove newline between C# property and the '{'
-nl_property_brace = ignore # ignore/add/remove/force
-
-# Whether to remove blank lines after '{'
-eat_blanks_after_open_brace = false # false/true
-
-# Whether to remove blank lines before '}'
-eat_blanks_before_close_brace = false # false/true
-
-# How aggressively to remove extra newlines not in preproc.
-# 0: No change
-# 1: Remove most newlines not handled by other config
-# 2: Remove all newlines and reformat completely by config
-nl_remove_extra_newlines = 0 # number
-
-# Whether to put a blank line before 'return' statements, unless after an open brace.
-nl_before_return = false # false/true
-
-# Whether to put a blank line after 'return' statements, unless followed by a close brace.
-nl_after_return = false # false/true
-
-# Whether to put a newline after a Java annotation statement.
-# Only affects annotations that are after a newline.
-nl_after_annotation = ignore # ignore/add/remove/force
-
-# Controls the newline between two annotations.
-nl_between_annotation = ignore # ignore/add/remove/force
-
-#
-# Code modifying options (non-whitespace)
-#
-
-# Add or remove braces on single-line 'do' statement
-mod_full_brace_do = add # ignore/add/remove/force
-
-# Add or remove braces on single-line 'for' statement
-mod_full_brace_for = add # ignore/add/remove/force
-
-# Add or remove braces on single-line function definitions. (Pawn)
-mod_full_brace_function = add # ignore/add/remove/force
-
-# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
-mod_full_brace_if = add # ignore/add/remove/force
-
-# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
-# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed.
-mod_full_brace_if_chain = false # false/true
-
-# Don't remove braces around statements that span N newlines
-mod_full_brace_nl = 0 # number
-
-# Add or remove braces on single-line 'while' statement
-mod_full_brace_while = add # ignore/add/remove/force
-
-# Add or remove braces on single-line 'using ()' statement
-mod_full_brace_using = ignore # ignore/add/remove/force
-
-# Add or remove unnecessary paren on 'return' statement
-mod_paren_on_return = ignore # ignore/add/remove/force
-
-# Whether to change optional semicolons to real semicolons
-mod_pawn_semicolon = false # false/true
-
-# Add parens on 'while' and 'if' statement around bools
-mod_full_paren_if_bool = false # false/true
-
-# Whether to remove superfluous semicolons
-mod_remove_extra_semicolon = false # false/true
-
-# If a function body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_function_closebrace_comment = 0 # number
-
-# If a switch body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_switch_closebrace_comment = 0 # number
-
-# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after
-# the #endif, a comment will be added.
-mod_add_long_ifdef_endif_comment = 0 # number
-
-# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after
-# the #else, a comment will be added.
-mod_add_long_ifdef_else_comment = 0 # number
-
-# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
-mod_sort_import = false # false/true
-
-# If TRUE, will sort consecutive single-line 'using' statements [C#]
-mod_sort_using = false # false/true
-
-# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
-# This is generally a bad idea, as it may break your code.
-mod_sort_include = false # false/true
-
-# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace.
-mod_move_case_break = false # false/true
-
-# Will add or remove the braces around a fully braced case statement.
-# Will only remove the braces if there are no variable declarations in the block.
-mod_case_brace = ignore # ignore/add/remove/force
-
-# If TRUE, it will remove a void 'return;' that appears as the last statement in a function.
-mod_remove_empty_return = false # false/true
-
-#
-# Comment modifications
-#
-
-# Try to wrap comments at cmt_width columns
-cmt_width = 0 # number
-
-# Set the comment reflow mode (default: 0)
-# 0: no reflowing (apart from the line wrapping due to cmt_width)
-# 1: no touching at all
-# 2: full reflow
-cmt_reflow_mode = 0 # number
-
-# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars.
-# Default is true.
-cmt_indent_multi = true # false/true
-
-# Whether to group c-comments that look like they are in a block
-cmt_c_group = false # false/true
-
-# Whether to put an empty '/*' on the first line of the combined c-comment
-cmt_c_nl_start = false # false/true
-
-# Whether to put a newline before the closing '*/' of the combined c-comment
-cmt_c_nl_end = false # false/true
-
-# Whether to group cpp-comments that look like they are in a block
-cmt_cpp_group = false # false/true
-
-# Whether to put an empty '/*' on the first line of the combined cpp-comment
-cmt_cpp_nl_start = false # false/true
-
-# Whether to put a newline before the closing '*/' of the combined cpp-comment
-cmt_cpp_nl_end = false # false/true
-
-# Whether to change cpp-comments into c-comments
-cmt_cpp_to_c = false # false/true
-
-# Whether to put a star on subsequent comment lines
-cmt_star_cont = false # false/true
-
-# The number of spaces to insert at the start of subsequent comment lines
-cmt_sp_before_star_cont = 0 # number
-
-# The number of spaces to insert after the star on subsequent comment lines
-cmt_sp_after_star_cont = 0 # number
-
-# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of
-# the comment are the same length. Default=True
-cmt_multi_check_last = false # false/true
-
-# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.
-# Will substitute $(filename) with the current file's name.
-cmt_insert_file_header = "" # string
-
-# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment.
-# Will substitute $(filename) with the current file's name.
-cmt_insert_file_footer = "" # string
-
-# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment.
-# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.
-# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }
-cmt_insert_func_header = "" # string
-
-# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment.
-# Will substitute $(class) with the class name.
-cmt_insert_class_header = "" # string
-
-# The filename that contains text to insert before a Obj-C message specification if the method isn't preceeded with a C/C++ comment.
-# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff.
-cmt_insert_oc_msg_header = "" # string
-
-# If a preprocessor is encountered when stepping backwards from a function name, then
-# this option decides whether the comment should be inserted.
-# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header.
-cmt_insert_before_preproc = false # false/true
-
-#
-# Preprocessor options
-#
-
-# Control indent of preprocessors inside #if blocks at brace level 0
-pp_indent = ignore # ignore/add/remove/force
-
-# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
-pp_indent_at_level = false # false/true
-
-# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1.
-pp_indent_count = 1 # number
-
-# Add or remove space after # based on pp_level of #if blocks
-pp_space = ignore # ignore/add/remove/force
-
-# Sets the number of spaces added with pp_space
-pp_space_count = 0 # number
-
-# The indent for #region and #endregion in C# and '#pragma region' in C/C++
-pp_indent_region = 0 # number
-
-# Whether to indent the code between #region and #endregion
-pp_region_indent_code = false # false/true
-
-# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
-pp_indent_if = 0 # number
-
-# Control whether to indent the code between #if, #else and #endif when not at file-level
-pp_if_indent_code = false # false/true
-
-# Whether to indent '#define' at the brace level (true) or from column 1 (false)
-pp_define_at_level = false # false/true
-
-# You can force a token to be a type with the 'type' option.
-# Example:
-# type myfoo1 myfoo2
-#
-# You can create custom macro-based indentation using macro-open,
-# macro-else and macro-close.
-# Example:
-# macro-open BEGIN_TEMPLATE_MESSAGE_MAP
-# macro-open BEGIN_MESSAGE_MAP
-# macro-close END_MESSAGE_MAP
-#
-# You can assign any keyword to any type with the set option.
-# set func_call_user _ N_
-#
-# The full syntax description of all custom definition config entries
-# is shown below:
-#
-# define custom tokens as:
-# - embed whitespace in token using '' escape character, or
-# put token in quotes
-# - these: ' " and ` are recognized as quote delimiters
-#
-# type token1 token2 token3 ...
-# ^ optionally specify multiple tokens on a single line
-# define def_token output_token
-# ^ output_token is optional, then NULL is assumed
-# macro-open token
-# macro-close token
-# macro-else token
-# set id token1 token2 ...
-# ^ optionally specify multiple tokens on a single line
-# ^ id is one of the names in token_enum.h sans the CT_ prefix,
-# e.g. PP_PRAGMA
-#
-# all tokens are separated by any mix of ',' commas, '=' equal signs
-# and whitespace (space, tab)
-#
-
-# Teach uncrustify about the GROMACS attribute aliases that we use
-# to hide compiler differences. This means that declarations like
-#
-# int i, j;
-# int nthreads gmx_unused;
-#
-# does not align i with gmx_unused.
-set ATTRIBUTE gmx_unused gmx_inline gmx_restrict
+++ /dev/null
-#!/bin/bash
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-# This script runs uncrustify on modified files and
-# reports/applies the necessary changes.
-#
-# See `uncrustify.sh -h` for a brief usage, and docs/dev-manual/code-formatting.rst
-# for more details.
-
-# Parse command-line arguments
-function usage() {
- echo "usage: uncrustify.sh [-f|--force] [--rev=REV]"
- echo " [--uncrustify=(off|check)]"
- echo " [--warnings=<file>] [<action>]"
- echo "<action>: (check*|diff|update)[-(index|workdir*)] (*=default)"
-}
-
-action="check-workdir"
-declare -a diffargs
-baserev="HEAD"
-force=
-uncrustify_mode=check
-warning_file=
-for arg in "$@" ; do
- if [[ "$arg" == "check-index" || "$arg" == "check-workdir" || \
- "$arg" == "diff-index" || "$arg" == "diff-workdir" || \
- "$arg" == "update-index" || "$arg" == "update-workdir" ]]
- then
- action=$arg
- elif [[ "$arg" == "check" || "$arg" == "diff" || "$arg" == "update" ]] ; then
- action=$arg-workdir
- elif [[ "$action" == diff-* ]] ; then
- diffargs+=("$arg")
- elif [[ "$arg" == --uncrustify=* ]] ; then
- uncrustify_mode=${arg#--uncrustify=}
- if [[ "$uncrustify_mode" != "off" && "$uncrustify_mode" != "check" ]] ; then
- echo "Unknown option: $arg"
- echo
- usage
- exit 2
- fi
- elif [[ "$arg" == "-f" || "$arg" == "--force" ]] ; then
- force=1
- elif [[ "$arg" == --rev=* ]] ; then
- baserev=${arg#--rev=}
- elif [[ "$arg" == --warnings=* ]] ; then
- warning_file=${arg#--warnings=}
- elif [[ "$arg" == "-h" || "$arg" == "--help" ]] ; then
- usage
- exit 0
- else
- echo "Unknown option: $arg"
- echo
- usage
- exit 2
- fi
-done
-
-# Check that uncrustify is present
-if [[ "$uncrustify_mode" != "off" ]]
-then
- if [ -z "$UNCRUSTIFY" ]
- then
- UNCRUSTIFY=`git config hooks.uncrustifypath`
- fi
- if [ -z "$UNCRUSTIFY" ]
- then
- echo "Please set the path to uncrustify using UNCRUSTIFY or"
- echo "git config hooks.uncrustifypath."
- echo "Note that you need a custom version of uncrustify."
- echo "See docs/dev-manual/uncrustify.rst for how to get one."
- exit 2
- fi
- if ! which "$UNCRUSTIFY" 1>/dev/null
- then
- echo "Uncrustify not found: $UNCRUSTIFY"
- exit 2
- fi
-fi
-
-# Switch to the root of the source tree and check the config file
-srcdir=`git rev-parse --show-toplevel`
-pushd $srcdir >/dev/null
-admin_dir=$srcdir/admin
-cfg_file=$admin_dir/uncrustify.cfg
-if [ ! -f "$cfg_file" ]
-then
- echo "Uncrustify configuration file not found: $cfg_file"
- exit 2
-fi
-
-# Actual processing starts: create a temporary directory
-tmpdir=`mktemp -d -t gmxuncrust.XXXXXX`
-
-# Produce a list of changed files
-# Only include files that have proper filter set in .gitattributes
-internal_diff_args=
-if [[ $action == *-index ]]
-then
- internal_diff_args="--cached"
-fi
-git diff-index $internal_diff_args --diff-filter=ACMR $baserev >$tmpdir/difflist
-cut -f2 <$tmpdir/difflist | \
- git check-attr --stdin filter | \
- sed -e 's/.*: filter: //' | \
- paste $tmpdir/difflist - | \
- grep -E '(complete_formatting|uncrustify|copyright|includesort)$' >$tmpdir/filtered
-cut -f2 <$tmpdir/filtered >$tmpdir/filelist_all
-grep -E '(uncrustify)$' <$tmpdir/filtered | \
- cut -f2 >$tmpdir/filelist_uncrustify
-git diff-files --name-only | grep -Ff $tmpdir/filelist_all >$tmpdir/localmods
-
-# Extract changed files to a temporary directory
-mkdir $tmpdir/org
-if [[ $action == *-index ]] ; then
- git checkout-index --prefix=$tmpdir/org/ --stdin <$tmpdir/filelist_all
-else
- rsync --files-from=$tmpdir/filelist_all $srcdir $tmpdir/org
-fi
-# Duplicate the original files to a separate directory, where all changes will
-# be made.
-cp -r $tmpdir/org $tmpdir/new
-
-# Create output file for what was done (in case no messages get written)
-touch $tmpdir/messages
-
-# Run uncrustify on the temporary directory
-cd $tmpdir/new
-if [[ $uncrustify_mode != "off" ]] ; then
- if ! $UNCRUSTIFY -c $cfg_file -F $tmpdir/filelist_uncrustify --no-backup >$tmpdir/uncrustify.out 2>&1 ; then
- echo "Reformatting failed. Check uncrustify output below for errors:"
- cat $tmpdir/uncrustify.out
- rm -rf $tmpdir
- exit 2
- fi
- # Find the changed files if necessary
- if [[ $action != diff-* ]] ; then
- msg="needs uncrustify"
- if [[ $action == update-* ]] ; then
- msg="uncrustified"
- fi
- git diff --no-index --name-only ../org/ . | \
- awk -v msg="$msg" '{sub(/.\//,""); print $0 ": " msg}' >> $tmpdir/messages
- fi
- # TODO: Consider checking whether rerunning uncrustify causes additional changes
-fi
-
-cd $tmpdir
-
-# If a diff was requested, show it and we are done
-if [[ $action == diff-* ]] ; then
- git diff --no-index --no-prefix "${diffargs[@]}" org/ new/
- rm -rf $tmpdir
- exit 0
-fi
-
-# Find the changed files
-git diff --no-index --name-only --exit-code org/ new/ | \
- sed -e 's#new/##' > $tmpdir/changed
-changes=
-if [[ -s $tmpdir/changed ]]
-then
- changes=1
-fi
-
-# Check if changed files have changed outside the index
-if grep -Ff $tmpdir/localmods $tmpdir/changed > $tmpdir/conflicts
-then
- awk '{print $0 ": has changes in work tree"}' $tmpdir/conflicts \
- >> $tmpdir/messages
- if [[ ! $force && $action == update-* ]] ; then
- echo "Modified files found in work tree, skipping update. Use -f to override."
- echo "The following would have been done:"
- sort $tmpdir/messages
- rm -rf $tmpdir
- exit 2
- fi
-fi
-
-# Update the index/work tree if requested
-if [[ $action == update-index ]] ; then
- grep -Ff $tmpdir/changed $tmpdir/filtered > $tmpdir/tohash
- cd $tmpdir/new
- IFS='
-'
- for change in `cut -f2 $tmpdir/tohash | \
- git --git-dir=$srcdir/.git hash-object -w --stdin-paths --no-filters | \
- paste - $tmpdir/tohash`
- do
- # NOTE: the patterns below contain literal tabs
- sha1=${change%% *}
- rest=${change#* }
- mode=${rest:8:6}
- path=${rest#* }
- path=${path%% *}
- # Contains a literal tab
- echo "$mode $sha1 $path" >> $tmpdir/toindex
- done
- unset IFS
- git --git-dir=$srcdir/.git update-index --index-info < $tmpdir/toindex
-elif [[ $action == update-workdir ]] ; then
- rsync --files-from=$tmpdir/changed $tmpdir/new/ $srcdir/
-fi
-
-# Get back to the original directory
-popd >/dev/null
-
-# Report what was done
-sort $tmpdir/messages | tee $warning_file
-
-rm -rf $tmpdir
-exit $changes
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2017, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-#.rst:
-# FindCUDA
-# --------
-#
-# GROMACS developers README
-# -------------------------
-#
-# This file is taken from CMake git tag v.3.4.3 Modules/FindCUDA.cmake
-# and modified to use --include-path and --system-include for the
-# include paths required for nvcc to function. Those are the supported
-# flags for nvcc, so should continue to function. Several other
-# supporting cmake files from Modules/FindCUDA/*cmake are also
-# required, and these are also copied from the CMake repo, unmodified.
-#
-# The main file is modified further to make
-# FindPackageHandleStandardArgs able to find those required supporting
-# cmake files.
-#
-# Once CMake 3.7.0 is required for GROMACS, then the fix for CMake
-# issue #14201 contained therein may remove the need for GROMACS to
-# import these files. Or CMake 3.8 supports CUDA natively (but 3.9
-# required for MSVC support also) if that proves useful for
-# GROMACS. However, the FindCUDA.cmake in CMake 3.9.0 still does not
-# use include functionality for headers internal to CUDA that would
-# permit the GROMACS use of -Wundef to lead to warning-free CUDA
-# compilation.
-#
-# Standard FindCUDA documentation
-# -------------------------------
-#
-# Tools for building CUDA C files: libraries and build dependencies.
-#
-# This script locates the NVIDIA CUDA C tools. It should work on linux,
-# windows, and mac and should be reasonably up to date with CUDA C
-# releases.
-#
-# This script makes use of the standard find_package arguments of
-# <VERSION>, REQUIRED and QUIET. CUDA_FOUND will report if an
-# acceptable version of CUDA was found.
-#
-# The script will prompt the user to specify CUDA_TOOLKIT_ROOT_DIR if
-# the prefix cannot be determined by the location of nvcc in the system
-# path and REQUIRED is specified to find_package(). To use a different
-# installed version of the toolkit set the environment variable
-# CUDA_BIN_PATH before running cmake (e.g.
-# CUDA_BIN_PATH=/usr/local/cuda1.0 instead of the default
-# /usr/local/cuda) or set CUDA_TOOLKIT_ROOT_DIR after configuring. If
-# you change the value of CUDA_TOOLKIT_ROOT_DIR, various components that
-# depend on the path will be relocated.
-#
-# It might be necessary to set CUDA_TOOLKIT_ROOT_DIR manually on certain
-# platforms, or to use a cuda runtime not installed in the default
-# location. In newer versions of the toolkit the cuda library is
-# included with the graphics driver- be sure that the driver version
-# matches what is needed by the cuda runtime version.
-#
-# The following variables affect the behavior of the macros in the
-# script (in alphebetical order). Note that any of these flags can be
-# changed multiple times in the same directory before calling
-# CUDA_ADD_EXECUTABLE, CUDA_ADD_LIBRARY, CUDA_COMPILE, CUDA_COMPILE_PTX,
-# CUDA_COMPILE_FATBIN, CUDA_COMPILE_CUBIN or CUDA_WRAP_SRCS::
-#
-# CUDA_64_BIT_DEVICE_CODE (Default matches host bit size)
-# -- Set to ON to compile for 64 bit device code, OFF for 32 bit device code.
-# Note that making this different from the host code when generating object
-# or C files from CUDA code just won't work, because size_t gets defined by
-# nvcc in the generated source. If you compile to PTX and then load the
-# file yourself, you can mix bit sizes between device and host.
-#
-# CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE (Default ON)
-# -- Set to ON if you want the custom build rule to be attached to the source
-# file in Visual Studio. Turn OFF if you add the same cuda file to multiple
-# targets.
-#
-# This allows the user to build the target from the CUDA file; however, bad
-# things can happen if the CUDA source file is added to multiple targets.
-# When performing parallel builds it is possible for the custom build
-# command to be run more than once and in parallel causing cryptic build
-# errors. VS runs the rules for every source file in the target, and a
-# source can have only one rule no matter how many projects it is added to.
-# When the rule is run from multiple targets race conditions can occur on
-# the generated file. Eventually everything will get built, but if the user
-# is unaware of this behavior, there may be confusion. It would be nice if
-# this script could detect the reuse of source files across multiple targets
-# and turn the option off for the user, but no good solution could be found.
-#
-# CUDA_BUILD_CUBIN (Default OFF)
-# -- Set to ON to enable and extra compilation pass with the -cubin option in
-# Device mode. The output is parsed and register, shared memory usage is
-# printed during build.
-#
-# CUDA_BUILD_EMULATION (Default OFF for device mode)
-# -- Set to ON for Emulation mode. -D_DEVICEEMU is defined for CUDA C files
-# when CUDA_BUILD_EMULATION is TRUE.
-#
-# CUDA_GENERATED_OUTPUT_DIR (Default CMAKE_CURRENT_BINARY_DIR)
-# -- Set to the path you wish to have the generated files placed. If it is
-# blank output files will be placed in CMAKE_CURRENT_BINARY_DIR.
-# Intermediate files will always be placed in
-# CMAKE_CURRENT_BINARY_DIR/CMakeFiles.
-#
-# CUDA_HOST_COMPILATION_CPP (Default ON)
-# -- Set to OFF for C compilation of host code.
-#
-# CUDA_HOST_COMPILER (Default CMAKE_C_COMPILER, $(VCInstallDir)/bin for VS)
-# -- Set the host compiler to be used by nvcc. Ignored if -ccbin or
-# --compiler-bindir is already present in the CUDA_NVCC_FLAGS or
-# CUDA_NVCC_FLAGS_<CONFIG> variables. For Visual Studio targets
-# $(VCInstallDir)/bin is a special value that expands out to the path when
-# the command is run from withing VS.
-#
-# CUDA_NVCC_FLAGS
-# CUDA_NVCC_FLAGS_<CONFIG>
-# -- Additional NVCC command line arguments. NOTE: multiple arguments must be
-# semi-colon delimited (e.g. --compiler-options;-Wall)
-#
-# CUDA_PROPAGATE_HOST_FLAGS (Default ON)
-# -- Set to ON to propagate CMAKE_{C,CXX}_FLAGS and their configuration
-# dependent counterparts (e.g. CMAKE_C_FLAGS_DEBUG) automatically to the
-# host compiler through nvcc's -Xcompiler flag. This helps make the
-# generated host code match the rest of the system better. Sometimes
-# certain flags give nvcc problems, and this will help you turn the flag
-# propagation off. This does not affect the flags supplied directly to nvcc
-# via CUDA_NVCC_FLAGS or through the OPTION flags specified through
-# CUDA_ADD_LIBRARY, CUDA_ADD_EXECUTABLE, or CUDA_WRAP_SRCS. Flags used for
-# shared library compilation are not affected by this flag.
-#
-# CUDA_SEPARABLE_COMPILATION (Default OFF)
-# -- If set this will enable separable compilation for all CUDA runtime object
-# files. If used outside of CUDA_ADD_EXECUTABLE and CUDA_ADD_LIBRARY
-# (e.g. calling CUDA_WRAP_SRCS directly),
-# CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME and
-# CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS should be called.
-#
-# CUDA_SOURCE_PROPERTY_FORMAT
-# -- If this source file property is set, it can override the format specified
-# to CUDA_WRAP_SRCS (OBJ, PTX, CUBIN, or FATBIN). If an input source file
-# is not a .cu file, setting this file will cause it to be treated as a .cu
-# file. See documentation for set_source_files_properties on how to set
-# this property.
-#
-# CUDA_USE_STATIC_CUDA_RUNTIME (Default ON)
-# -- When enabled the static version of the CUDA runtime library will be used
-# in CUDA_LIBRARIES. If the version of CUDA configured doesn't support
-# this option, then it will be silently disabled.
-#
-# CUDA_VERBOSE_BUILD (Default OFF)
-# -- Set to ON to see all the commands used when building the CUDA file. When
-# using a Makefile generator the value defaults to VERBOSE (run make
-# VERBOSE=1 to see output), although setting CUDA_VERBOSE_BUILD to ON will
-# always print the output.
-#
-# The script creates the following macros (in alphebetical order)::
-#
-# CUDA_ADD_CUFFT_TO_TARGET( cuda_target )
-# -- Adds the cufft library to the target (can be any target). Handles whether
-# you are in emulation mode or not.
-#
-# CUDA_ADD_CUBLAS_TO_TARGET( cuda_target )
-# -- Adds the cublas library to the target (can be any target). Handles
-# whether you are in emulation mode or not.
-#
-# CUDA_ADD_EXECUTABLE( cuda_target file0 file1 ...
-# [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
-# -- Creates an executable "cuda_target" which is made up of the files
-# specified. All of the non CUDA C files are compiled using the standard
-# build rules specified by CMAKE and the cuda files are compiled to object
-# files using nvcc and the host compiler. In addition CUDA_INCLUDE_DIRS is
-# added automatically to include_directories(). Some standard CMake target
-# calls can be used on the target after calling this macro
-# (e.g. set_target_properties and target_link_libraries), but setting
-# properties that adjust compilation flags will not affect code compiled by
-# nvcc. Such flags should be modified before calling CUDA_ADD_EXECUTABLE,
-# CUDA_ADD_LIBRARY or CUDA_WRAP_SRCS.
-#
-# CUDA_ADD_LIBRARY( cuda_target file0 file1 ...
-# [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
-# -- Same as CUDA_ADD_EXECUTABLE except that a library is created.
-#
-# CUDA_BUILD_CLEAN_TARGET()
-# -- Creates a convience target that deletes all the dependency files
-# generated. You should make clean after running this target to ensure the
-# dependency files get regenerated.
-#
-# CUDA_COMPILE( generated_files file0 file1 ... [STATIC | SHARED | MODULE]
-# [OPTIONS ...] )
-# -- Returns a list of generated files from the input source files to be used
-# with ADD_LIBRARY or ADD_EXECUTABLE.
-#
-# CUDA_COMPILE_PTX( generated_files file0 file1 ... [OPTIONS ...] )
-# -- Returns a list of PTX files generated from the input source files.
-#
-# CUDA_COMPILE_FATBIN( generated_files file0 file1 ... [OPTIONS ...] )
-# -- Returns a list of FATBIN files generated from the input source files.
-#
-# CUDA_COMPILE_CUBIN( generated_files file0 file1 ... [OPTIONS ...] )
-# -- Returns a list of CUBIN files generated from the input source files.
-#
-# CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME( output_file_var
-# cuda_target
-# object_files )
-# -- Compute the name of the intermediate link file used for separable
-# compilation. This file name is typically passed into
-# CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS. output_file_var is produced
-# based on cuda_target the list of objects files that need separable
-# compilation as specified by object_files. If the object_files list is
-# empty, then output_file_var will be empty. This function is called
-# automatically for CUDA_ADD_LIBRARY and CUDA_ADD_EXECUTABLE. Note that
-# this is a function and not a macro.
-#
-# CUDA_INCLUDE_DIRECTORIES( path0 path1 ... )
-# -- Sets the directories that should be passed to nvcc
-# (e.g. nvcc -Ipath0 -Ipath1 ... ). These paths usually contain other .cu
-# files.
-#
-#
-#
-# CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS( output_file_var cuda_target
-# nvcc_flags object_files)
-#
-# -- Generates the link object required by separable compilation from the given
-# object files. This is called automatically for CUDA_ADD_EXECUTABLE and
-# CUDA_ADD_LIBRARY, but can be called manually when using CUDA_WRAP_SRCS
-# directly. When called from CUDA_ADD_LIBRARY or CUDA_ADD_EXECUTABLE the
-# nvcc_flags passed in are the same as the flags passed in via the OPTIONS
-# argument. The only nvcc flag added automatically is the bitness flag as
-# specified by CUDA_64_BIT_DEVICE_CODE. Note that this is a function
-# instead of a macro.
-#
-# CUDA_WRAP_SRCS ( cuda_target format generated_files file0 file1 ...
-# [STATIC | SHARED | MODULE] [OPTIONS ...] )
-# -- This is where all the magic happens. CUDA_ADD_EXECUTABLE,
-# CUDA_ADD_LIBRARY, CUDA_COMPILE, and CUDA_COMPILE_PTX all call this
-# function under the hood.
-#
-# Given the list of files (file0 file1 ... fileN) this macro generates
-# custom commands that generate either PTX or linkable objects (use "PTX" or
-# "OBJ" for the format argument to switch). Files that don't end with .cu
-# or have the HEADER_FILE_ONLY property are ignored.
-#
-# The arguments passed in after OPTIONS are extra command line options to
-# give to nvcc. You can also specify per configuration options by
-# specifying the name of the configuration followed by the options. General
-# options must preceed configuration specific options. Not all
-# configurations need to be specified, only the ones provided will be used.
-#
-# OPTIONS -DFLAG=2 "-DFLAG_OTHER=space in flag"
-# DEBUG -g
-# RELEASE --use_fast_math
-# RELWITHDEBINFO --use_fast_math;-g
-# MINSIZEREL --use_fast_math
-#
-# For certain configurations (namely VS generating object files with
-# CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE set to ON), no generated file will
-# be produced for the given cuda file. This is because when you add the
-# cuda file to Visual Studio it knows that this file produces an object file
-# and will link in the resulting object file automatically.
-#
-# This script will also generate a separate cmake script that is used at
-# build time to invoke nvcc. This is for several reasons.
-#
-# 1. nvcc can return negative numbers as return values which confuses
-# Visual Studio into thinking that the command succeeded. The script now
-# checks the error codes and produces errors when there was a problem.
-#
-# 2. nvcc has been known to not delete incomplete results when it
-# encounters problems. This confuses build systems into thinking the
-# target was generated when in fact an unusable file exists. The script
-# now deletes the output files if there was an error.
-#
-# 3. By putting all the options that affect the build into a file and then
-# make the build rule dependent on the file, the output files will be
-# regenerated when the options change.
-#
-# This script also looks at optional arguments STATIC, SHARED, or MODULE to
-# determine when to target the object compilation for a shared library.
-# BUILD_SHARED_LIBS is ignored in CUDA_WRAP_SRCS, but it is respected in
-# CUDA_ADD_LIBRARY. On some systems special flags are added for building
-# objects intended for shared libraries. A preprocessor macro,
-# <target_name>_EXPORTS is defined when a shared library compilation is
-# detected.
-#
-# Flags passed into add_definitions with -D or /D are passed along to nvcc.
-#
-#
-#
-# The script defines the following variables::
-#
-# CUDA_VERSION_MAJOR -- The major version of cuda as reported by nvcc.
-# CUDA_VERSION_MINOR -- The minor version.
-# CUDA_VERSION
-# CUDA_VERSION_STRING -- CUDA_VERSION_MAJOR.CUDA_VERSION_MINOR
-#
-# CUDA_TOOLKIT_ROOT_DIR -- Path to the CUDA Toolkit (defined if not set).
-# CUDA_SDK_ROOT_DIR -- Path to the CUDA SDK. Use this to find files in the
-# SDK. This script will not directly support finding
-# specific libraries or headers, as that isn't
-# supported by NVIDIA. If you want to change
-# libraries when the path changes see the
-# FindCUDA.cmake script for an example of how to clear
-# these variables. There are also examples of how to
-# use the CUDA_SDK_ROOT_DIR to locate headers or
-# libraries, if you so choose (at your own risk).
-# CUDA_INCLUDE_DIRS -- Include directory for cuda headers. Added automatically
-# for CUDA_ADD_EXECUTABLE and CUDA_ADD_LIBRARY.
-# CUDA_LIBRARIES -- Cuda RT library.
-# CUDA_CUFFT_LIBRARIES -- Device or emulation library for the Cuda FFT
-# implementation (alternative to:
-# CUDA_ADD_CUFFT_TO_TARGET macro)
-# CUDA_CUBLAS_LIBRARIES -- Device or emulation library for the Cuda BLAS
-# implementation (alterative to:
-# CUDA_ADD_CUBLAS_TO_TARGET macro).
-# CUDA_cudart_static_LIBRARY -- Statically linkable cuda runtime library.
-# Only available for CUDA version 5.5+
-# CUDA_cupti_LIBRARY -- CUDA Profiling Tools Interface library.
-# Only available for CUDA version 4.0+.
-# CUDA_curand_LIBRARY -- CUDA Random Number Generation library.
-# Only available for CUDA version 3.2+.
-# CUDA_cusolver_LIBRARY -- CUDA Direct Solver library.
-# Only available for CUDA version 7.0+.
-# CUDA_cusparse_LIBRARY -- CUDA Sparse Matrix library.
-# Only available for CUDA version 3.2+.
-# CUDA_npp_LIBRARY -- NVIDIA Performance Primitives lib.
-# Only available for CUDA version 4.0+.
-# CUDA_nppc_LIBRARY -- NVIDIA Performance Primitives lib (core).
-# Only available for CUDA version 5.5+.
-# CUDA_nppi_LIBRARY -- NVIDIA Performance Primitives lib (image processing).
-# Only available for CUDA version 5.5+.
-# CUDA_npps_LIBRARY -- NVIDIA Performance Primitives lib (signal processing).
-# Only available for CUDA version 5.5+.
-# CUDA_nvcuvenc_LIBRARY -- CUDA Video Encoder library.
-# Only available for CUDA version 3.2+.
-# Windows only.
-# CUDA_nvcuvid_LIBRARY -- CUDA Video Decoder library.
-# Only available for CUDA version 3.2+.
-# Windows only.
-#
-
-# James Bigler, NVIDIA Corp (nvidia.com - jbigler)
-# Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
-#
-# Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
-#
-# Copyright (c) 2007-2009
-# Scientific Computing and Imaging Institute, University of Utah
-#
-# This code is licensed under the MIT License. See the FindCUDA.cmake script
-# for the text of the license.
-
-# The MIT License
-#
-# License for the specific language governing rights and limitations under
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-#
-###############################################################################
-
-# FindCUDA.cmake
-
-# This macro helps us find the location of helper files we will need the full path to
-macro(CUDA_FIND_HELPER_FILE _name _extension)
- set(_full_name "${_name}.${_extension}")
- # CMAKE_CURRENT_LIST_FILE contains the full path to the file currently being
- # processed. Using this variable, we can pull out the current path, and
- # provide a way to get access to the other files we need local to here.
- get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
- set(CUDA_${_name} "${CMAKE_CURRENT_LIST_DIR}/FindCUDA/${_full_name}")
- if(NOT EXISTS "${CUDA_${_name}}")
- set(error_message "${_full_name} not found in ${CMAKE_CURRENT_LIST_DIR}/FindCUDA")
- if(CUDA_FIND_REQUIRED)
- message(FATAL_ERROR "${error_message}")
- else()
- if(NOT CUDA_FIND_QUIETLY)
- message(STATUS "${error_message}")
- endif()
- endif()
- endif()
- # Set this variable as internal, so the user isn't bugged with it.
- set(CUDA_${_name} ${CUDA_${_name}} CACHE INTERNAL "Location of ${_full_name}" FORCE)
-endmacro()
-
-#####################################################################
-## CUDA_INCLUDE_NVCC_DEPENDENCIES
-##
-
-# So we want to try and include the dependency file if it exists. If
-# it doesn't exist then we need to create an empty one, so we can
-# include it.
-
-# If it does exist, then we need to check to see if all the files it
-# depends on exist. If they don't then we should clear the dependency
-# file and regenerate it later. This covers the case where a header
-# file has disappeared or moved.
-
-macro(CUDA_INCLUDE_NVCC_DEPENDENCIES dependency_file)
- set(CUDA_NVCC_DEPEND)
- set(CUDA_NVCC_DEPEND_REGENERATE FALSE)
-
-
- # Include the dependency file. Create it first if it doesn't exist . The
- # INCLUDE puts a dependency that will force CMake to rerun and bring in the
- # new info when it changes. DO NOT REMOVE THIS (as I did and spent a few
- # hours figuring out why it didn't work.
- if(NOT EXISTS ${dependency_file})
- file(WRITE ${dependency_file} "#FindCUDA.cmake generated file. Do not edit.\n")
- endif()
- # Always include this file to force CMake to run again next
- # invocation and rebuild the dependencies.
- #message("including dependency_file = ${dependency_file}")
- include(${dependency_file})
-
- # Now we need to verify the existence of all the included files
- # here. If they aren't there we need to just blank this variable and
- # make the file regenerate again.
-# if(DEFINED CUDA_NVCC_DEPEND)
-# message("CUDA_NVCC_DEPEND set")
-# else()
-# message("CUDA_NVCC_DEPEND NOT set")
-# endif()
- if(CUDA_NVCC_DEPEND)
- #message("CUDA_NVCC_DEPEND found")
- foreach(f ${CUDA_NVCC_DEPEND})
- # message("searching for ${f}")
- if(NOT EXISTS ${f})
- #message("file ${f} not found")
- set(CUDA_NVCC_DEPEND_REGENERATE TRUE)
- endif()
- endforeach()
- else()
- #message("CUDA_NVCC_DEPEND false")
- # No dependencies, so regenerate the file.
- set(CUDA_NVCC_DEPEND_REGENERATE TRUE)
- endif()
-
- #message("CUDA_NVCC_DEPEND_REGENERATE = ${CUDA_NVCC_DEPEND_REGENERATE}")
- # No incoming dependencies, so we need to generate them. Make the
- # output depend on the dependency file itself, which should cause the
- # rule to re-run.
- if(CUDA_NVCC_DEPEND_REGENERATE)
- set(CUDA_NVCC_DEPEND ${dependency_file})
- #message("Generating an empty dependency_file: ${dependency_file}")
- file(WRITE ${dependency_file} "#FindCUDA.cmake generated file. Do not edit.\n")
- endif()
-
-endmacro()
-
-###############################################################################
-###############################################################################
-# Setup variables' defaults
-###############################################################################
-###############################################################################
-
-# Allow the user to specify if the device code is supposed to be 32 or 64 bit.
-if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(CUDA_64_BIT_DEVICE_CODE_DEFAULT ON)
-else()
- set(CUDA_64_BIT_DEVICE_CODE_DEFAULT OFF)
-endif()
-option(CUDA_64_BIT_DEVICE_CODE "Compile device code in 64 bit mode" ${CUDA_64_BIT_DEVICE_CODE_DEFAULT})
-
-# Attach the build rule to the source file in VS. This option
-option(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE "Attach the build rule to the CUDA source file. Enable only when the CUDA source file is added to at most one target." ON)
-
-# Prints out extra information about the cuda file during compilation
-option(CUDA_BUILD_CUBIN "Generate and parse .cubin files in Device mode." OFF)
-
-# Set whether we are using emulation or device mode.
-option(CUDA_BUILD_EMULATION "Build in Emulation mode" OFF)
-
-# Where to put the generated output.
-set(CUDA_GENERATED_OUTPUT_DIR "" CACHE PATH "Directory to put all the output files. If blank it will default to the CMAKE_CURRENT_BINARY_DIR")
-
-# Parse HOST_COMPILATION mode.
-option(CUDA_HOST_COMPILATION_CPP "Generated file extension" ON)
-
-# Extra user settable flags
-set(CUDA_NVCC_FLAGS "" CACHE STRING "Semi-colon delimit multiple arguments.")
-
-if(CMAKE_GENERATOR MATCHES "Visual Studio")
- set(CUDA_HOST_COMPILER "$(VCInstallDir)bin" CACHE FILEPATH "Host side compiler used by NVCC")
-else()
- if(APPLE
- AND "${CMAKE_C_COMPILER_ID}" MATCHES "Clang"
- AND "${CMAKE_C_COMPILER}" MATCHES "/cc$")
- # Using cc which is symlink to clang may let NVCC think it is GCC and issue
- # unhandled -dumpspecs option to clang. Also in case neither
- # CMAKE_C_COMPILER is defined (project does not use C language) nor
- # CUDA_HOST_COMPILER is specified manually we should skip -ccbin and let
- # nvcc use its own default C compiler.
- # Only care about this on APPLE with clang to avoid
- # following symlinks to things like ccache
- if(DEFINED CMAKE_C_COMPILER AND NOT DEFINED CUDA_HOST_COMPILER)
- get_filename_component(c_compiler_realpath "${CMAKE_C_COMPILER}" REALPATH)
- # if the real path does not end up being clang then
- # go back to using CMAKE_C_COMPILER
- if(NOT "${c_compiler_realpath}" MATCHES "/clang$")
- set(c_compiler_realpath "${CMAKE_C_COMPILER}")
- endif()
- else()
- set(c_compiler_realpath "")
- endif()
- set(CUDA_HOST_COMPILER "${c_compiler_realpath}" CACHE FILEPATH "Host side compiler used by NVCC")
- else()
- set(CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}"
- CACHE FILEPATH "Host side compiler used by NVCC")
- endif()
-endif()
-
-# Propagate the host flags to the host compiler via -Xcompiler
-option(CUDA_PROPAGATE_HOST_FLAGS "Propage C/CXX_FLAGS and friends to the host compiler via -Xcompile" ON)
-
-# Enable CUDA_SEPARABLE_COMPILATION
-option(CUDA_SEPARABLE_COMPILATION "Compile CUDA objects with separable compilation enabled. Requires CUDA 5.0+" OFF)
-
-# Specifies whether the commands used when compiling the .cu file will be printed out.
-option(CUDA_VERBOSE_BUILD "Print out the commands run while compiling the CUDA source file. With the Makefile generator this defaults to VERBOSE variable specified on the command line, but can be forced on with this option." OFF)
-
-mark_as_advanced(
- CUDA_64_BIT_DEVICE_CODE
- CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE
- CUDA_GENERATED_OUTPUT_DIR
- CUDA_HOST_COMPILATION_CPP
- CUDA_NVCC_FLAGS
- CUDA_PROPAGATE_HOST_FLAGS
- CUDA_BUILD_CUBIN
- CUDA_BUILD_EMULATION
- CUDA_VERBOSE_BUILD
- CUDA_SEPARABLE_COMPILATION
- )
-
-# Makefile and similar generators don't define CMAKE_CONFIGURATION_TYPES, so we
-# need to add another entry for the CMAKE_BUILD_TYPE. We also need to add the
-# standerd set of 4 build types (Debug, MinSizeRel, Release, and RelWithDebInfo)
-# for completeness. We need run this loop in order to accomodate the addition
-# of extra configuration types. Duplicate entries will be removed by
-# REMOVE_DUPLICATES.
-set(CUDA_configuration_types ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE} Debug MinSizeRel Release RelWithDebInfo)
-list(REMOVE_DUPLICATES CUDA_configuration_types)
-foreach(config ${CUDA_configuration_types})
- string(TOUPPER ${config} config_upper)
- set(CUDA_NVCC_FLAGS_${config_upper} "" CACHE STRING "Semi-colon delimit multiple arguments.")
- mark_as_advanced(CUDA_NVCC_FLAGS_${config_upper})
-endforeach()
-
-###############################################################################
-###############################################################################
-# Locate CUDA, Set Build Type, etc.
-###############################################################################
-###############################################################################
-
-macro(cuda_unset_include_and_libraries)
- unset(CUDA_TOOLKIT_INCLUDE CACHE)
- unset(CUDA_CUDART_LIBRARY CACHE)
- unset(CUDA_CUDA_LIBRARY CACHE)
- # Make sure you run this before you unset CUDA_VERSION.
- if(CUDA_VERSION VERSION_EQUAL "3.0")
- # This only existed in the 3.0 version of the CUDA toolkit
- unset(CUDA_CUDARTEMU_LIBRARY CACHE)
- endif()
- unset(CUDA_cudart_static_LIBRARY CACHE)
- unset(CUDA_cublas_LIBRARY CACHE)
- unset(CUDA_cublasemu_LIBRARY CACHE)
- unset(CUDA_cufft_LIBRARY CACHE)
- unset(CUDA_cufftemu_LIBRARY CACHE)
- unset(CUDA_cupti_LIBRARY CACHE)
- unset(CUDA_curand_LIBRARY CACHE)
- unset(CUDA_cusolver_LIBRARY CACHE)
- unset(CUDA_cusparse_LIBRARY CACHE)
- unset(CUDA_npp_LIBRARY CACHE)
- unset(CUDA_nppc_LIBRARY CACHE)
- unset(CUDA_nppi_LIBRARY CACHE)
- unset(CUDA_npps_LIBRARY CACHE)
- unset(CUDA_nvcuvenc_LIBRARY CACHE)
- unset(CUDA_nvcuvid_LIBRARY CACHE)
-
- unset(CUDA_USE_STATIC_CUDA_RUNTIME CACHE)
-endmacro()
-
-# Check to see if the CUDA_TOOLKIT_ROOT_DIR and CUDA_SDK_ROOT_DIR have changed,
-# if they have then clear the cache variables, so that will be detected again.
-if(NOT "${CUDA_TOOLKIT_ROOT_DIR}" STREQUAL "${CUDA_TOOLKIT_ROOT_DIR_INTERNAL}")
- unset(CUDA_TOOLKIT_TARGET_DIR CACHE)
- unset(CUDA_NVCC_EXECUTABLE CACHE)
- cuda_unset_include_and_libraries()
- unset(CUDA_VERSION CACHE)
-endif()
-
-if(NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}")
- cuda_unset_include_and_libraries()
-endif()
-
-if(NOT "${CUDA_SDK_ROOT_DIR}" STREQUAL "${CUDA_SDK_ROOT_DIR_INTERNAL}")
- # No specific variables to catch. Use this kind of code before calling
- # find_package(CUDA) to clean up any variables that may depend on this path.
-
- # unset(MY_SPECIAL_CUDA_SDK_INCLUDE_DIR CACHE)
- # unset(MY_SPECIAL_CUDA_SDK_LIBRARY CACHE)
-endif()
-
-# Search for the cuda distribution.
-if(NOT CUDA_TOOLKIT_ROOT_DIR)
-
- # Search in the CUDA_BIN_PATH first.
- find_path(CUDA_TOOLKIT_ROOT_DIR
- NAMES nvcc nvcc.exe
- PATHS
- ENV CUDA_PATH
- ENV CUDA_BIN_PATH
- PATH_SUFFIXES bin bin64
- DOC "Toolkit location."
- NO_DEFAULT_PATH
- )
- # Now search default paths
- find_path(CUDA_TOOLKIT_ROOT_DIR
- NAMES nvcc nvcc.exe
- PATHS /usr/local/bin
- /usr/local/cuda/bin
- DOC "Toolkit location."
- )
-
- if (CUDA_TOOLKIT_ROOT_DIR)
- string(REGEX REPLACE "[/\\\\]?bin[64]*[/\\\\]?$" "" CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR})
- # We need to force this back into the cache.
- set(CUDA_TOOLKIT_ROOT_DIR ${CUDA_TOOLKIT_ROOT_DIR} CACHE PATH "Toolkit location." FORCE)
- endif()
- if (NOT EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
- if(CUDA_FIND_REQUIRED)
- message(FATAL_ERROR "Specify CUDA_TOOLKIT_ROOT_DIR")
- elseif(NOT CUDA_FIND_QUIETLY)
- message("CUDA_TOOLKIT_ROOT_DIR not found or specified")
- endif()
- endif ()
-endif ()
-
-# CUDA_NVCC_EXECUTABLE
-find_program(CUDA_NVCC_EXECUTABLE
- NAMES nvcc
- PATHS "${CUDA_TOOLKIT_ROOT_DIR}"
- ENV CUDA_PATH
- ENV CUDA_BIN_PATH
- PATH_SUFFIXES bin bin64
- NO_DEFAULT_PATH
- )
-# Search default search paths, after we search our own set of paths.
-find_program(CUDA_NVCC_EXECUTABLE nvcc)
-mark_as_advanced(CUDA_NVCC_EXECUTABLE)
-
-if(CUDA_NVCC_EXECUTABLE AND NOT CUDA_VERSION)
- # Compute the version.
- execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
- string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT})
- string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT})
- set(CUDA_VERSION "${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}" CACHE STRING "Version of CUDA as computed from nvcc.")
- mark_as_advanced(CUDA_VERSION)
-else()
- # Need to set these based off of the cached value
- string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR "${CUDA_VERSION}")
- string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR "${CUDA_VERSION}")
-endif()
-
-# Always set this convenience variable
-set(CUDA_VERSION_STRING "${CUDA_VERSION}")
-
-# Support for arm cross compilation with CUDA 5.5
-if(CUDA_VERSION VERSION_GREATER "5.0" AND CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm" AND EXISTS "${CUDA_TOOLKIT_ROOT_DIR}/targets/armv7-linux-gnueabihf")
- set(CUDA_TOOLKIT_TARGET_DIR "${CUDA_TOOLKIT_ROOT_DIR}/targets/armv7-linux-gnueabihf" CACHE PATH "Toolkit target location.")
-else()
- set(CUDA_TOOLKIT_TARGET_DIR "${CUDA_TOOLKIT_ROOT_DIR}" CACHE PATH "Toolkit target location.")
-endif()
-mark_as_advanced(CUDA_TOOLKIT_TARGET_DIR)
-
-# Target CPU architecture
-if(CUDA_VERSION VERSION_GREATER "5.0" AND CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
- set(_cuda_target_cpu_arch_initial "ARM")
-else()
- set(_cuda_target_cpu_arch_initial "")
-endif()
-set(CUDA_TARGET_CPU_ARCH ${_cuda_target_cpu_arch_initial} CACHE STRING "Specify the name of the class of CPU architecture for which the input files must be compiled.")
-mark_as_advanced(CUDA_TARGET_CPU_ARCH)
-
-# CUDA_TOOLKIT_INCLUDE
-find_path(CUDA_TOOLKIT_INCLUDE
- device_functions.h # Header included in toolkit
- PATHS "${CUDA_TOOLKIT_TARGET_DIR}" "${CUDA_TOOLKIT_ROOT_DIR}"
- ENV CUDA_PATH
- ENV CUDA_INC_PATH
- PATH_SUFFIXES include
- NO_DEFAULT_PATH
- )
-# Search default search paths, after we search our own set of paths.
-find_path(CUDA_TOOLKIT_INCLUDE device_functions.h)
-mark_as_advanced(CUDA_TOOLKIT_INCLUDE)
-
-# Set the user list of include dir to nothing to initialize it.
-set (CUDA_NVCC_INCLUDE_ARGS_USER "")
-set (CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE})
-
-macro(cuda_find_library_local_first_with_path_ext _var _names _doc _path_ext )
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- # CUDA 3.2+ on Windows moved the library directories, so we need the new
- # and old paths.
- set(_cuda_64bit_lib_dir "${_path_ext}lib/x64" "${_path_ext}lib64" "${_path_ext}libx64" )
- endif()
- # CUDA 3.2+ on Windows moved the library directories, so we need to new
- # (lib/Win32) and the old path (lib).
- find_library(${_var}
- NAMES ${_names}
- PATHS "${CUDA_TOOLKIT_TARGET_DIR}" "${CUDA_TOOLKIT_ROOT_DIR}"
- ENV CUDA_PATH
- ENV CUDA_LIB_PATH
- PATH_SUFFIXES ${_cuda_64bit_lib_dir} "${_path_ext}lib/Win32" "${_path_ext}lib" "${_path_ext}libWin32"
- DOC ${_doc}
- NO_DEFAULT_PATH
- )
- # Search default search paths, after we search our own set of paths.
- find_library(${_var}
- NAMES ${_names}
- PATHS "/usr/lib/nvidia-current"
- DOC ${_doc}
- )
-endmacro()
-
-macro(cuda_find_library_local_first _var _names _doc)
- cuda_find_library_local_first_with_path_ext( "${_var}" "${_names}" "${_doc}" "" )
-endmacro()
-
-macro(find_library_local_first _var _names _doc )
- cuda_find_library_local_first( "${_var}" "${_names}" "${_doc}" "" )
-endmacro()
-
-
-# CUDA_LIBRARIES
-cuda_find_library_local_first(CUDA_CUDART_LIBRARY cudart "\"cudart\" library")
-if(CUDA_VERSION VERSION_EQUAL "3.0")
- # The cudartemu library only existed for the 3.0 version of CUDA.
- cuda_find_library_local_first(CUDA_CUDARTEMU_LIBRARY cudartemu "\"cudartemu\" library")
- mark_as_advanced(
- CUDA_CUDARTEMU_LIBRARY
- )
-endif()
-if(NOT CUDA_VERSION VERSION_LESS "5.5")
- cuda_find_library_local_first(CUDA_cudart_static_LIBRARY cudart_static "static CUDA runtime library")
- mark_as_advanced(CUDA_cudart_static_LIBRARY)
-endif()
-if(CUDA_cudart_static_LIBRARY)
- # Set whether to use the static cuda runtime.
- option(CUDA_USE_STATIC_CUDA_RUNTIME "Use the static version of the CUDA runtime library if available" ON)
-else()
- option(CUDA_USE_STATIC_CUDA_RUNTIME "Use the static version of the CUDA runtime library if available" OFF)
-endif()
-
-if(CUDA_USE_STATIC_CUDA_RUNTIME)
- if(UNIX)
- # Check for the dependent libraries. Here we look for pthreads.
- if (DEFINED CMAKE_THREAD_PREFER_PTHREAD)
- set(_cuda_cmake_thread_prefer_pthread ${CMAKE_THREAD_PREFER_PTHREAD})
- endif()
- set(CMAKE_THREAD_PREFER_PTHREAD 1)
-
- # Many of the FindXYZ CMake comes with makes use of try_compile with int main(){return 0;}
- # as the source file. Unfortunately this causes a warning with -Wstrict-prototypes and
- # -Werror causes the try_compile to fail. We will just temporarily disable other flags
- # when doing the find_package command here.
- set(_cuda_cmake_c_flags ${CMAKE_C_FLAGS})
- set(CMAKE_C_FLAGS "-fPIC")
- find_package(Threads REQUIRED)
- set(CMAKE_C_FLAGS ${_cuda_cmake_c_flags})
-
- if (DEFINED _cuda_cmake_thread_prefer_pthread)
- set(CMAKE_THREAD_PREFER_PTHREAD ${_cuda_cmake_thread_prefer_pthread})
- unset(_cuda_cmake_thread_prefer_pthread)
- else()
- unset(CMAKE_THREAD_PREFER_PTHREAD)
- endif()
- if (NOT APPLE)
- # Here is librt that has things such as, clock_gettime, shm_open, and shm_unlink.
- find_library(CUDA_rt_LIBRARY rt)
- find_library(CUDA_dl_LIBRARY dl)
- if (NOT CUDA_rt_LIBRARY)
- message(WARNING "Expecting to find librt for libcudart_static, but didn't find it.")
- endif()
- if (NOT CUDA_dl_LIBRARY)
- message(WARNING "Expecting to find libdl for libcudart_static, but didn't find it.")
- endif()
- endif()
- endif()
-endif()
-
-# CUPTI library showed up in cuda toolkit 4.0
-if(NOT CUDA_VERSION VERSION_LESS "4.0")
- cuda_find_library_local_first_with_path_ext(CUDA_cupti_LIBRARY cupti "\"cupti\" library" "extras/CUPTI/")
- mark_as_advanced(CUDA_cupti_LIBRARY)
-endif()
-
-# Set the CUDA_LIBRARIES variable. This is the set of stuff to link against if you are
-# using the CUDA runtime. For the dynamic version of the runtime, most of the
-# dependencies are brough in, but for the static version there are additional libraries
-# and linker commands needed.
-# Initialize to empty
-set(CUDA_LIBRARIES)
-
-# If we are using emulation mode and we found the cudartemu library then use
-# that one instead of cudart.
-if(CUDA_BUILD_EMULATION AND CUDA_CUDARTEMU_LIBRARY)
- list(APPEND CUDA_LIBRARIES ${CUDA_CUDARTEMU_LIBRARY})
-elseif(CUDA_USE_STATIC_CUDA_RUNTIME AND CUDA_cudart_static_LIBRARY)
- list(APPEND CUDA_LIBRARIES ${CUDA_cudart_static_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
- if (CUDA_rt_LIBRARY)
- list(APPEND CUDA_LIBRARIES ${CUDA_rt_LIBRARY})
- endif()
- if (CUDA_dl_LIBRARY)
- list(APPEND CUDA_LIBRARIES ${CUDA_dl_LIBRARY})
- endif()
- if(APPLE)
- # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that
- # the static cuda runtime can find it at runtime.
- list(APPEND CUDA_LIBRARIES -Wl,-rpath,/usr/local/cuda/lib)
- endif()
-else()
- list(APPEND CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY})
-endif()
-
-# 1.1 toolkit on linux doesn't appear to have a separate library on
-# some platforms.
-cuda_find_library_local_first(CUDA_CUDA_LIBRARY cuda "\"cuda\" library (older versions only).")
-
-mark_as_advanced(
- CUDA_CUDA_LIBRARY
- CUDA_CUDART_LIBRARY
- )
-
-#######################
-# Look for some of the toolkit helper libraries
-macro(FIND_CUDA_HELPER_LIBS _name)
- cuda_find_library_local_first(CUDA_${_name}_LIBRARY ${_name} "\"${_name}\" library")
- mark_as_advanced(CUDA_${_name}_LIBRARY)
-endmacro()
-
-#######################
-# Disable emulation for v3.1 onward
-if(CUDA_VERSION VERSION_GREATER "3.0")
- if(CUDA_BUILD_EMULATION)
- message(FATAL_ERROR "CUDA_BUILD_EMULATION is not supported in version 3.1 and onwards. You must disable it to proceed. You have version ${CUDA_VERSION}.")
- endif()
-endif()
-
-# Search for additional CUDA toolkit libraries.
-if(CUDA_VERSION VERSION_LESS "3.1")
- # Emulation libraries aren't available in version 3.1 onward.
- find_cuda_helper_libs(cufftemu)
- find_cuda_helper_libs(cublasemu)
-endif()
-find_cuda_helper_libs(cufft)
-find_cuda_helper_libs(cublas)
-if(NOT CUDA_VERSION VERSION_LESS "3.2")
- # cusparse showed up in version 3.2
- find_cuda_helper_libs(cusparse)
- find_cuda_helper_libs(curand)
- if (WIN32)
- find_cuda_helper_libs(nvcuvenc)
- find_cuda_helper_libs(nvcuvid)
- endif()
-endif()
-if(CUDA_VERSION VERSION_GREATER "5.0")
- # In CUDA 5.5 NPP was splitted onto 3 separate libraries.
- find_cuda_helper_libs(nppc)
- find_cuda_helper_libs(nppi)
- find_cuda_helper_libs(npps)
- set(CUDA_npp_LIBRARY "${CUDA_nppc_LIBRARY};${CUDA_nppi_LIBRARY};${CUDA_npps_LIBRARY}")
-elseif(NOT CUDA_VERSION VERSION_LESS "4.0")
- find_cuda_helper_libs(npp)
-endif()
-if(NOT CUDA_VERSION VERSION_LESS "7.0")
- # cusolver showed up in version 7.0
- find_cuda_helper_libs(cusolver)
-endif()
-
-if (CUDA_BUILD_EMULATION)
- set(CUDA_CUFFT_LIBRARIES ${CUDA_cufftemu_LIBRARY})
- set(CUDA_CUBLAS_LIBRARIES ${CUDA_cublasemu_LIBRARY})
-else()
- set(CUDA_CUFFT_LIBRARIES ${CUDA_cufft_LIBRARY})
- set(CUDA_CUBLAS_LIBRARIES ${CUDA_cublas_LIBRARY})
-endif()
-
-########################
-# Look for the SDK stuff. As of CUDA 3.0 NVSDKCUDA_ROOT has been replaced with
-# NVSDKCOMPUTE_ROOT with the old CUDA C contents moved into the C subdirectory
-find_path(CUDA_SDK_ROOT_DIR common/inc/cutil.h
- HINTS
- "$ENV{NVSDKCOMPUTE_ROOT}/C"
- ENV NVSDKCUDA_ROOT
- "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Installed Products\\NVIDIA SDK 10\\Compute;InstallDir]"
- PATHS
- "/Developer/GPU\ Computing/C"
- )
-
-# Keep the CUDA_SDK_ROOT_DIR first in order to be able to override the
-# environment variables.
-set(CUDA_SDK_SEARCH_PATH
- "${CUDA_SDK_ROOT_DIR}"
- "${CUDA_TOOLKIT_ROOT_DIR}/local/NVSDK0.2"
- "${CUDA_TOOLKIT_ROOT_DIR}/NVSDK0.2"
- "${CUDA_TOOLKIT_ROOT_DIR}/NV_CUDA_SDK"
- "$ENV{HOME}/NVIDIA_CUDA_SDK"
- "$ENV{HOME}/NVIDIA_CUDA_SDK_MACOSX"
- "/Developer/CUDA"
- )
-
-# Example of how to find an include file from the CUDA_SDK_ROOT_DIR
-
-# find_path(CUDA_CUT_INCLUDE_DIR
-# cutil.h
-# PATHS ${CUDA_SDK_SEARCH_PATH}
-# PATH_SUFFIXES "common/inc"
-# DOC "Location of cutil.h"
-# NO_DEFAULT_PATH
-# )
-# # Now search system paths
-# find_path(CUDA_CUT_INCLUDE_DIR cutil.h DOC "Location of cutil.h")
-
-# mark_as_advanced(CUDA_CUT_INCLUDE_DIR)
-
-
-# Example of how to find a library in the CUDA_SDK_ROOT_DIR
-
-# # cutil library is called cutil64 for 64 bit builds on windows. We don't want
-# # to get these confused, so we are setting the name based on the word size of
-# # the build.
-
-# if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-# set(cuda_cutil_name cutil64)
-# else()
-# set(cuda_cutil_name cutil32)
-# endif()
-
-# find_library(CUDA_CUT_LIBRARY
-# NAMES cutil ${cuda_cutil_name}
-# PATHS ${CUDA_SDK_SEARCH_PATH}
-# # The new version of the sdk shows up in common/lib, but the old one is in lib
-# PATH_SUFFIXES "common/lib" "lib"
-# DOC "Location of cutil library"
-# NO_DEFAULT_PATH
-# )
-# # Now search system paths
-# find_library(CUDA_CUT_LIBRARY NAMES cutil ${cuda_cutil_name} DOC "Location of cutil library")
-# mark_as_advanced(CUDA_CUT_LIBRARY)
-# set(CUDA_CUT_LIBRARIES ${CUDA_CUT_LIBRARY})
-
-
-
-#############################
-# Check for required components
-set(CUDA_FOUND TRUE)
-
-set(CUDA_TOOLKIT_ROOT_DIR_INTERNAL "${CUDA_TOOLKIT_ROOT_DIR}" CACHE INTERNAL
- "This is the value of the last time CUDA_TOOLKIT_ROOT_DIR was set successfully." FORCE)
-set(CUDA_TOOLKIT_TARGET_DIR_INTERNAL "${CUDA_TOOLKIT_TARGET_DIR}" CACHE INTERNAL
- "This is the value of the last time CUDA_TOOLKIT_TARGET_DIR was set successfully." FORCE)
-set(CUDA_SDK_ROOT_DIR_INTERNAL "${CUDA_SDK_ROOT_DIR}" CACHE INTERNAL
- "This is the value of the last time CUDA_SDK_ROOT_DIR was set successfully." FORCE)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(CUDA
- REQUIRED_VARS
- CUDA_TOOLKIT_ROOT_DIR
- CUDA_NVCC_EXECUTABLE
- CUDA_INCLUDE_DIRS
- CUDA_CUDART_LIBRARY
- VERSION_VAR
- CUDA_VERSION
- )
-
-
-
-###############################################################################
-###############################################################################
-# Macros
-###############################################################################
-###############################################################################
-
-###############################################################################
-# Add include directories to pass to the nvcc command.
-macro(CUDA_INCLUDE_DIRECTORIES)
- foreach(dir ${ARGN})
- list(APPEND CUDA_NVCC_INCLUDE_ARGS_USER -I${dir})
- endforeach()
-endmacro()
-
-
-##############################################################################
-cuda_find_helper_file(parse_cubin cmake)
-cuda_find_helper_file(make2cmake cmake)
-cuda_find_helper_file(run_nvcc cmake)
-
-##############################################################################
-# Separate the OPTIONS out from the sources
-#
-macro(CUDA_GET_SOURCES_AND_OPTIONS _sources _cmake_options _options)
- set( ${_sources} )
- set( ${_cmake_options} )
- set( ${_options} )
- set( _found_options FALSE )
- foreach(arg ${ARGN})
- if("x${arg}" STREQUAL "xOPTIONS")
- set( _found_options TRUE )
- elseif(
- "x${arg}" STREQUAL "xWIN32" OR
- "x${arg}" STREQUAL "xMACOSX_BUNDLE" OR
- "x${arg}" STREQUAL "xEXCLUDE_FROM_ALL" OR
- "x${arg}" STREQUAL "xSTATIC" OR
- "x${arg}" STREQUAL "xSHARED" OR
- "x${arg}" STREQUAL "xMODULE"
- )
- list(APPEND ${_cmake_options} ${arg})
- else()
- if ( _found_options )
- list(APPEND ${_options} ${arg})
- else()
- # Assume this is a file
- list(APPEND ${_sources} ${arg})
- endif()
- endif()
- endforeach()
-endmacro()
-
-##############################################################################
-# Parse the OPTIONS from ARGN and set the variables prefixed by _option_prefix
-#
-macro(CUDA_PARSE_NVCC_OPTIONS _option_prefix)
- set( _found_config )
- foreach(arg ${ARGN})
- # Determine if we are dealing with a perconfiguration flag
- foreach(config ${CUDA_configuration_types})
- string(TOUPPER ${config} config_upper)
- if (arg STREQUAL "${config_upper}")
- set( _found_config _${arg})
- # Set arg to nothing to keep it from being processed further
- set( arg )
- endif()
- endforeach()
-
- if ( arg )
- list(APPEND ${_option_prefix}${_found_config} "${arg}")
- endif()
- endforeach()
-endmacro()
-
-##############################################################################
-# Helper to add the include directory for CUDA only once
-function(CUDA_ADD_CUDA_INCLUDE_ONCE)
- get_directory_property(_include_directories INCLUDE_DIRECTORIES)
- set(_add TRUE)
- if(_include_directories)
- foreach(dir ${_include_directories})
- if("${dir}" STREQUAL "${CUDA_INCLUDE_DIRS}")
- set(_add FALSE)
- endif()
- endforeach()
- endif()
- if(_add)
- include_directories(${CUDA_INCLUDE_DIRS})
- endif()
-endfunction()
-
-function(CUDA_BUILD_SHARED_LIBRARY shared_flag)
- set(cmake_args ${ARGN})
- # If SHARED, MODULE, or STATIC aren't already in the list of arguments, then
- # add SHARED or STATIC based on the value of BUILD_SHARED_LIBS.
- list(FIND cmake_args SHARED _cuda_found_SHARED)
- list(FIND cmake_args MODULE _cuda_found_MODULE)
- list(FIND cmake_args STATIC _cuda_found_STATIC)
- if( _cuda_found_SHARED GREATER -1 OR
- _cuda_found_MODULE GREATER -1 OR
- _cuda_found_STATIC GREATER -1)
- set(_cuda_build_shared_libs)
- else()
- if (BUILD_SHARED_LIBS)
- set(_cuda_build_shared_libs SHARED)
- else()
- set(_cuda_build_shared_libs STATIC)
- endif()
- endif()
- set(${shared_flag} ${_cuda_build_shared_libs} PARENT_SCOPE)
-endfunction()
-
-##############################################################################
-# Helper to avoid clashes of files with the same basename but different paths.
-# This doesn't attempt to do exactly what CMake internals do, which is to only
-# add this path when there is a conflict, since by the time a second collision
-# in names is detected it's already too late to fix the first one. For
-# consistency sake the relative path will be added to all files.
-function(CUDA_COMPUTE_BUILD_PATH path build_path)
- #message("CUDA_COMPUTE_BUILD_PATH([${path}] ${build_path})")
- # Only deal with CMake style paths from here on out
- file(TO_CMAKE_PATH "${path}" bpath)
- if (IS_ABSOLUTE "${bpath}")
- # Absolute paths are generally unnessary, especially if something like
- # file(GLOB_RECURSE) is used to pick up the files.
-
- string(FIND "${bpath}" "${CMAKE_CURRENT_BINARY_DIR}" _binary_dir_pos)
- if (_binary_dir_pos EQUAL 0)
- file(RELATIVE_PATH bpath "${CMAKE_CURRENT_BINARY_DIR}" "${bpath}")
- else()
- file(RELATIVE_PATH bpath "${CMAKE_CURRENT_SOURCE_DIR}" "${bpath}")
- endif()
- endif()
-
- # This recipe is from cmLocalGenerator::CreateSafeUniqueObjectFileName in the
- # CMake source.
-
- # Remove leading /
- string(REGEX REPLACE "^[/]+" "" bpath "${bpath}")
- # Avoid absolute paths by removing ':'
- string(REPLACE ":" "_" bpath "${bpath}")
- # Avoid relative paths that go up the tree
- string(REPLACE "../" "__/" bpath "${bpath}")
- # Avoid spaces
- string(REPLACE " " "_" bpath "${bpath}")
-
- # Strip off the filename. I wait until here to do it, since removin the
- # basename can make a path that looked like path/../basename turn into
- # path/.. (notice the trailing slash).
- get_filename_component(bpath "${bpath}" PATH)
-
- set(${build_path} "${bpath}" PARENT_SCOPE)
- #message("${build_path} = ${bpath}")
-endfunction()
-
-##############################################################################
-# This helper macro populates the following variables and setups up custom
-# commands and targets to invoke the nvcc compiler to generate C or PTX source
-# dependent upon the format parameter. The compiler is invoked once with -M
-# to generate a dependency file and a second time with -cuda or -ptx to generate
-# a .cpp or .ptx file.
-# INPUT:
-# cuda_target - Target name
-# format - PTX, CUBIN, FATBIN or OBJ
-# FILE1 .. FILEN - The remaining arguments are the sources to be wrapped.
-# OPTIONS - Extra options to NVCC
-# OUTPUT:
-# generated_files - List of generated files
-##############################################################################
-##############################################################################
-
-macro(CUDA_WRAP_SRCS cuda_target format generated_files)
-
- # If CMake doesn't support separable compilation, complain
- if(CUDA_SEPARABLE_COMPILATION AND CMAKE_VERSION VERSION_LESS "2.8.10.1")
- message(SEND_ERROR "CUDA_SEPARABLE_COMPILATION isn't supported for CMake versions less than 2.8.10.1")
- endif()
-
- # Set up all the command line flags here, so that they can be overridden on a per target basis.
-
- set(nvcc_flags "")
-
- # Emulation if the card isn't present.
- if (CUDA_BUILD_EMULATION)
- # Emulation.
- set(nvcc_flags ${nvcc_flags} --device-emulation -D_DEVICEEMU -g)
- else()
- # Device mode. No flags necessary.
- endif()
-
- if(CUDA_HOST_COMPILATION_CPP)
- set(CUDA_C_OR_CXX CXX)
- else()
- if(CUDA_VERSION VERSION_LESS "3.0")
- set(nvcc_flags ${nvcc_flags} --host-compilation C)
- else()
- message(WARNING "--host-compilation flag is deprecated in CUDA version >= 3.0. Removing --host-compilation C flag" )
- endif()
- set(CUDA_C_OR_CXX C)
- endif()
-
- set(generated_extension ${CMAKE_${CUDA_C_OR_CXX}_OUTPUT_EXTENSION})
-
- if(CUDA_64_BIT_DEVICE_CODE)
- set(nvcc_flags ${nvcc_flags} -m64)
- else()
- set(nvcc_flags ${nvcc_flags} -m32)
- endif()
-
- if(CUDA_TARGET_CPU_ARCH)
- set(nvcc_flags ${nvcc_flags} "--target-cpu-architecture=${CUDA_TARGET_CPU_ARCH}")
- endif()
-
- # This needs to be passed in at this stage, because VS needs to fill out the
- # value of VCInstallDir from within VS. Note that CCBIN is only used if
- # -ccbin or --compiler-bindir isn't used and CUDA_HOST_COMPILER matches
- # $(VCInstallDir)/bin.
- if(CMAKE_GENERATOR MATCHES "Visual Studio")
- set(ccbin_flags -D "\"CCBIN:PATH=$(VCInstallDir)bin\"" )
- else()
- set(ccbin_flags)
- endif()
-
- # Figure out which configure we will use and pass that in as an argument to
- # the script. We need to defer the decision until compilation time, because
- # for VS projects we won't know if we are making a debug or release build
- # until build time.
- if(CMAKE_GENERATOR MATCHES "Visual Studio")
- set( CUDA_build_configuration "$(ConfigurationName)" )
- else()
- set( CUDA_build_configuration "${CMAKE_BUILD_TYPE}")
- endif()
-
- # Initialize our list of includes with the user ones followed by the CUDA system ones.
- set(CUDA_NVCC_INCLUDE_ARGS ${CUDA_NVCC_INCLUDE_ARGS_USER} --system-include;${CUDA_INCLUDE_DIRS})
- # Get the include directories for this directory and use them for our nvcc command.
- # Remove duplicate entries which may be present since include_directories
- # in CMake >= 2.8.8 does not remove them.
- get_directory_property(CUDA_NVCC_INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES)
- list(REMOVE_DUPLICATES CUDA_NVCC_INCLUDE_DIRECTORIES)
- if(CUDA_NVCC_INCLUDE_DIRECTORIES)
- foreach(dir ${CUDA_NVCC_INCLUDE_DIRECTORIES})
- list(APPEND CUDA_NVCC_INCLUDE_ARGS --include-path;${dir})
- endforeach()
- endif()
-
- # Reset these variables
- set(CUDA_WRAP_OPTION_NVCC_FLAGS)
- foreach(config ${CUDA_configuration_types})
- string(TOUPPER ${config} config_upper)
- set(CUDA_WRAP_OPTION_NVCC_FLAGS_${config_upper})
- endforeach()
-
- CUDA_GET_SOURCES_AND_OPTIONS(_cuda_wrap_sources _cuda_wrap_cmake_options _cuda_wrap_options ${ARGN})
- CUDA_PARSE_NVCC_OPTIONS(CUDA_WRAP_OPTION_NVCC_FLAGS ${_cuda_wrap_options})
-
- # Figure out if we are building a shared library. BUILD_SHARED_LIBS is
- # respected in CUDA_ADD_LIBRARY.
- set(_cuda_build_shared_libs FALSE)
- # SHARED, MODULE
- list(FIND _cuda_wrap_cmake_options SHARED _cuda_found_SHARED)
- list(FIND _cuda_wrap_cmake_options MODULE _cuda_found_MODULE)
- if(_cuda_found_SHARED GREATER -1 OR _cuda_found_MODULE GREATER -1)
- set(_cuda_build_shared_libs TRUE)
- endif()
- # STATIC
- list(FIND _cuda_wrap_cmake_options STATIC _cuda_found_STATIC)
- if(_cuda_found_STATIC GREATER -1)
- set(_cuda_build_shared_libs FALSE)
- endif()
-
- # CUDA_HOST_FLAGS
- if(_cuda_build_shared_libs)
- # If we are setting up code for a shared library, then we need to add extra flags for
- # compiling objects for shared libraries.
- set(CUDA_HOST_SHARED_FLAGS ${CMAKE_SHARED_LIBRARY_${CUDA_C_OR_CXX}_FLAGS})
- else()
- set(CUDA_HOST_SHARED_FLAGS)
- endif()
- # Only add the CMAKE_{C,CXX}_FLAGS if we are propagating host flags. We
- # always need to set the SHARED_FLAGS, though.
- if(CUDA_PROPAGATE_HOST_FLAGS)
- set(_cuda_host_flags "set(CMAKE_HOST_FLAGS ${CMAKE_${CUDA_C_OR_CXX}_FLAGS} ${CUDA_HOST_SHARED_FLAGS})")
- else()
- set(_cuda_host_flags "set(CMAKE_HOST_FLAGS ${CUDA_HOST_SHARED_FLAGS})")
- endif()
-
- set(_cuda_nvcc_flags_config "# Build specific configuration flags")
- # Loop over all the configuration types to generate appropriate flags for run_nvcc.cmake
- foreach(config ${CUDA_configuration_types})
- string(TOUPPER ${config} config_upper)
- # CMAKE_FLAGS are strings and not lists. By not putting quotes around CMAKE_FLAGS
- # we convert the strings to lists (like we want).
-
- if(CUDA_PROPAGATE_HOST_FLAGS)
- # nvcc chokes on -g3 in versions previous to 3.0, so replace it with -g
- set(_cuda_fix_g3 FALSE)
-
- if(CMAKE_COMPILER_IS_GNUCC)
- if (CUDA_VERSION VERSION_LESS "3.0" OR
- CUDA_VERSION VERSION_EQUAL "4.1" OR
- CUDA_VERSION VERSION_EQUAL "4.2"
- )
- set(_cuda_fix_g3 TRUE)
- endif()
- endif()
- if(_cuda_fix_g3)
- string(REPLACE "-g3" "-g" _cuda_C_FLAGS "${CMAKE_${CUDA_C_OR_CXX}_FLAGS_${config_upper}}")
- else()
- set(_cuda_C_FLAGS "${CMAKE_${CUDA_C_OR_CXX}_FLAGS_${config_upper}}")
- endif()
-
- set(_cuda_host_flags "${_cuda_host_flags}\nset(CMAKE_HOST_FLAGS_${config_upper} ${_cuda_C_FLAGS})")
- endif()
-
- # Note that if we ever want CUDA_NVCC_FLAGS_<CONFIG> to be string (instead of a list
- # like it is currently), we can remove the quotes around the
- # ${CUDA_NVCC_FLAGS_${config_upper}} variable like the CMAKE_HOST_FLAGS_<CONFIG> variable.
- set(_cuda_nvcc_flags_config "${_cuda_nvcc_flags_config}\nset(CUDA_NVCC_FLAGS_${config_upper} ${CUDA_NVCC_FLAGS_${config_upper}} ;; ${CUDA_WRAP_OPTION_NVCC_FLAGS_${config_upper}})")
- endforeach()
-
- # Process the C++11 flag. If the host sets the flag, we need to add it to nvcc and
- # remove it from the host. This is because -Xcompile -std=c++ will choke nvcc (it uses
- # the C preprocessor). In order to get this to work correctly, we need to use nvcc's
- # specific c++11 flag.
- if( "${_cuda_host_flags}" MATCHES "-std=c\\+\\+11")
- # Add the c++11 flag to nvcc if it isn't already present. Note that we only look at
- # the main flag instead of the configuration specific flags.
- if( NOT "${CUDA_NVCC_FLAGS}" MATCHES "-std;c\\+\\+11" )
- list(APPEND nvcc_flags --std c++11)
- endif()
- string(REGEX REPLACE "[-]+std=c\\+\\+11" "" _cuda_host_flags "${_cuda_host_flags}")
- endif()
-
- # Get the list of definitions from the directory property
- get_directory_property(CUDA_NVCC_DEFINITIONS COMPILE_DEFINITIONS)
- if(CUDA_NVCC_DEFINITIONS)
- foreach(_definition ${CUDA_NVCC_DEFINITIONS})
- list(APPEND nvcc_flags "-D${_definition}")
- endforeach()
- endif()
-
- if(_cuda_build_shared_libs)
- list(APPEND nvcc_flags "-D${cuda_target}_EXPORTS")
- endif()
-
- # Reset the output variable
- set(_cuda_wrap_generated_files "")
-
- # Iterate over the macro arguments and create custom
- # commands for all the .cu files.
- foreach(file ${ARGN})
- # Ignore any file marked as a HEADER_FILE_ONLY
- get_source_file_property(_is_header ${file} HEADER_FILE_ONLY)
- # Allow per source file overrides of the format. Also allows compiling non-.cu files.
- get_source_file_property(_cuda_source_format ${file} CUDA_SOURCE_PROPERTY_FORMAT)
- if((${file} MATCHES "\\.cu$" OR _cuda_source_format) AND NOT _is_header)
-
- if(NOT _cuda_source_format)
- set(_cuda_source_format ${format})
- endif()
- # If file isn't a .cu file, we need to tell nvcc to treat it as such.
- if(NOT ${file} MATCHES "\\.cu$")
- set(cuda_language_flag -x=cu)
- else()
- set(cuda_language_flag)
- endif()
-
- if( ${_cuda_source_format} MATCHES "OBJ")
- set( cuda_compile_to_external_module OFF )
- else()
- set( cuda_compile_to_external_module ON )
- if( ${_cuda_source_format} MATCHES "PTX" )
- set( cuda_compile_to_external_module_type "ptx" )
- elseif( ${_cuda_source_format} MATCHES "CUBIN")
- set( cuda_compile_to_external_module_type "cubin" )
- elseif( ${_cuda_source_format} MATCHES "FATBIN")
- set( cuda_compile_to_external_module_type "fatbin" )
- else()
- message( FATAL_ERROR "Invalid format flag passed to CUDA_WRAP_SRCS or set with CUDA_SOURCE_PROPERTY_FORMAT file property for file '${file}': '${_cuda_source_format}'. Use OBJ, PTX, CUBIN or FATBIN.")
- endif()
- endif()
-
- if(cuda_compile_to_external_module)
- # Don't use any of the host compilation flags for PTX targets.
- set(CUDA_HOST_FLAGS)
- set(CUDA_NVCC_FLAGS_CONFIG)
- else()
- set(CUDA_HOST_FLAGS ${_cuda_host_flags})
- set(CUDA_NVCC_FLAGS_CONFIG ${_cuda_nvcc_flags_config})
- endif()
-
- # Determine output directory
- cuda_compute_build_path("${file}" cuda_build_path)
- set(cuda_compile_intermediate_directory "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${cuda_target}.dir/${cuda_build_path}")
- if(CUDA_GENERATED_OUTPUT_DIR)
- set(cuda_compile_output_dir "${CUDA_GENERATED_OUTPUT_DIR}")
- else()
- if ( cuda_compile_to_external_module )
- set(cuda_compile_output_dir "${CMAKE_CURRENT_BINARY_DIR}")
- else()
- set(cuda_compile_output_dir "${cuda_compile_intermediate_directory}")
- endif()
- endif()
-
- # Add a custom target to generate a c or ptx file. ######################
-
- get_filename_component( basename ${file} NAME )
- if( cuda_compile_to_external_module )
- set(generated_file_path "${cuda_compile_output_dir}")
- set(generated_file_basename "${cuda_target}_generated_${basename}.${cuda_compile_to_external_module_type}")
- set(format_flag "-${cuda_compile_to_external_module_type}")
- file(MAKE_DIRECTORY "${cuda_compile_output_dir}")
- else()
- set(generated_file_path "${cuda_compile_output_dir}/${CMAKE_CFG_INTDIR}")
- set(generated_file_basename "${cuda_target}_generated_${basename}${generated_extension}")
- if(CUDA_SEPARABLE_COMPILATION)
- set(format_flag "-dc")
- else()
- set(format_flag "-c")
- endif()
- endif()
-
- # Set all of our file names. Make sure that whatever filenames that have
- # generated_file_path in them get passed in through as a command line
- # argument, so that the ${CMAKE_CFG_INTDIR} gets expanded at run time
- # instead of configure time.
- set(generated_file "${generated_file_path}/${generated_file_basename}")
- set(cmake_dependency_file "${cuda_compile_intermediate_directory}/${generated_file_basename}.depend")
- set(NVCC_generated_dependency_file "${cuda_compile_intermediate_directory}/${generated_file_basename}.NVCC-depend")
- set(generated_cubin_file "${generated_file_path}/${generated_file_basename}.cubin.txt")
- set(custom_target_script "${cuda_compile_intermediate_directory}/${generated_file_basename}.cmake")
-
- # Setup properties for obj files:
- if( NOT cuda_compile_to_external_module )
- set_source_files_properties("${generated_file}"
- PROPERTIES
- EXTERNAL_OBJECT true # This is an object file not to be compiled, but only be linked.
- )
- endif()
-
- # Don't add CMAKE_CURRENT_SOURCE_DIR if the path is already an absolute path.
- get_filename_component(file_path "${file}" PATH)
- if(IS_ABSOLUTE "${file_path}")
- set(source_file "${file}")
- else()
- set(source_file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
- endif()
-
- if( NOT cuda_compile_to_external_module AND CUDA_SEPARABLE_COMPILATION)
- list(APPEND ${cuda_target}_SEPARABLE_COMPILATION_OBJECTS "${generated_file}")
- endif()
-
- # Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND #######
- cuda_include_nvcc_dependencies(${cmake_dependency_file})
-
- # Convience string for output ###########################################
- if(CUDA_BUILD_EMULATION)
- set(cuda_build_type "Emulation")
- else()
- set(cuda_build_type "Device")
- endif()
-
- # Build the NVCC made dependency file ###################################
- set(build_cubin OFF)
- if ( NOT CUDA_BUILD_EMULATION AND CUDA_BUILD_CUBIN )
- if ( NOT cuda_compile_to_external_module )
- set ( build_cubin ON )
- endif()
- endif()
-
- # Configure the build script
- configure_file("${CUDA_run_nvcc}" "${custom_target_script}" @ONLY)
-
- # So if a user specifies the same cuda file as input more than once, you
- # can have bad things happen with dependencies. Here we check an option
- # to see if this is the behavior they want.
- if(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE)
- set(main_dep MAIN_DEPENDENCY ${source_file})
- else()
- set(main_dep DEPENDS ${source_file})
- endif()
-
- if(CUDA_VERBOSE_BUILD)
- set(verbose_output ON)
- elseif(CMAKE_GENERATOR MATCHES "Makefiles")
- set(verbose_output "$(VERBOSE)")
- else()
- set(verbose_output OFF)
- endif()
-
- # Create up the comment string
- file(RELATIVE_PATH generated_file_relative_path "${CMAKE_BINARY_DIR}" "${generated_file}")
- if(cuda_compile_to_external_module)
- set(cuda_build_comment_string "Building NVCC ${cuda_compile_to_external_module_type} file ${generated_file_relative_path}")
- else()
- set(cuda_build_comment_string "Building NVCC (${cuda_build_type}) object ${generated_file_relative_path}")
- endif()
-
- # Build the generated file and dependency file ##########################
- add_custom_command(
- OUTPUT ${generated_file}
- # These output files depend on the source_file and the contents of cmake_dependency_file
- ${main_dep}
- DEPENDS ${CUDA_NVCC_DEPEND}
- DEPENDS ${custom_target_script}
- # Make sure the output directory exists before trying to write to it.
- COMMAND ${CMAKE_COMMAND} -E make_directory "${generated_file_path}"
- COMMAND ${CMAKE_COMMAND} ARGS
- -D verbose:BOOL=${verbose_output}
- ${ccbin_flags}
- -D build_configuration:STRING=${CUDA_build_configuration}
- -D "generated_file:STRING=${generated_file}"
- -D "generated_cubin_file:STRING=${generated_cubin_file}"
- -P "${custom_target_script}"
- WORKING_DIRECTORY "${cuda_compile_intermediate_directory}"
- COMMENT "${cuda_build_comment_string}"
- )
-
- # Make sure the build system knows the file is generated.
- set_source_files_properties(${generated_file} PROPERTIES GENERATED TRUE)
-
- list(APPEND _cuda_wrap_generated_files ${generated_file})
-
- # Add the other files that we want cmake to clean on a cleanup ##########
- list(APPEND CUDA_ADDITIONAL_CLEAN_FILES "${cmake_dependency_file}")
- list(REMOVE_DUPLICATES CUDA_ADDITIONAL_CLEAN_FILES)
- set(CUDA_ADDITIONAL_CLEAN_FILES ${CUDA_ADDITIONAL_CLEAN_FILES} CACHE INTERNAL "List of intermediate files that are part of the cuda dependency scanning.")
-
- endif()
- endforeach()
-
- # Set the return parameter
- set(${generated_files} ${_cuda_wrap_generated_files})
-endmacro()
-
-function(_cuda_get_important_host_flags important_flags flag_string)
- if(CMAKE_GENERATOR MATCHES "Visual Studio")
- string(REGEX MATCHALL "/M[DT][d]?" flags "${flag_string}")
- list(APPEND ${important_flags} ${flags})
- else()
- string(REGEX MATCHALL "-fPIC" flags "${flag_string}")
- list(APPEND ${important_flags} ${flags})
- endif()
- set(${important_flags} ${${important_flags}} PARENT_SCOPE)
-endfunction()
-
-###############################################################################
-###############################################################################
-# Separable Compilation Link
-###############################################################################
-###############################################################################
-
-# Compute the filename to be used by CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS
-function(CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME output_file_var cuda_target object_files)
- if (object_files)
- set(generated_extension ${CMAKE_${CUDA_C_OR_CXX}_OUTPUT_EXTENSION})
- set(output_file "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${cuda_target}.dir/${CMAKE_CFG_INTDIR}/${cuda_target}_intermediate_link${generated_extension}")
- else()
- set(output_file)
- endif()
-
- set(${output_file_var} "${output_file}" PARENT_SCOPE)
-endfunction()
-
-# Setup the build rule for the separable compilation intermediate link file.
-function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options object_files)
- if (object_files)
-
- set_source_files_properties("${output_file}"
- PROPERTIES
- EXTERNAL_OBJECT TRUE # This is an object file not to be compiled, but only
- # be linked.
- GENERATED TRUE # This file is generated during the build
- )
-
- # For now we are ignoring all the configuration specific flags.
- set(nvcc_flags)
- CUDA_PARSE_NVCC_OPTIONS(nvcc_flags ${options})
- if(CUDA_64_BIT_DEVICE_CODE)
- list(APPEND nvcc_flags -m64)
- else()
- list(APPEND nvcc_flags -m32)
- endif()
- # If -ccbin, --compiler-bindir has been specified, don't do anything. Otherwise add it here.
- list( FIND nvcc_flags "-ccbin" ccbin_found0 )
- list( FIND nvcc_flags "--compiler-bindir" ccbin_found1 )
- if( ccbin_found0 LESS 0 AND ccbin_found1 LESS 0 AND CUDA_HOST_COMPILER )
- list(APPEND nvcc_flags -ccbin "\"${CUDA_HOST_COMPILER}\"")
- endif()
-
- # Create a list of flags specified by CUDA_NVCC_FLAGS_${CONFIG} and CMAKE_${CUDA_C_OR_CXX}_FLAGS*
- set(config_specific_flags)
- set(flags)
- foreach(config ${CUDA_configuration_types})
- string(TOUPPER ${config} config_upper)
- # Add config specific flags
- foreach(f ${CUDA_NVCC_FLAGS_${config_upper}})
- list(APPEND config_specific_flags $<$<CONFIG:${config}>:${f}>)
- endforeach()
- set(important_host_flags)
- _cuda_get_important_host_flags(important_host_flags "${CMAKE_${CUDA_C_OR_CXX}_FLAGS_${config_upper}}")
- foreach(f ${important_host_flags})
- list(APPEND flags $<$<CONFIG:${config}>:-Xcompiler> $<$<CONFIG:${config}>:${f}>)
- endforeach()
- endforeach()
- # Add CMAKE_${CUDA_C_OR_CXX}_FLAGS
- set(important_host_flags)
- _cuda_get_important_host_flags(important_host_flags "${CMAKE_${CUDA_C_OR_CXX}_FLAGS}")
- foreach(f ${important_host_flags})
- list(APPEND flags -Xcompiler ${f})
- endforeach()
-
- # Add our general CUDA_NVCC_FLAGS with the configuration specifig flags
- set(nvcc_flags ${CUDA_NVCC_FLAGS} ${config_specific_flags} ${nvcc_flags})
-
- file(RELATIVE_PATH output_file_relative_path "${CMAKE_BINARY_DIR}" "${output_file}")
-
- # Some generators don't handle the multiple levels of custom command
- # dependencies correctly (obj1 depends on file1, obj2 depends on obj1), so
- # we work around that issue by compiling the intermediate link object as a
- # pre-link custom command in that situation.
- set(do_obj_build_rule TRUE)
- if (MSVC_VERSION GREATER 1599 AND MSVC_VERSION LESS 1800)
- # VS 2010 and 2012 have this problem.
- set(do_obj_build_rule FALSE)
- endif()
-
- if (do_obj_build_rule)
- add_custom_command(
- OUTPUT ${output_file}
- DEPENDS ${object_files}
- COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} -dlink ${object_files} -o ${output_file}
- ${flags}
- COMMENT "Building NVCC intermediate link file ${output_file_relative_path}"
- )
- else()
- get_filename_component(output_file_dir "${output_file}" DIRECTORY)
- add_custom_command(
- TARGET ${cuda_target}
- PRE_LINK
- COMMAND ${CMAKE_COMMAND} -E echo "Building NVCC intermediate link file ${output_file_relative_path}"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${output_file_dir}"
- COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} ${flags} -dlink ${object_files} -o "${output_file}"
- )
- endif()
- endif()
-endfunction()
-
-###############################################################################
-###############################################################################
-# ADD LIBRARY
-###############################################################################
-###############################################################################
-macro(CUDA_ADD_LIBRARY cuda_target)
-
- CUDA_ADD_CUDA_INCLUDE_ONCE()
-
- # Separate the sources from the options
- CUDA_GET_SOURCES_AND_OPTIONS(_sources _cmake_options _options ${ARGN})
- CUDA_BUILD_SHARED_LIBRARY(_cuda_shared_flag ${ARGN})
- # Create custom commands and targets for each file.
- CUDA_WRAP_SRCS( ${cuda_target} OBJ _generated_files ${_sources}
- ${_cmake_options} ${_cuda_shared_flag}
- OPTIONS ${_options} )
-
- # Compute the file name of the intermedate link file used for separable
- # compilation.
- CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME(link_file ${cuda_target} "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
-
- # Add the library.
- add_library(${cuda_target} ${_cmake_options}
- ${_generated_files}
- ${_sources}
- ${link_file}
- )
-
- # Add a link phase for the separable compilation if it has been enabled. If
- # it has been enabled then the ${cuda_target}_SEPARABLE_COMPILATION_OBJECTS
- # variable will have been defined.
- CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
-
- target_link_libraries(${cuda_target}
- ${CUDA_LIBRARIES}
- )
-
- # We need to set the linker language based on what the expected generated file
- # would be. CUDA_C_OR_CXX is computed based on CUDA_HOST_COMPILATION_CPP.
- set_target_properties(${cuda_target}
- PROPERTIES
- LINKER_LANGUAGE ${CUDA_C_OR_CXX}
- )
-
-endmacro()
-
-
-###############################################################################
-###############################################################################
-# ADD EXECUTABLE
-###############################################################################
-###############################################################################
-macro(CUDA_ADD_EXECUTABLE cuda_target)
-
- CUDA_ADD_CUDA_INCLUDE_ONCE()
-
- # Separate the sources from the options
- CUDA_GET_SOURCES_AND_OPTIONS(_sources _cmake_options _options ${ARGN})
- # Create custom commands and targets for each file.
- CUDA_WRAP_SRCS( ${cuda_target} OBJ _generated_files ${_sources} OPTIONS ${_options} )
-
- # Compute the file name of the intermedate link file used for separable
- # compilation.
- CUDA_COMPUTE_SEPARABLE_COMPILATION_OBJECT_FILE_NAME(link_file ${cuda_target} "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
-
- # Add the library.
- add_executable(${cuda_target} ${_cmake_options}
- ${_generated_files}
- ${_sources}
- ${link_file}
- )
-
- # Add a link phase for the separable compilation if it has been enabled. If
- # it has been enabled then the ${cuda_target}_SEPARABLE_COMPILATION_OBJECTS
- # variable will have been defined.
- CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS("${link_file}" ${cuda_target} "${_options}" "${${cuda_target}_SEPARABLE_COMPILATION_OBJECTS}")
-
- target_link_libraries(${cuda_target}
- ${CUDA_LIBRARIES}
- )
-
- # We need to set the linker language based on what the expected generated file
- # would be. CUDA_C_OR_CXX is computed based on CUDA_HOST_COMPILATION_CPP.
- set_target_properties(${cuda_target}
- PROPERTIES
- LINKER_LANGUAGE ${CUDA_C_OR_CXX}
- )
-
-endmacro()
-
-
-###############################################################################
-###############################################################################
-# (Internal) helper for manually added cuda source files with specific targets
-###############################################################################
-###############################################################################
-macro(cuda_compile_base cuda_target format generated_files)
-
- # Separate the sources from the options
- CUDA_GET_SOURCES_AND_OPTIONS(_sources _cmake_options _options ${ARGN})
- # Create custom commands and targets for each file.
- CUDA_WRAP_SRCS( ${cuda_target} ${format} _generated_files ${_sources} ${_cmake_options}
- OPTIONS ${_options} )
-
- set( ${generated_files} ${_generated_files})
-
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA COMPILE
-###############################################################################
-###############################################################################
-macro(CUDA_COMPILE generated_files)
- cuda_compile_base(cuda_compile OBJ ${generated_files} ${ARGN})
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA COMPILE PTX
-###############################################################################
-###############################################################################
-macro(CUDA_COMPILE_PTX generated_files)
- cuda_compile_base(cuda_compile_ptx PTX ${generated_files} ${ARGN})
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA COMPILE FATBIN
-###############################################################################
-###############################################################################
-macro(CUDA_COMPILE_FATBIN generated_files)
- cuda_compile_base(cuda_compile_fatbin FATBIN ${generated_files} ${ARGN})
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA COMPILE CUBIN
-###############################################################################
-###############################################################################
-macro(CUDA_COMPILE_CUBIN generated_files)
- cuda_compile_base(cuda_compile_cubin CUBIN ${generated_files} ${ARGN})
-endmacro()
-
-
-###############################################################################
-###############################################################################
-# CUDA ADD CUFFT TO TARGET
-###############################################################################
-###############################################################################
-macro(CUDA_ADD_CUFFT_TO_TARGET target)
- if (CUDA_BUILD_EMULATION)
- target_link_libraries(${target} ${CUDA_cufftemu_LIBRARY})
- else()
- target_link_libraries(${target} ${CUDA_cufft_LIBRARY})
- endif()
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA ADD CUBLAS TO TARGET
-###############################################################################
-###############################################################################
-macro(CUDA_ADD_CUBLAS_TO_TARGET target)
- if (CUDA_BUILD_EMULATION)
- target_link_libraries(${target} ${CUDA_cublasemu_LIBRARY})
- else()
- target_link_libraries(${target} ${CUDA_cublas_LIBRARY})
- endif()
-endmacro()
-
-###############################################################################
-###############################################################################
-# CUDA BUILD CLEAN TARGET
-###############################################################################
-###############################################################################
-macro(CUDA_BUILD_CLEAN_TARGET)
- # Call this after you add all your CUDA targets, and you will get a convience
- # target. You should also make clean after running this target to get the
- # build system to generate all the code again.
-
- set(cuda_clean_target_name clean_cuda_depends)
- if (CMAKE_GENERATOR MATCHES "Visual Studio")
- string(TOUPPER ${cuda_clean_target_name} cuda_clean_target_name)
- endif()
- add_custom_target(${cuda_clean_target_name}
- COMMAND ${CMAKE_COMMAND} -E remove ${CUDA_ADDITIONAL_CLEAN_FILES})
-
- # Clear out the variable, so the next time we configure it will be empty.
- # This is useful so that the files won't persist in the list after targets
- # have been removed.
- set(CUDA_ADDITIONAL_CLEAN_FILES "" CACHE INTERNAL "List of intermediate files that are part of the cuda dependency scanning.")
-endmacro()
+++ /dev/null
-# James Bigler, NVIDIA Corp (nvidia.com - jbigler)
-# Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
-#
-# Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
-#
-# Copyright (c) 2007-2009
-# Scientific Computing and Imaging Institute, University of Utah
-#
-# This code is licensed under the MIT License. See the FindCUDA.cmake script
-# for the text of the license.
-
-# The MIT License
-#
-# License for the specific language governing rights and limitations under
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-#
-
-#######################################################################
-# This converts a file written in makefile syntax into one that can be included
-# by CMake.
-
-file(READ ${input_file} depend_text)
-
-if (NOT "${depend_text}" STREQUAL "")
-
- # message("FOUND DEPENDS")
-
- string(REPLACE "\\ " " " depend_text ${depend_text})
-
- # This works for the nvcc -M generated dependency files.
- string(REGEX REPLACE "^.* : " "" depend_text ${depend_text})
- string(REGEX REPLACE "[ \\\\]*\n" ";" depend_text ${depend_text})
-
- set(dependency_list "")
-
- foreach(file ${depend_text})
-
- string(REGEX REPLACE "^ +" "" file ${file})
-
- # OK, now if we had a UNC path, nvcc has a tendency to only output the first '/'
- # instead of '//'. Here we will test to see if the file exists, if it doesn't then
- # try to prepend another '/' to the path and test again. If it still fails remove the
- # path.
-
- if(NOT EXISTS "${file}")
- if (EXISTS "/${file}")
- set(file "/${file}")
- else()
- message(WARNING " Removing non-existent dependency file: ${file}")
- set(file "")
- endif()
- endif()
-
- if(NOT IS_DIRECTORY "${file}")
- # If softlinks start to matter, we should change this to REALPATH. For now we need
- # to flatten paths, because nvcc can generate stuff like /bin/../include instead of
- # just /include.
- get_filename_component(file_absolute "${file}" ABSOLUTE)
- list(APPEND dependency_list "${file_absolute}")
- endif()
-
- endforeach()
-
-else()
- # message("FOUND NO DEPENDS")
-endif()
-
-# Remove the duplicate entries and sort them.
-list(REMOVE_DUPLICATES dependency_list)
-list(SORT dependency_list)
-
-foreach(file ${dependency_list})
- set(cuda_nvcc_depend "${cuda_nvcc_depend} \"${file}\"\n")
-endforeach()
-
-file(WRITE ${output_file} "# Generated by: make2cmake.cmake\nSET(CUDA_NVCC_DEPEND\n ${cuda_nvcc_depend})\n\n")
+++ /dev/null
-# James Bigler, NVIDIA Corp (nvidia.com - jbigler)
-# Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
-#
-# Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
-#
-# Copyright (c) 2007-2009
-# Scientific Computing and Imaging Institute, University of Utah
-#
-# This code is licensed under the MIT License. See the FindCUDA.cmake script
-# for the text of the license.
-
-# The MIT License
-#
-# License for the specific language governing rights and limitations under
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-#
-
-#######################################################################
-# Parses a .cubin file produced by nvcc and reports statistics about the file.
-
-
-file(READ ${input_file} file_text)
-
-if (NOT "${file_text}" STREQUAL "")
-
- string(REPLACE ";" "\\;" file_text ${file_text})
- string(REPLACE "\ncode" ";code" file_text ${file_text})
-
- list(LENGTH file_text len)
-
- foreach(line ${file_text})
-
- # Only look at "code { }" blocks.
- if(line MATCHES "^code")
-
- # Break into individual lines.
- string(REGEX REPLACE "\n" ";" line ${line})
-
- foreach(entry ${line})
-
- # Extract kernel names.
- if (${entry} MATCHES "[^g]name = ([^ ]+)")
- set(entry "${CMAKE_MATCH_1}")
-
- # Check to see if the kernel name starts with "_"
- set(skip FALSE)
- # if (${entry} MATCHES "^_")
- # Skip the rest of this block.
- # message("Skipping ${entry}")
- # set(skip TRUE)
- # else ()
- message("Kernel: ${entry}")
- # endif ()
-
- endif()
-
- # Skip the rest of the block if necessary
- if(NOT skip)
-
- # Registers
- if (${entry} MATCHES "reg([ ]+)=([ ]+)([^ ]+)")
- set(entry "${CMAKE_MATCH_3}")
- message("Registers: ${entry}")
- endif()
-
- # Local memory
- if (${entry} MATCHES "lmem([ ]+)=([ ]+)([^ ]+)")
- set(entry "${CMAKE_MATCH_3}")
- message("Local: ${entry}")
- endif()
-
- # Shared memory
- if (${entry} MATCHES "smem([ ]+)=([ ]+)([^ ]+)")
- set(entry "${CMAKE_MATCH_3}")
- message("Shared: ${entry}")
- endif()
-
- if (${entry} MATCHES "^}")
- message("")
- endif()
-
- endif()
-
-
- endforeach()
-
- endif()
-
- endforeach()
-
-else()
- # message("FOUND NO DEPENDS")
-endif()
-
-
+++ /dev/null
-# James Bigler, NVIDIA Corp (nvidia.com - jbigler)
-#
-# Copyright (c) 2008 - 2009 NVIDIA Corporation. All rights reserved.
-#
-# This code is licensed under the MIT License. See the FindCUDA.cmake script
-# for the text of the license.
-
-# The MIT License
-#
-# License for the specific language governing rights and limitations under
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-
-##########################################################################
-# This file runs the nvcc commands to produce the desired output file along with
-# the dependency file needed by CMake to compute dependencies. In addition the
-# file checks the output of each command and if the command fails it deletes the
-# output files.
-
-# Input variables
-#
-# verbose:BOOL=<> OFF: Be as quiet as possible (default)
-# ON : Describe each step
-#
-# build_configuration:STRING=<> Typically one of Debug, MinSizeRel, Release, or
-# RelWithDebInfo, but it should match one of the
-# entries in CUDA_HOST_FLAGS. This is the build
-# configuration used when compiling the code. If
-# blank or unspecified Debug is assumed as this is
-# what CMake does.
-#
-# generated_file:STRING=<> File to generate. This argument must be passed in.
-#
-# generated_cubin_file:STRING=<> File to generate. This argument must be passed
-# in if build_cubin is true.
-
-if(NOT generated_file)
- message(FATAL_ERROR "You must specify generated_file on the command line")
-endif()
-
-# Set these up as variables to make reading the generated file easier
-set(CMAKE_COMMAND "@CMAKE_COMMAND@") # path
-set(source_file "@source_file@") # path
-set(NVCC_generated_dependency_file "@NVCC_generated_dependency_file@") # path
-set(cmake_dependency_file "@cmake_dependency_file@") # path
-set(CUDA_make2cmake "@CUDA_make2cmake@") # path
-set(CUDA_parse_cubin "@CUDA_parse_cubin@") # path
-set(build_cubin @build_cubin@) # bool
-set(CUDA_HOST_COMPILER "@CUDA_HOST_COMPILER@") # path
-# We won't actually use these variables for now, but we need to set this, in
-# order to force this file to be run again if it changes.
-set(generated_file_path "@generated_file_path@") # path
-set(generated_file_internal "@generated_file@") # path
-set(generated_cubin_file_internal "@generated_cubin_file@") # path
-
-set(CUDA_NVCC_EXECUTABLE "@CUDA_NVCC_EXECUTABLE@") # path
-set(CUDA_NVCC_FLAGS @CUDA_NVCC_FLAGS@ ;; @CUDA_WRAP_OPTION_NVCC_FLAGS@) # list
-@CUDA_NVCC_FLAGS_CONFIG@
-set(nvcc_flags @nvcc_flags@) # list
-set(CUDA_NVCC_INCLUDE_ARGS "@CUDA_NVCC_INCLUDE_ARGS@") # list (needs to be in quotes to handle spaces properly).
-set(format_flag "@format_flag@") # string
-set(cuda_language_flag @cuda_language_flag@) # list
-
-if(build_cubin AND NOT generated_cubin_file)
- message(FATAL_ERROR "You must specify generated_cubin_file on the command line")
-endif()
-
-# This is the list of host compilation flags. It C or CXX should already have
-# been chosen by FindCUDA.cmake.
-@CUDA_HOST_FLAGS@
-
-# Take the compiler flags and package them up to be sent to the compiler via -Xcompiler
-set(nvcc_host_compiler_flags "")
-# If we weren't given a build_configuration, use Debug.
-if(NOT build_configuration)
- set(build_configuration Debug)
-endif()
-string(TOUPPER "${build_configuration}" build_configuration)
-#message("CUDA_NVCC_HOST_COMPILER_FLAGS = ${CUDA_NVCC_HOST_COMPILER_FLAGS}")
-foreach(flag ${CMAKE_HOST_FLAGS} ${CMAKE_HOST_FLAGS_${build_configuration}})
- # Extra quotes are added around each flag to help nvcc parse out flags with spaces.
- set(nvcc_host_compiler_flags "${nvcc_host_compiler_flags},\"${flag}\"")
-endforeach()
-if (nvcc_host_compiler_flags)
- set(nvcc_host_compiler_flags "-Xcompiler" ${nvcc_host_compiler_flags})
-endif()
-#message("nvcc_host_compiler_flags = \"${nvcc_host_compiler_flags}\"")
-# Add the build specific configuration flags
-list(APPEND CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS_${build_configuration}})
-
-# Any -ccbin existing in CUDA_NVCC_FLAGS gets highest priority
-list( FIND CUDA_NVCC_FLAGS "-ccbin" ccbin_found0 )
-list( FIND CUDA_NVCC_FLAGS "--compiler-bindir" ccbin_found1 )
-if( ccbin_found0 LESS 0 AND ccbin_found1 LESS 0 AND CUDA_HOST_COMPILER )
- if (CUDA_HOST_COMPILER STREQUAL "$(VCInstallDir)bin" AND DEFINED CCBIN)
- set(CCBIN -ccbin "${CCBIN}")
- else()
- set(CCBIN -ccbin "${CUDA_HOST_COMPILER}")
- endif()
-endif()
-
-# cuda_execute_process - Executes a command with optional command echo and status message.
-#
-# status - Status message to print if verbose is true
-# command - COMMAND argument from the usual execute_process argument structure
-# ARGN - Remaining arguments are the command with arguments
-#
-# CUDA_result - return value from running the command
-#
-# Make this a macro instead of a function, so that things like RESULT_VARIABLE
-# and other return variables are present after executing the process.
-macro(cuda_execute_process status command)
- set(_command ${command})
- if(NOT "x${_command}" STREQUAL "xCOMMAND")
- message(FATAL_ERROR "Malformed call to cuda_execute_process. Missing COMMAND as second argument. (command = ${command})")
- endif()
- if(verbose)
- execute_process(COMMAND "${CMAKE_COMMAND}" -E echo -- ${status})
- # Now we need to build up our command string. We are accounting for quotes
- # and spaces, anything else is left up to the user to fix if they want to
- # copy and paste a runnable command line.
- set(cuda_execute_process_string)
- foreach(arg ${ARGN})
- # If there are quotes, excape them, so they come through.
- string(REPLACE "\"" "\\\"" arg ${arg})
- # Args with spaces need quotes around them to get them to be parsed as a single argument.
- if(arg MATCHES " ")
- list(APPEND cuda_execute_process_string "\"${arg}\"")
- else()
- list(APPEND cuda_execute_process_string ${arg})
- endif()
- endforeach()
- # Echo the command
- execute_process(COMMAND ${CMAKE_COMMAND} -E echo ${cuda_execute_process_string})
- endif()
- # Run the command
- execute_process(COMMAND ${ARGN} RESULT_VARIABLE CUDA_result )
-endmacro()
-
-# Delete the target file
-cuda_execute_process(
- "Removing ${generated_file}"
- COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}"
- )
-
-# For CUDA 2.3 and below, -G -M doesn't work, so remove the -G flag
-# for dependency generation and hope for the best.
-set(depends_CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}")
-set(CUDA_VERSION @CUDA_VERSION@)
-if(CUDA_VERSION VERSION_LESS "3.0")
- cmake_policy(PUSH)
- # CMake policy 0007 NEW states that empty list elements are not
- # ignored. I'm just setting it to avoid the warning that's printed.
- cmake_policy(SET CMP0007 NEW)
- # Note that this will remove all occurances of -G.
- list(REMOVE_ITEM depends_CUDA_NVCC_FLAGS "-G")
- cmake_policy(POP)
-endif()
-
-# nvcc doesn't define __CUDACC__ for some reason when generating dependency files. This
-# can cause incorrect dependencies when #including files based on this macro which is
-# defined in the generating passes of nvcc invokation. We will go ahead and manually
-# define this for now until a future version fixes this bug.
-set(CUDACC_DEFINE -D__CUDACC__)
-
-# Generate the dependency file
-cuda_execute_process(
- "Generating dependency file: ${NVCC_generated_dependency_file}"
- COMMAND "${CUDA_NVCC_EXECUTABLE}"
- -M
- ${CUDACC_DEFINE}
- "${source_file}"
- -o "${NVCC_generated_dependency_file}"
- ${CCBIN}
- ${nvcc_flags}
- ${nvcc_host_compiler_flags}
- ${depends_CUDA_NVCC_FLAGS}
- -DNVCC
- ${CUDA_NVCC_INCLUDE_ARGS}
- )
-
-if(CUDA_result)
- message(FATAL_ERROR "Error generating ${generated_file}")
-endif()
-
-# Generate the cmake readable dependency file to a temp file. Don't put the
-# quotes just around the filenames for the input_file and output_file variables.
-# CMake will pass the quotes through and not be able to find the file.
-cuda_execute_process(
- "Generating temporary cmake readable file: ${cmake_dependency_file}.tmp"
- COMMAND "${CMAKE_COMMAND}"
- -D "input_file:FILEPATH=${NVCC_generated_dependency_file}"
- -D "output_file:FILEPATH=${cmake_dependency_file}.tmp"
- -P "${CUDA_make2cmake}"
- )
-
-if(CUDA_result)
- message(FATAL_ERROR "Error generating ${generated_file}")
-endif()
-
-# Copy the file if it is different
-cuda_execute_process(
- "Copy if different ${cmake_dependency_file}.tmp to ${cmake_dependency_file}"
- COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${cmake_dependency_file}.tmp" "${cmake_dependency_file}"
- )
-
-if(CUDA_result)
- message(FATAL_ERROR "Error generating ${generated_file}")
-endif()
-
-# Delete the temporary file
-cuda_execute_process(
- "Removing ${cmake_dependency_file}.tmp and ${NVCC_generated_dependency_file}"
- COMMAND "${CMAKE_COMMAND}" -E remove "${cmake_dependency_file}.tmp" "${NVCC_generated_dependency_file}"
- )
-
-if(CUDA_result)
- message(FATAL_ERROR "Error generating ${generated_file}")
-endif()
-
-# Generate the code
-cuda_execute_process(
- "Generating ${generated_file}"
- COMMAND "${CUDA_NVCC_EXECUTABLE}"
- "${source_file}"
- ${cuda_language_flag}
- ${format_flag} -o "${generated_file}"
- ${CCBIN}
- ${nvcc_flags}
- ${nvcc_host_compiler_flags}
- ${CUDA_NVCC_FLAGS}
- -DNVCC
- ${CUDA_NVCC_INCLUDE_ARGS}
- )
-
-if(CUDA_result)
- # Since nvcc can sometimes leave half done files make sure that we delete the output file.
- cuda_execute_process(
- "Removing ${generated_file}"
- COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}"
- )
- message(FATAL_ERROR "Error generating file ${generated_file}")
-else()
- if(verbose)
- message("Generated ${generated_file} successfully.")
- endif()
-endif()
-
-# Cubin resource report commands.
-if( build_cubin )
- # Run with -cubin to produce resource usage report.
- cuda_execute_process(
- "Generating ${generated_cubin_file}"
- COMMAND "${CUDA_NVCC_EXECUTABLE}"
- "${source_file}"
- ${CUDA_NVCC_FLAGS}
- ${nvcc_flags}
- ${CCBIN}
- ${nvcc_host_compiler_flags}
- -DNVCC
- -cubin
- -o "${generated_cubin_file}"
- ${CUDA_NVCC_INCLUDE_ARGS}
- )
-
- # Execute the parser script.
- cuda_execute_process(
- "Executing the parser script"
- COMMAND "${CMAKE_COMMAND}"
- -D "input_file:STRING=${generated_cubin_file}"
- -P "${CUDA_parse_cubin}"
- )
-
-endif()
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
REQUIRED_VARS HWLOC_LIBRARIES HWLOC_INCLUDE_DIRS
VERSION_VAR HWLOC_VERSION)
-mark_as_advanced(HWLOC_INCLUDE_DIRS HWLOC_LIBRARIES HWLOC_VERSION)
+mark_as_advanced(HWLOC_INCLUDE_DIRS HWLOC_LIBRARIES HWLOC_VERSION GMX_HWLOC_API_VERSION)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# Now run a sanity check on the compiler using libstdc++, regardless
# of how it was specified or found.
-# Test a feature which was added in libstdc++ 5
-check_cxx_source_compiles("#include <iterator>
-int main() { int a[2]; std::cbegin(a); }" CXX14_COMPILES)
+# Test required 2017 standard library features.
+check_cxx_source_compiles("
+#include <string_view>
+#include <optional>
+int main() { std::string_view(); std::optional<int>(); }" CXX17_COMPILES)
-if (NOT CXX14_COMPILES)
+if (NOT CXX17_COMPILES)
if (NEED_TO_FIND_GPLUSPLUS)
set (EXTRA_MESSAGE " The g++ found at ${GMX_GPLUSPLUS_PATH} had a suitable version, so "
"something else must be the problem")
else()
set (EXTRA_MESSAGE " Check your toolchain documentation or environment flags so that "
- "they will find a suitable C++14 standard library")
+ "they will find a suitable C++17 standard library")
endif()
- message(FATAL_ERROR "GROMACS requires C++14, but a test of such functionality in the C++ standard "
+ message(FATAL_ERROR "GROMACS requires C++17, but a test of such functionality in the C++ standard "
"library failed to compile.${EXTRA_MESSAGE}")
endif()
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015,2019, by the GROMACS development team, led by
+# Copyright (c) 2015,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# Adapted from code posted on cmake-users by Mark Moll (the execute_process()
# call remains, but other things have been rewritten for nicer behavior).
-find_package(PythonInterp 3.5)
function (find_python_module module)
string(TOUPPER ${module} _module_upper)
+++ /dev/null
-int main()
-{
-#ifdef __ARM_ARCH_7A__
- return 0;
-#else
-#error This compiler is not targetting 32-bit ARMv7
-#endif
-}
+++ /dev/null
-int main()
-{
-#if defined(__ARM_ARCH_7A__) && defined(__GNUC__)
- unsigned int cycles_lo, cycles_hi;
- asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cycles_lo), "=r" (cycles_hi));
-
- // Return 0 (success) if low or high 32 bits contained anything non-trivial
- return !(cycles_lo > 0 || cycles_hi > 0);
-#else
-#error This architecture/compiler does not support ARMv7 32-bit cycle counters
-#endif
-}
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
if (GMX_SKIP_DEFAULT_CFLAGS)
set (CXXFLAGS "")
else()
+ # Prepare the generic compiler options
gmx_target_compile_options_inner()
+ # CUDA headers issue lots of warnings when compiled with
+ # -Wundef because they use old-style #ifdef a lot. We'd prefer
+ # to have FindCUDA.cmake treat CUDA internal headers with
+ # -isystem so that these warnings are naturally suppressed,
+ # but there's no way to do that without bundling a modified
+ # form of FindCUDA.cmake. That creates its own problems,
+ # because people either don't know we do that, or don't
+ # remember that we don't do that in user tarballs.
+ #
+ # We have make check-source ensuring that we have included
+ # config.h any time we use such symbols in commits in a merge
+ # request. Local development could run that too. So, we can
+ # tolerate any remaining risk from accidentally using
+ # e.g. #ifdef GMX_MPI rather than #if GMX_MPI in CUDA source
+ # files.
+ #
+ # So we disable -Wundef by the simple hack of appending
+ # -Wno-undef after it. That's more maintainable than having
+ # logic to avoid adding -Wundef to GMXC_CXXFLAGS, given the
+ # current approach to adding them. Hopefully this will improve
+ # if/when we have more CMake object libraries, and/or native
+ # CUDA compilation.
+ GMX_TEST_CXXFLAG(CXXFLAGS_WARN_NOUNDEF "-Wno-undef" CXXFLAGS)
endif()
# Only C++ compilation is supported with CUDA code in GROMACS
# Problematic with CUDA
# GMX_TEST_CXXFLAG(CXXFLAGS_WARN_EFFCXX "-Wnon-virtual-dtor" GMXC_CXXFLAGS)
GMX_TEST_CXXFLAG(CXXFLAGS_WARN_EXTRA "-Wextra;-Wno-missing-field-initializers;-Wpointer-arith;-Wmissing-declarations" GMXC_CXXFLAGS)
- # CUDA versions prior to 7.5 come with a header (math_functions.h) which uses the _MSC_VER macro
- # unconditionally, so we don't use -Wundef for earlier CUDA versions.
- if(NOT(GMX_GPU AND CUDA_VERSION VERSION_LESS "7.5"))
- GMX_TEST_CXXFLAG(CXXFLAGS_WARN_UNDEF "-Wundef" GMXC_CXXFLAGS)
- endif()
+ GMX_TEST_CXXFLAG(CXXFLAGS_WARN_UNDEF "-Wundef" GMXC_CXXFLAGS)
GMX_TEST_CFLAG(CXXFLAGS_WARN_REL "-Wno-array-bounds" GMXC_CXXFLAGS_RELEASE_ONLY)
GMX_TEST_CXXFLAG(CXXFLAGS_STRINGOP_TRUNCATION "-Wstringop-truncation" GMXC_CXXFLAGS)
if (CXXFLAGS_STRINGOP_TRUNCATION)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
\\\\.gitignore
\\\\.gitattributes
INSTALL-dev
- cmake/FindCUDA\\\\.cmake
- cmake/FindCUDA
# entry below is needed for CI not to include the cache directory
ccache)
set(CPACK_SOURCE_IGNORE_FILES ${FILES_NOT_INCLUDED_IN_SOURCE_PACKAGE})
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
try_compile(GMX_TARGET_MIC ${CMAKE_BINARY_DIR}
"${CMAKE_SOURCE_DIR}/cmake/TestMIC.cpp")
endif()
- if (NOT DEFINED GMX_TARGET_ARMV7)
- try_compile(GMX_TARGET_ARMV7 ${CMAKE_BINARY_DIR}
- "${CMAKE_SOURCE_DIR}/cmake/TestARMv7.cpp")
- endif()
if (NOT DEFINED GMX_TARGET_FUJITSU_SPARC64)
try_compile(GMX_TARGET_FUJITSU_SPARC64 ${CMAKE_BINARY_DIR}
"${CMAKE_SOURCE_DIR}/cmake/TestFujitsuSparc64.cpp")
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
set(VERSION_STR_SUFFIX "${HEAD_DATE}-${HEAD_HASH_SHORT}${DIRTY_STR}")
# find the names of remotes that are located on the official gromacs
-# git/gerrit servers
+# git servers
execute_process(COMMAND ${GIT_EXECUTABLE} config --get-regexp
- "remote\\..*\\.url" "\\.gromacs\\.org[:/].*gromacs(\\.git)?$"
+ "remote\\..*\\.url" "\\gitlab\\.com[:/]gromacs.gromacs(\\.git)?$"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE GMX_REMOTES
ERROR_VARIABLE EXEC_ERR
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-# - Decide whether to use CPU cycle counters
-#
-# gmx_manage_cycle_counters()
-#
-# By default, we enable GMX_CYCLECOUNTERS for all architectures except ARMv7.
-# On ARMv7, we enable it if we are not cross-compiling and can run a small
-# test to confirm that the support is present in the kernel, otherwise we
-# disable it.
-#
-macro(gmx_manage_cycle_counters)
-
- if(NOT DEFINED GMX_CYCLECOUNTERS)
-
- if(GMX_TARGET_ARMV7)
-
- if(NOT CMAKE_CROSSCOMPILING)
-
- try_run(ARMV7_COUNTER_RUN_VAR ARMV7_COUNTER_COMPILE_VAR
- ${CMAKE_BINARY_DIR} "${CMAKE_SOURCE_DIR}/cmake/TestARMv7CycleCounters.cpp")
-
- # Enable cycle counter usage if the test ran fine and exited with 0 return code
- if(${ARMV7_COUNTER_COMPILE_VAR} AND ("${ARMV7_COUNTER_RUN_VAR}" EQUAL "0"))
- set(GMX_CYCLECOUNTERS ON CACHE BOOL "Use CPU cycle counters timing")
- else()
- set(GMX_CYCLECOUNTERS OFF CACHE BOOL "Use CPU cycle counters for timing")
- endif()
-
- else()
-
- # Disable cycle counters when cross-compiling for ARMv7
- set(GMX_CYCLECOUNTERS OFF CACHE BOOL "Use CPU cycle counters for timing")
-
- endif()
-
- else()
-
- # For now we (try to) enable cycle counters on all other platforms
- set(GMX_CYCLECOUNTERS ON CACHE BOOL "Use CPU cycle counters timing")
-
- endif()
-
- mark_as_advanced(GMX_CYCLECOUNTERS)
-
- endif()
-
-endmacro()
-
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2016, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# there is need to (say) use vendor BLAS with MKL for FFTs.
#
# If the vendor BLAS and/or LAPACK have abnormal library names, then
-# the default searching procedure will fail (e.g. Redmine #771). The
+# the default searching procedure will fail (e.g. Issue #771). The
# GMX_(BLAS|LAPACK)_USER variables can be used to indicate the correct
# libraries. If these do not work, a warning is emitted and we try to
# use them anyway, assuming the user knows what they are doing.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# glibc source shows that _FORCE_INLINES is only used in this string.h
# feature and performance of memcpy variants is unimportant for CUDA
# code in GROMACS. So this workaround is good enough to keep problems
-# away from users installing GROMACS. See Redmine 1942.
+# away from users installing GROMACS. See Issue #1942.
function(work_around_glibc_2_23)
try_compile(IS_GLIBC_2_23_OR_HIGHER ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/cmake/TestGlibcVersion.cpp)
if(IS_GLIBC_2_23_OR_HIGHER)
set_property(CACHE GMX_CUDA_TARGET_COMPUTE PROPERTY TYPE STRING)
endif()
-# FindCUDA.cmake is unaware of the mechanism used by cmake to embed
-# the compiler flag for the required C++ standard in the generated
-# build files, so we have to pass it ourselves
-if (MSVC)
- # We use C++14 on MSVC, but cmake does not understand the
- # necessary compilation option for that until version 3.10, so we
- # can remove this after we require that version.
- if (NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
- set(GMX_CXX_STANDARD_COMPILE_OPTION "-std:c++14")
- else()
- set(GMX_CXX_STANDARD_COMPILE_OPTION "${CMAKE_CXX14_STANDARD_COMPILE_OPTION}")
- endif()
-else()
- set(GMX_CXX_STANDARD_COMPILE_OPTION "${CMAKE_CXX14_STANDARD_COMPILE_OPTION}")
-endif()
-list(APPEND GMX_CUDA_NVCC_FLAGS "${GMX_CXX_STANDARD_COMPILE_OPTION}")
-
# assemble the CUDA flags
list(APPEND GMX_CUDA_NVCC_FLAGS "${GMX_CUDA_NVCC_GENCODE_FLAGS}")
list(APPEND GMX_CUDA_NVCC_FLAGS "-use_fast_math")
# Source files generated by NVCC can include gmxmpi.h, and so
# need access to thread-MPI.
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
+ # Source files can also contain topology related files and need access to
+ # the remaining external headers
+ include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/src/external)
# Now add all the compilation options
gmx_cuda_target_compile_options(CUDA_${TARGET}_CXXFLAGS)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015, The GROMACS development team.
-# Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# is not required for SIMD support on this platform. cmake through
# at least version 3.7 cannot pass this check with the C compiler
# in the latest xlc 13.1.5, but the C++ compiler has different
- # behaviour and is OK. See Redmine #2102.
+ # behaviour and is OK. See Issue #2102.
if(NOT SIMD_IBM_VSX_CXX_SUPPORTED)
gmx_give_fatal_error_when_simd_support_not_found("IBM VSX" "disable SIMD support (slower)" "${SUGGEST_BINUTILS_UPDATE}")
endif()
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2020, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# Perform Python installation discovery early and in one place, for consistency.
+#
+# Note: If necessary, the Python location can be hinted with Python3_ROOT_DIR
+# For additional parameters affecting Python installation discovery, see
+# https://cmake.org/cmake/help/latest/module/FindPython3.html#hints
+if(FIND_PACKAGE_MESSAGE_DETAILS_Python3)
+ # Keep quiet on subsequent runs of cmake
+ set(Python3_FIND_QUIETLY ON)
+ set(PythonInterp_FIND_QUIETLY ON)
+endif()
+# Older CMake versions might not search for Python newer than 3.7.
+set(Python_ADDITIONAL_VERSIONS 3.8)
+# We advocate using Python venvs to manage package availability, so by default
+# we want to preferentially discover user-space software.
+set(Python3_FIND_REGISTRY LAST)
+# Make package discovery consistent with Unix behavior and our documented
+# suggestions for installing dependencies.
+set(CMAKE_FIND_FRAMEWORK LAST)
+if(GMX_PYTHON_PACKAGE)
+ find_package(Python3 3.6 COMPONENTS Interpreter Development)
+ if (NOT Python3_FOUND OR NOT Python3_Development_FOUND)
+ message(FATAL_ERROR "Could not locate Python development requirements. \
+ Provide appropriate CMake hints or set GMX_PYTHON_PACKAGE=OFF")
+ endif ()
+else()
+ find_package(Python3 3.6 COMPONENTS Interpreter)
+endif()
+# Other components, such as pybind and googletest, may expect the
+# PYTHON_EXECUTABLE variable from pre-3.12 FindPythonInterp.cmake.
+if (Python3_Interpreter_FOUND)
+ set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE FILEPATH "Location hint for Python interpreter.")
+endif ()
+# We've already generated all of the output we need, even though other subcomponents
+# may call find_package(PythonInterp) later on.
+set(Python3_FIND_QUIETLY ON)
+set(PythonInterp_FIND_QUIETLY ON)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2012,2013,2014,2015, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2012,2013,2014,2015, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-#
# GMX_TEST_MM_MALLOC(VARIABLE)
#
# VARIABLE will be set to true if we find _mm_malloc() and _mm_free().
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2011,2012,2014,2015,2016,2020, by the GROMACS development team, led by
+# Copyright (c) 2009,2011,2012,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# GROMACS 2018 3
# GROMACS 2019 4
# GROMACS 2020 5
+# GROMACS 2021 6
# LIBRARY_SOVERSION_MINOR so minor version for the built libraries.
# Should be increased for each release that changes only the implementation.
# In GROMACS, the typical policy is to increase it for each patch version
# The GROMACS convention is that these are the version number of the next
# release that is going to be made from this branch.
-set(GMX_VERSION_MAJOR 2020)
-set(GMX_VERSION_PATCH 3)
+set(GMX_VERSION_MAJOR 2021)
+set(GMX_VERSION_PATCH 0)
# The suffix, on the other hand, is used mainly for betas and release
# candidates, where it signifies the most recent such release from
# this branch; it will be empty before the first such release, as well
# here. The important thing is to minimize the chance of third-party
# code being able to dynamically link with a version of libgromacs
# that might not work.
-set(LIBRARY_SOVERSION_MAJOR 5)
+set(LIBRARY_SOVERSION_MAJOR 6)
set(LIBRARY_SOVERSION_MINOR 0)
set(LIBRARY_VERSION ${LIBRARY_SOVERSION_MAJOR}.${LIBRARY_SOVERSION_MINOR}.0)
endif()
set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
-set(REGRESSIONTEST_BRANCH "release-2020")
+set(REGRESSIONTEST_BRANCH "master")
# Run the regressiontests packaging job with the correct pakage
# version string, and the release box checked, in order to have it
# build the regressiontests tarball with all the right naming. The
list(APPEND SET_OF_DIRECTORIES_TO_CHECKSUM "python_packaging")
# Due to the limitations for passing a list as arguments, we make the directories a string here
string(REPLACE ";" ":" DIRECTORIES_TO_CHECKSUM_STRING "${SET_OF_DIRECTORIES_TO_CHECKSUM}")
-# Try to find python for the checksumming script
-set(PythonInterp_FIND_QUIETLY ON)
-find_package(PythonInterp 3.5)
# Rules to create the VersionInfo.cmake file.
# For git info, the sequence is:
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# of configure time, because 1) some of the version variables are only
# available during build time, and 2) we don't want to do all the Sphinx setup
# during configuration to save some time when not building the content.
-# All the generated values get put into conf-vars.py (generated from
-# conf-vars.py.cmakein), which in turn is included by the Sphinx configuration
-# file conf.py.
+# All of the generated values get put into conf.py (generated from
+# conf.cmakein.py).
set(SOURCE_MD5SUM "unknown" CACHE STRING
"MD5 sum of the source tarball, normally used only for the pre-release webpage build")
set(SPHINX_SOURCE_FILES
index.rst
download.rst
- conf.py
links.dat
dev-manual/build-system.rst
dev-manual/change-management.rst
dev-manual/commitstyle.rst
+ dev-manual/containers.rst
dev-manual/documentation-generation.rst
dev-manual/contribute.rst
dev-manual/doxygen.rst
dev-manual/error-handling.rst
dev-manual/formatting.rst
+ dev-manual/gitlab.rst
dev-manual/gmxtree.rst
dev-manual/includestyle.rst
dev-manual/index.rst
+ dev-manual/infrastructure.rst
dev-manual/jenkins.rst
dev-manual/known-issues.rst
dev-manual/language-features.rst
how-to/visualize.rst
install-guide/index.rst
release-notes/index.rst
+ release-notes/2021/major/highlights.rst
+ release-notes/2021/major/features.rst
+ release-notes/2021/major/performance.rst
+ release-notes/2021/major/tools.rst
+ release-notes/2021/major/bugs-fixed.rst
+ release-notes/2021/major/removed-functionality.rst
+ release-notes/2021/major/deprecated-functionality.rst
+ release-notes/2021/major/portability.rst
+ release-notes/2021/major/miscellaneous.rst
release-notes/2020/2020.1.rst
release-notes/2020/2020.2.rst
release-notes/2020/2020.3.rst
set(IMAGE_CONVERT_STRING "impossible")
endif()
- set(SPHINX_CONFIG_VARS_FILE ${SPHINX_INPUT_DIR}/conf-vars.py)
+ set(SPHINX_CONFIG_FILE ${SPHINX_INPUT_DIR}/conf.py)
if (GMX_PYTHON_PACKAGE)
set(GMXAPI_PYTHON_STAGING_DIR ${CMAKE_BINARY_DIR}/python_packaging/src/gmxapi_staging)
# TODO: Resolve circular reference. We would like to get the CMake build-time directory for
# in this context?
endif ()
- gmx_configure_version_file(conf-vars.py.cmakein ${SPHINX_CONFIG_VARS_FILE}
+ gmx_configure_version_file(
+ conf.cmakein.py ${SPHINX_CONFIG_FILE}
EXTRA_VARS
- SPHINX_EXTENSION_PATH RELENG_PATH
- IMAGE_CONVERT_STRING
+ CMAKE_MINIMUM_REQUIRED_VERSION
EXPECTED_DOXYGEN_VERSION
EXPECTED_SPHINX_VERSION
- CMAKE_MINIMUM_REQUIRED_VERSION REQUIRED_CUDA_VERSION
- REQUIRED_OPENCL_MIN_VERSION
- REQUIRED_CUDA_COMPUTE_CAPABILITY REGRESSIONTEST_VERSION
- SOURCE_MD5SUM REGRESSIONTEST_MD5SUM_STRING
- GMX_TNG_MINIMUM_REQUIRED_VERSION
+ GMX_ADMIN_DIR
GMX_LMFIT_REQUIRED_VERSION
GMX_MANUAL_DOI_STRING
+ GMX_TNG_MINIMUM_REQUIRED_VERSION
GMX_SOURCE_DOI_STRING
GMXAPI_PYTHON_STAGING_DIR
+ IMAGE_CONVERT_STRING
+ REGRESSIONTEST_VERSION
+ REQUIRED_CUDA_COMPUTE_CAPABILITY
+ REQUIRED_CUDA_VERSION
+ REQUIRED_OPENCL_MIN_VERSION
+ REGRESSIONTEST_MD5SUM_STRING
+ RELENG_PATH
+ SOURCE_MD5SUM
+ SPHINX_EXTENSION_PATH
COMMENT "Configuring Sphinx configuration file")
- gmx_add_sphinx_input_file(${SPHINX_CONFIG_VARS_FILE})
+ gmx_add_sphinx_input_file(${SPHINX_CONFIG_FILE})
gmx_add_sphinx_source_files(FILES ${SPHINX_SOURCE_FILES})
if (EXISTS ${RELENG_PATH}/docs/FileList.cmake)
include(${RELENG_PATH}/docs/FileList.cmake)
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
+ set(SPHINX_CONFIG_OVERRIDES "")
+ if (GMX_DEVELOPER_BUILD)
+ set(SPHINX_CONFIG_OVERRIDES "-Dtodo_include_todos=1")
+ endif()
add_custom_target(webpage-sphinx
DEPENDS sphinx-programs
DEPENDS sphinx-input
-q -b html
-w sphinx-html.log
-d "${SPHINX_CACHE_DIR}"
+ ${SPHINX_CONFIG_OVERRIDES}
"${SPHINX_INPUT_DIR}"
"${HTML_OUTPUT_DIR}"
WORKING_DIRECTORY
set(HTML_BUILD_WARNINGS)
# Next, turn it off if any of the preconditions are unsatisified
-if (NOT PythonInterp_FOUND)
+if (NOT Python3_Interpreter_FOUND)
set(HTML_BUILD_IS_POSSIBLE OFF)
set(HTML_BUILD_NOT_POSSIBLE_REASON "Python is required")
elseif (NOT SPHINX_FOUND)
- Quite a few error conditions are unhandled, noted with TODOs in several files
-- gmx_device_info_t needs struct field documentation
-
3. ENHANCEMENTS
============
- Implement OpenCL kernels for Intel GPUs
+++ /dev/null
-#
-# This file is part of the GROMACS molecular simulation package.
-#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
-# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
-# and including many others, as listed in the AUTHORS file in the
-# top-level source directory and at http://www.gromacs.org.
-#
-# GROMACS is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2.1
-# of the License, or (at your option) any later version.
-#
-# GROMACS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with GROMACS; if not, see
-# http://www.gnu.org/licenses, or write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# If you want to redistribute modifications to GROMACS, please
-# consider that scientific software is very special. Version
-# control is crucial - bugs must be traceable. We will be happy to
-# consider code for inclusion in the official distribution, but
-# derived work must not be called official GROMACS. Details are found
-# in the README & COPYING files - if they are missing, get the
-# official version at http://www.gromacs.org.
-#
-# To help us fund GROMACS development, we humbly ask that you cite
-# the research papers on the package. Check out http://www.gromacs.org.
-
-gmx_sphinx_extension_path = '@SPHINX_EXTENSION_PATH@'
-gmxapi_staging_path = '@GMXAPI_PYTHON_STAGING_DIR@'
-releng_path = '@RELENG_PATH@'
-gmx_version_string = '@GMX_VERSION_STRING@'
-gmx_version_string_full = '@GMX_VERSION_STRING_FULL@'
-regressiontest_version = '@REGRESSIONTEST_VERSION@'
-gmx_min_sphinx = '@EXPECTED_SPHINX_VERSION@'
-gmx_image_convert = '@IMAGE_CONVERT_STRING@'
-variables = [
- ('EXPECTED_DOXYGEN_VERSION', '@EXPECTED_DOXYGEN_VERSION@'),
- ('EXPECTED_SPHINX_VERSION', '@EXPECTED_SPHINX_VERSION@'),
- ('CMAKE_MINIMUM_REQUIRED_VERSION', '@CMAKE_MINIMUM_REQUIRED_VERSION@'),
- ('REQUIRED_CUDA_VERSION', '@REQUIRED_CUDA_VERSION@'),
- ('REQUIRED_CUDA_COMPUTE_CAPABILITY', '@REQUIRED_CUDA_COMPUTE_CAPABILITY@'),
- ('REQUIRED_OPENCL_MIN_VERSION', '@REQUIRED_OPENCL_MIN_VERSION@'),
- ('SOURCE_MD5SUM', '@SOURCE_MD5SUM@'),
- ('REGRESSIONTEST_MD5SUM', '@REGRESSIONTEST_MD5SUM_STRING@'),
- ('GMX_TNG_MINIMUM_REQUIRED_VERSION', '@GMX_TNG_MINIMUM_REQUIRED_VERSION@'),
- ('GMX_LMFIT_REQUIRED_VERSION', '@GMX_LMFIT_REQUIRED_VERSION@'),
- ('GMX_MANUAL_DOI_STRING', '@GMX_MANUAL_DOI_STRING@'),
- ('GMX_SOURCE_DOI_STRING', '@GMX_SOURCE_DOI_STRING@')
- ]
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+# Copyright (c) 2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import os
import sys
-exec(open('conf-vars.py').read())
+# The following definitions are completed via CMake machinery.
+gmx_containers_path = '@GMX_ADMIN_DIR@/containers'
+gmx_sphinx_extension_path = '@SPHINX_EXTENSION_PATH@'
+gmxapi_staging_path = '@GMXAPI_PYTHON_STAGING_DIR@'
+releng_path = '@RELENG_PATH@'
+gmx_version_string = '@GMX_VERSION_STRING@'
+gmx_version_string_full = '@GMX_VERSION_STRING_FULL@'
+regressiontest_version = '@REGRESSIONTEST_VERSION@'
+gmx_min_sphinx = '@EXPECTED_SPHINX_VERSION@'
+gmx_image_convert = '@IMAGE_CONVERT_STRING@'
+variables = [
+ ('EXPECTED_DOXYGEN_VERSION', '@EXPECTED_DOXYGEN_VERSION@'),
+ ('EXPECTED_SPHINX_VERSION', '@EXPECTED_SPHINX_VERSION@'),
+ ('CMAKE_MINIMUM_REQUIRED_VERSION', '@CMAKE_MINIMUM_REQUIRED_VERSION@'),
+ ('REQUIRED_CUDA_VERSION', '@REQUIRED_CUDA_VERSION@'),
+ ('REQUIRED_CUDA_COMPUTE_CAPABILITY', '@REQUIRED_CUDA_COMPUTE_CAPABILITY@'),
+ ('REQUIRED_OPENCL_MIN_VERSION', '@REQUIRED_OPENCL_MIN_VERSION@'),
+ ('SOURCE_MD5SUM', '@SOURCE_MD5SUM@'),
+ ('REGRESSIONTEST_MD5SUM', '@REGRESSIONTEST_MD5SUM_STRING@'),
+ ('GMX_TNG_MINIMUM_REQUIRED_VERSION', '@GMX_TNG_MINIMUM_REQUIRED_VERSION@'),
+ ('GMX_LMFIT_REQUIRED_VERSION', '@GMX_LMFIT_REQUIRED_VERSION@'),
+ ('GMX_MANUAL_DOI_STRING', '@GMX_MANUAL_DOI_STRING@'),
+ ('GMX_SOURCE_DOI_STRING', '@GMX_SOURCE_DOI_STRING@')
+]
+# End of build-time substitutions.
+
+sys.path.append(gmx_containers_path)
sys.path.append(gmx_sphinx_extension_path)
if releng_path and os.path.isdir(releng_path):
sys.path.append(releng_path)
'sphinx.ext.mathjax',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
+ # The viewcode extension requires extra configuration or consideration to
+ # avoid collecting sources for external packages (through intersphninx) or
+ # generating broken links for compiled extension modules that do not have
+ # inspectable 'code' member data.
+ # Ref: https://www.sphinx-doc.org/en/master/usage/extensions/viewcode.html
+ # Please run linkchecker and inspect the generated
+ # docs/html/_modules/index.html page before committing a change that enables
+ # 'sphinx.ext.viewcode',
'gmxsphinx'
]
-extlinks = {'issue': ('https://redmine.gromacs.org/issues/%s',
+extlinks = {'issue': ('https://gitlab.com/gromacs/gromacs/-/issues/%s',
'Issue ')}
# Add any paths that contain templates here, relative to this directory.
.. _webpage: http://www.gromacs.org
.. _ftp site: ftp://ftp.gromacs.org/pub/gromacs/
.. _tutorials: http://www.gromacs.org/Documentation/Tutorials
+.. _issue tracker: https://gitlab.com/gromacs/gromacs/-/issues/
+.. _issues: https://gitlab.com/gromacs/gromacs/-/issues/
+.. _gitlab: https://gitlab.com/gromacs/gromacs/
.. _redmine: http://redmine.gromacs.org
.. _gerrit: http://gerrit.gromacs.org
.. _download: ../download.html
# Make it possible to use numbered labels for figures and tables
numfig = True
+# -- Options for autodoc extension ----------------------------------------
+
+# http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc-mock-imports
+autodoc_mock_imports = ['hpccm', 'hpccm.config']
+
# -- Options for intersphinx extension ------------------------------------
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
developers or advanced users can set to affect what CMake generates and/or what
will get built.
-.. TODO: Figure out where to document basic variables intended for user
+.. todo::
+
+ Figure out where to document basic variables intended for user
consumption, and how does it relate to documentation here.
-.. TODO: Document the remaining variables below, and identify any variables
+.. todo::
+
+ Document the remaining variables below, and identify any variables
missing from the list.
Compiler flags
Defaults to ``OFF``, and there should not be any need to change this in a
manual build.
- .. TODO: This could likely be replaced by a (yet another) build type.
+ .. todo:: This could likely be replaced by a (yet another) build type.
.. cmake:: GMX_BUILD_MDRUN_ONLY
.. cmake:: GMX_CLANG_TIDY
- `clang-tidy <http://releases.llvm.org/8.0.0/tools/clang/tools/extra/docs/clang-tidy/index.html>`_
+ `clang-tidy <http://releases.llvm.org/9.0.0/tools/clang/tools/extra/docs/clang-tidy/index.html>`_
is used for static code analysis and (some) automated fixing of issues detected. clang-tidy is easy to install. It is contained in
- the llvm binary `package <http://releases.llvm.org/download.html#8.0.0>`_. Only
- version 8.0.* with libstdc++<7 or libc++ is supported. Others might miss tests or give false positives.
- It is run automatically on Jenkins for each commit. Many checks have fixes which can automatically be
+ the llvm binary `package <http://releases.llvm.org/download.html#9.0.0>`_. Only
+ version 9.0.* with libstdc++<7 or libc++ is supported. Others might miss tests or give false positives.
+ It is run automatically in gitlab CI for each commit. Many checks have fixes which can automatically be
applied. To run it, the build has to be configured with
- ``cmake -DGMX_CLANG_TIDY=ON -DGMX_OPENMP=no -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=on``.
+ ``cmake -DGMX_CLANG_TIDY=ON -DCMAKE_BUILD_TYPE=Debug``.
Any ``CMAKE_BUILD_TYPE`` which enables asserts (e.g. ASAN) works. Such a configured build will
run both the compiler as well as clang-tidy when building. The name of the clang-tidy executable is set with
``-DCLANG_TIDY=...``, and the full path to it can be set with ``-DCLANG_TIDY_EXE=...``.
If ``OFF`` (the default), all detection is skipped and the manual cannot be
built.
- .. TODO: Consider if this is really necessary, or if we could just use
+ .. todo:: Consider if this is really necessary, or if we could just use
GMX_DEVELOPER_BUILD.
.. cmake:: GMX_BUILD_TARBALL
External libraries
------------------
-.. TODO: List external libraries used (either from src/external/, or from the
+.. todo::
+
+ List external libraries used (either from src/external/, or from the
system), whether they are required or optional, what functionality they
provide for Gromacs, and how to control their use.
-.. _gmx-gerrit:
-
-=========================
-GROMACS change management
-=========================
+=================
+Change Management
+=================
This documentation assumes the reader is already familiary with using ``git``
for managing file revisions.
Getting started
===============
-#. Go to https://gerrit.gromacs.org
-#. Click Register (you can choose any OpenID provider including any
- existing Google/Yahoo account. If you manually enter the URL make sure
- to start with ``http(s)://``)
-#. Choose a username and add an ssh key
-
-See `here <https://gerrit.gromacs.org/Documentation/intro-quick.html>`_ for
-a quick intro into Gerrit.
-
-Creating the SSH key for Gerrit
--------------------------------
-
-In order to push your commits to gerrit server, you must have an SSH key
-in your computer which matches with the one registered in your Gerrit
-user account. To do so, you first need to create this unique SSH
-key. You will be asked to enter a passphrase. *This is
-optional with respect to Gerrit, but it is a good security practice to have
-it.*
-
-To proceed with the creation of the SSH key, type the following commands
-from your terminal window:
-
-::
-
- $ cd ~/.ssh
-
- $ ssh-keygen -t rsa -C "your.email@address.com"
-
-Please substitute the email string in the command above
-with the same email address which you used to register the account in
-Gerrit.
-
-Now you have created your public SSH key, which you need to copy/paste
-into your Gerrit profile. First, open it with the following command:
-
-::
-
- $ cat id_rsa.pub
-
-Copy all the contents of the file id_rsa.pub in your clipboard, and
-switch to your favorite web browser where you logged in to Gerrit
-GROMACS page. Click on your username at the top right corner of the
-Gerrit webpage and select "Settings". You should now be in your Gerrit
-profile settings page, where you should see a vertical menu.
-
-From this vertical menu, select "SSH Public Keys", then click the button
-"Add Key ..." and an edit box will appear below the button. Here you
-need to paste the contents of id_rsa.pub file, which you previously
-copied to your clipboard.
-
-Now you are ready to operate!
-
-Setting up a local repository to work with gerrit
--------------------------------------------------
-
-Either clone using::
-
- $ git clone ssh://USER@gerrit.gromacs.org/gromacs.git
-
-(replace **USER** \ with your username)
-
-or change the remote url using:
-
-::
-
- $ git remote set-url origin ssh://USER@gerrit.gromacs.org/gromacs.git
-
-(change **USER** with the username you've registered)
-
-Or add a new remote url using:
-
-::
-
- $ git remote add upload ssh://USER@gerrit.gromacs.org/gromacs.git
-
-If you are working with a GROMACS repository other than the source code,
-then you should substitute e.g. regressiontests.git or releng.git
-instead of gromacs.git above.
-
-Be sure to configure your user name and e-mail to match those registered to Gerrit::
-
- git config [--global] user.name "Your Name"
- git config [--global] user.email "your.name@domain.org"
-
-It is optional if you want to set those settings for git on a global
-level, or just for the current repository.
-
-If necessary, register the e-mail address you want to use
-with Gerrit.
-
-Install the commit hook
------------------------
-
-Differently from a simple usage of git, with Gerrit a Change-ID is
-needed at the end of each commit message. Gerrit uses Change-IDs to
-understand whether your new commit is patching a previous commit or it
-should be regarded as a separate, different patch, uncorrelated with
-your previously pushed commits.
-
-To allow git to append such Change-IDs automatically after each commit,
-type the following command:
-
-::
-
- $ scp -p USER@gerrit.gromacs.org:hooks/commit-msg .git/hooks/
+#. Go to https://gitlab.com/gromacs/gromacs
-(change **USER** with the username you've registered in Gerrit)
-
-.. Note::
-
- This commit hook needs to be added to the repo where the
- commit will occur, not the repo where the push to upstream will occur
- (should they be different).
+.. todo:: Link to GitLab docs for setting up an account, setting up git, and cloning repositories.
Uploading a commit for review
-----------------------------
Make sure your HEAD is up to date (use ``git pull --rebase origin`` if
someone else has committed since you last pulled), check that your commit
-message follows the :doc:`commitstyle`, make your commit and then use
-
-::
-
- $ git push origin HEAD:refs/for/BRANCH
-
-Replace ``BRANCH`` with the branch it should be committed to.
-Master has a number of sub branches that can be used to show
-what the patch is relevant to such as OpenCL and tools-cleanup.
-These can be pushed to by specifying them after the branch,
-for example ``BRANCH/domdec-cleanup``.
-
-When updating/replacing an existing change, make sure the commit message
-has the same Change-ID. Please see the section `Ammending a change <gmx-ammend-change>`
-below.
+message follows the :doc:`commitstyle`.
Uploading a Work-In-Progress (WIP) or Private commit for review
---------------------------------------------------------------
-You can use the WIP or Private workflow on Gerrit to upload changes
-that might not be ready yet for public review and merging.
-Those changes will only be visible to people explicitly added as reviewers,
-and will not automatically trigger Jenkins if the reviewer "Jenkins Buildbot"
-is not added manually to them.
-
-For uploading a new private change, push to refs/for/master%private
-(substituting master with the branch you want to push to). To remove the private
-flag when uploading a new patch set, use refs/for/master%remove-private.
-To mark change as Work-In-Progress, push to refs/for/master%wip,
-to unmark push to refs/for/master%ready.
-You can also mark and unmark changes as Private or WIP in the Gerrit web-interface.
-
-To manually trigger Jenkins on a WIP or Private change, you need to log in
-to Jenkis after adding the "Jenkins Buildbot" reviewer. In Jenkins, navigate to
-http://jenkins.gromacs.org/gerrit_manual_trigger/ and tell it to
-search for the commit for which you want to trigger the build agents.
-For example, https://gerrit.gromacs.org/#/c/1238/ is 1238 (but maybe
-SHA or ChangeID will work, too).
-Any change made to the commit after "Jenkins Buildbot" was added to the
-list of reviewers will also trigger Jenkins.
-
-After uploading a commit
-------------------------
-
-Use
-
-::
-
- $ git reset --keep HEAD^
-
-to reset your branch to the HEAD before the commit you just uploaded.
-This allows you to keep your repo in sync with what every other repo
-thinks is the HEAD. In particular, if you have another patch to upload
-(or worse, have to pull in other people's patches, and then have a new
-patch), you probably do not want to have the second patch depend on the
-first one. If the first one is rejected, you have made extra work for
-yourself sorting out the mess. Your repo still knows about the commit,
-and you can cherry-pick it to somewhere if you want to use it.
+.. todo:: Note work-in-progress and privacy semantics.
Code Review
===========
The reviewing workflow is the following:
-#. https://gerrit.gromacs.org/#q/status:open shows all open changes
+#. https://gitlab.com/gromacs/gromacs/-/issues shows all open changes
#. A change needs a +2 and usually +1 review, as well as a +2 verified
to be allowed to be merged.
#. Usually a patch goes through several cycles of voting, commenting and
- Check adherence to the :ref:`GROMACS coding
standards <style-guidelines>`;
- We should try to ensure that commits that implement bugfixes (as
- well as important features and tasks) get a `Redmine`_ entry created
- and linked. The linking is done **automatically** by
- `Redmine`_ **if the commit message contains** keyword
- "#issueID", the valid syntax is explained below.
+ well as important features and tasks) get an `issue tracker`_ entry created
+ and linked. The linking is done **automatically** through
+ `special syntax <https://gitlab.com/help/user/markdown#special-gitlab-references>`__
- If the commit is a **bugfix**\ :
- - if present in Redmine it has to contain a valid reference to the
+ - if present in the `issue tracker`_, it has to contain a valid reference to the
issue;
- - if it's a **major bug**, there has to be a bug report filed in
- `Redmine`_ (with urgent or
+ - if it's a **major bug**, there has to be a bug report filed in the
+ `issue tracker`_ (with urgent or
immediate priority) and referenced appropriately.
- If the commit is a **feature/task** implementation:
- - if it's present in `Redmine`_ it
+ - if it's present in the `issue tracker`_ it
has to contain a valid reference to the issue;
- If no current issue is currently present and the change
would benefit of one for future explanation on why it was
- added, a new redmine issue should be created.
-
-Use of Verify
--------------
-
-Jenkins has been installed for automated build testing. So it isn't
-required to vote "verify +2" anymore. As the testing is not always
-perfect, and because test coverage can be spotty, developers can still
-manually vote to indicate that a change performs as intended. Please note
-that this should not be abused to bypass Jenkins testing. The vote from
-the test suite should only be discarded if failures are caused by unrelated
-issues.
-
-Further information
--------------------
-
-Currently it is possible to review your own code. It is undesirable to
-review your own code, because that defeats the point. It will be
-deactivated if it is being abused and those responsible may lose
-their voting rights.
-
-For further documentation:
-
-- |Gromacs| `specific manual <https://gerrit.gromacs.org/Documentation/index.html>`__
-- `General tutorials <https://gerrit-documentation.storage.googleapis.com/Documentation/2.15.3/index.html#_tutorials>`__
-
-FAQs
-====
-
-How do I access gerrit behind a proxy?
---------------------------------------
-
-If you are behind a firewall blocking port 22, you can use socat to
-overcome this problem by adding the following block to your
-``~/.ssh/config``
-
-::
-
- Host gerrit.gromacs.org
- User USER
- Hostname gerrit.gromacs.org
- ProxyCommand socat - PROXY:YOURPROXY:gerrit.gromacs.org,proxyport=PORT
-
-Replace ``YOURPROXY``, ``PORT`` and ``USER``, (but not ``PROXY``!) with your own
-settings.
-
-How do I link fixes with Redmine issues?
-----------------------------------------
-
-The linking of commits that relate to an existing issue is
-done automatically by `Redmine`_ if
-the git commit message contains a reference to the Redmine entry
-through the issueID, the numeric ID of the respective issue (bug,
-feature, task). The general syntax of a git comit reference is [keyword]
-#issueID.
-
-The following two types of refereces are possible:
-
-- For bugfix commits the issueID should be preceeded by
- the "Fixes" keyword;
-- For commits related to a general issue (e.g. partial implementation of
- feature or partial fix), the issueID should be preceeded by the "Refs" keyword;
-
-An example commit message header::
-
- This commit refs #1, #2 and fixes #3
-
-How can I submit conflicting changes?
--------------------------------------
-
-When there are several, mutually conflicting changes in gerrit pending
-for review, the submission of the 2nd and subsequent ones will fail.
-Those need to be resolved locally and updated by
-
-::
-
- $ git pull --rebase
-
-Then fix the conflicts and use
-
-::
-
- $ git push
-
-Please add a comment (review without voting) saying that it was rebased
-with/without conflicts, to help the reviewer.
-
-
-.. _gmx-ammend-change:
-
-How do I upload an update to a pending change?
-----------------------------------------------
-
-First, obtain the code you want to update. If you haven't changed your
-local repository, then you already have it. Maybe you can check out the
-branch again, or consult your git reflog. Otherwise, you should go to
-gerrit, select the latest patch set (remembering that others may have
-contributed to your work), and use the "Download" link to give you a
-"Checkout" command that you can run, e.g.
-
-::
-
- $ git fetch ssh://USER@gerrit.gromacs.org/gromacs refs/changes/?/?/? && git checkout FETCH_HEAD
-
-Make your changes, then add them to the index, and use
-
-::
-
- $ git commit --amend
- $ git push origin HEAD:refs/for/BRANCH
-
-When amending the previous commit message, leave the "Change-Id" intact
-so that gerrit can recognize this is an update and not open a new issue.
-
-DO NOT rebase your patch set and update it in one step. If both are done
-in one step, the diff between patch set versions has both kinds of
-changes. This makes it difficult for the reviewer, because it is not
-clear what parts have to be re-reviewed. If you need to update and
-rebase your change please do it in two steps (order doesn't matter).
-gerrit has a feature that allows you to rebase within gerrit, which
-creates the desired independent patch for that rebase (if the rebase is
-clean).
-
-How do I get a copy of my commit for which someone else has uploaded a patch?
------------------------------------------------------------------------------
-
-Gerrit makes this easy. You can download the updated commit in various
-ways, and even copy a magic git command to your clipboard to use in your
-shell.
-
-You can select the kind of git operation you want to do (cherry-pick is
-best if you are currently in the commit that was the parent, checkout is
-best if you just want to get the commit and not worry about the current
-state of your checked out git branch) and how you want to get it. The
-icon on the far right will paste the magic shell command into your
-clipboard, for you to paste into a terminal to use.
-
-How do I submit lots of independent commits (e.g. bug fixes)?
--------------------------------------------------------------
-
-Simply pushing a whole commit tree of unrelated fixes creates
-dependencies between them that make for trouble when one of them needs
-to be changed. Instead, from an up-to-date repo, create and commit the
-first change (or git cherry-pick it from an existing other branch).
-Upload it to gerrit. Then do
-
-::
-
- $ git reset --keep HEAD^
-
-This will revert to the old HEAD, and allow you to work on a new commit
-that will be independent of the one you've already uploaded. The one
-you've uploaded won't appear in the commit history until it's been
-reviewed and accepted on gerrit and you've pulled from the main repo,
-however the version of it you uploaded still exists in your repo. You
-can see it with git show or git checkout using its hash - which you can
-get from the gerrit server or by digging in the internals of your repo.
-
-How can I avoid needing to remember all these arcane git commands?
-------------------------------------------------------------------
-
-In your ``.gitconfig``, having set the git remote for the gerrit repo to
-upload, use something like the following to make life easier:
-
-::
-
- [alias]
- upload-r2018 = push origin HEAD:refs/for/release-2018
- upload-r2016 = push origin HEAD:refs/for/release-2016
- upload-master = push origin HEAD:refs/for/master
- upload-reset = reset --keep HEAD^
-
-
-How can I get my patch in gerrit to have a different parent?
-------------------------------------------------------------
-
-Sometimes, some other patch under review is a relevant point from which
-to start work. For simple changes without conflicts to the previous
-work, you can use the Gerrit web UI to either rebase or cherry-pick
-the change you are working on.
-
-If this is not possible, you can still use
-the canned gerrit checkouts to (say) checkout out patch 2117 and start work:
-
-::
-
- git fetch https://gerrit.gromacs.org/gromacs refs/changes/17/2117/2 && git checkout FETCH_HEAD
-
-Other times you might have already uploaded a patch (e.g. patch 1 of
-2145), but now see that some concurrent work makes more sense as a
-parent commit (e.g. patch 2 of 2117), so check it out as above, and then
-use the canned gerrit **cherry-pick**:
-
-::
-
- git fetch https://gerrit.gromacs.org/gromacs refs/changes/45/2145/1 && git cherry-pick FETCH_HEAD
-
-Resolve any merge commits, check things look OK, and then upload.
-Because the ChangeId of 2145 hasn't changed, and nothing about 2117 has
-changed, the second patch set of 2145 will reflect the state of 2145 now
-having 2117 as a parent.
-
-This can also be useful for constructing a short development branch
-where the commits are somehow dependent, but should be separated for
-review purposes. This technique is useful when constructing a series of
-commits that will contribute to a release.
-
-How can I revert a change back to an old patchset?
---------------------------------------------------
-
-If a change accidentally gets updated or when a patchset is incorrect,
-you might want to revert to an older patchset. This can be done by
-fetching an old patchset, running git commit --amend to update the time
-stamp in the commit and pushing the commit back up to gerrit. Note that
-without the amending you will get an error from the remote telling you
-that there are no new changes.
-
-How do I handle common errors
------------------------------
-
-.. rubric:: error: server certificate verification failed. CAfile...
-
-If you try to cherry-pick a change from the server, you'll probably get
-the error:
-
-::
-
- $ git fetch https://gerrit.gromacs.org/p/gromacs refs/changes/09/109/1 && git cherry-pick FETCH_HEAD
- error: server certificate verification failed.
- CAfile: /etc/ssl/certs/ca-certificates.crt
- CRLfile: none while accessing https://gerrit.gromacs.org/p/gromacs/info/refs
-
- fatal: HTTP request failed
-
-As explained
-`here <http://code.google.com/p/chromium-os/issues/detail?id=13402>`__,
-the problem is with git not trusting the certificate and as a workaround
-one can set globally
-
-::
-
- $ git config --global --add http.sslVerify false
-
-or prepend GIT_SSL_NO_VERIFY=1 to the command
-
-::
-
- $ GIT_SSL_NO_VERIFY=1 git fetch https://gerrit.gromacs.org/p/gromacs refs/changes/09/109/1 \
- && git cherry-pick FETCH_HEAD
-
-.. rubric:: Various error messages and their meanings
-
-http://review.coreboot.org/Documentation/error-messages.html
+ added, a new issue should be created.
More git tips
=============
amend your existing commit with
``git commit --amend``. After you are
satisfied, you can push the
-commit into gerrit for review. If
+commit for review. If
you stashed away your changes and
you want the next change to be
reviewed independently, do
git stash pop
(only do this if you pushed the
-previous change to gerrit,
+previous change upstream,
otherwise it is difficult to get
the old changes back!) and repeat
until each independent change is
::
git rebase -i master
-
-.. rubric:: Interacting with Gerrit
- :name: interacting-with-gerrit
- :class: editable
-
-This section is intended for
-using git to interact with
-gerrit; interacting with the web
-UI may be better dealt with on a
-separate page.
-
-.. rubric:: Q: How do I move a change from a branch to another?
-
-A: Moving one or a few changes is
-most easily done using ``git
-cherry-pick``. To move a single
-change, first do
-
-::
-
- git checkout <target-branch>
-
-Then, open the change/patch set
-in Gerrit that you want to move,
-select "cherry-pick" in the
-Download section for that patch
-set, and copy/paste the given
-command:
-
-::
-
- git fetch ... refs/changes/... && git cherry-pick FETCH_HEAD
-
-Resolve any conflicts and do
-
-::
-
- git commit [-a]
-
-You can also cherry-pick multiple
-changes this way to move a small
-topic branch. Before pushing the
-change to Gerrit, remove the
-lines about conflicts from the
-commit message, as they don't
-serve any useful purpose in the
-history. You can type that
-information into the change as a
-Gerrit comment if it helps the
-review process. Note that Gerrit
-creates a new change for the
-target branch, even if Change-Ids
-are same in the commits. You need
-to manually abandon the change in
-the wrong branch.
-
.. highlight:: bash
The source code can be automatically formatted using clang-format
-(GROMACS 2020 and later)
-or uncrustify (GROMACS 2019 and earlier).
+since GROMACS 2020.
Both are formatting tools that apply the guidelines in :doc:`formatting`.
Additionally, other Python scripts are used for a few other automatic
formatting/checking tasks. The overview tools page contains a list of these
tools: :ref:`dev-formatting-tools`.
-This page provides more details for clang-format, uncrustify and copyright scripts.
+This page provides more details for clang-format, clang-tidy and copyright scripts.
-Jenkins uses these same scripts (in particular, ``clang-format.sh``,
-``copyright.sh`` and the ``check-source`` target) to enforce that
+Our CI uses these same scripts (in particular, ``clang-format.sh``,
+``copyright.sh``, ``clang-tidy.sh`` and the ``check-source`` target) to enforce that
the code stays invariant under such formatting.
-.. _gmx-uncrustify:
-
-Setting up uncrustify
----------------------
-
-A patched version of uncrustify is used for |Gromacs|. To set this up, you need
-to do these (once):
-
-1. Change to a directory under which you want to build uncrustify and run::
-
- git clone -b gromacs git://github.com/rolandschulz/uncrustify.git
- cd uncrustify
- ./configure
- make
-
-2. Copy the binary ``src/uncrustify`` into a directory of your choice
- (``/path/to/uncrustify`` below).
-
-Alternatively, if you are running Linux, you can try whether the binary from
-http://redmine.gromacs.org/issues/845 works for you.
-
-In order to use the binary for ``uncrustify.sh`` and for the pre-commit hook, you
-also need to run this in each of your |Gromacs| repositories::
-
- git config hooks.uncrustifypath /path/to/uncrustify
-
-Alternatively, if you just want to use ``uncrustify.sh``, you can set the
-``UNCRUSTIFY`` environment variable to ``/path/to/uncrustify``.
-
-Using the pre-commit hook or git filters needs additional setup; see the
-respective sections below.
-
-Note that Jenkins now only allows formatting using ``clang-format``.
-
.. _gmx-clang-format:
Setting up clang-format
Alternatively, if you just want to use ``clang-format.sh``, you can set the
``CLANG_FORMAT`` environment variable to ``/path/to/clang-format``.
-As above, see the sections below for using the pre-commit hook or git filters.
+Using the pre-commit hook or git filters needs additional setup; see the
+respective sections below.
clang-format discovers which formatting rules to apply from the
:file:`.clang-format` configuration file(s) in project directories,
attribute ``filter`` set to one of the below values are processed:
- ``filter=complete_formatting``: Performs all formatting. Uses clang-format for code formatting.
-- ``filter=uncrustify``: uncrustify is run. Deprecated and here for historical reasons.
-- ``filter=clangformat``: clang-format is run.
+ Files included here are also passed to the clang-tidy code checker.
+- ``filter=clangformat``: clang-format is run. Again also runs clang-tidy.
- ``filter=includesort``: include order is enforced and copyright headers are checked.
- ``filter=copyright``: only copyright headers are checked.
-Other files are ignored by ``uncrustify.sh``, ``clang-format.sh``,
+Other files are ignored by ``clang-tidy.sh``, ``clang-format.sh``,
``copyright.sh`` and ``reformat_all.sh`` scripts (see below).
+.. _gmx-clang-tidy:
+
+Setting up clang-tidy
+---------------------
+
+|Gromacs| source code tidiness checking is enforced with clang-tidy provided
+alongside *clang* compiler version 9.
+:command:`clang-tidy` is one of the core *clang* tools.
+It may be included in a *clang* or *llvm* package from your favorite packaging
+system or you may find a standalone *clang-tidy* or *clang-tools* package,
+but you should confirm that the provided command is version 9.
+Example::
+
+ $ clang-tidy --version
+ LLVM (http://llvm.org/):
+ LLVM version 9.0.0
+
+If you use a different version of clang-tidy,
+you will likely get different checking results than
+the |Gromacs| continuous integration testing system,
+and the commits that you push will fail the automated tests.
+
+.. note::
+
+ Refer to `LLVM <http://releases.llvm.org/download.html#9.0.1>`__ for
+ source and binary downloads.
+ If downloading sources, note that you will need to download both the
+ *LLVM source code* and the *Clang source code*.
+ As per the clang
+ `INSTALL.txt <https://github.com/llvm/llvm-project/blob/release/9.x/clang/INSTALL.txt>`__,
+ place the expanded clang source into a :file:`tools/clang` subdirectory within
+ the expanded llvm archive, then run CMake against the llvm source directory.
+
+In order to use the installed version of clang-tidy for ``clang-tidy.sh``
+and for the pre-commit hook, you also need to run this in each of your |Gromacs| repositories::
+
+ git config hooks.runclangtidypath /path/to/run-clang-tidy.py
+
+Alternatively, if you just want to use ``clang-tidy.sh``, you can set the
+``RUN_CLANG_TIDY`` environment variable to ``/path/to/run-clang-tidy.py``.
+
+As above, see the sections below for using the pre-commit hook or git filters.
+
+clang-tidy discovers which formatting rules to apply from the
+:file:`.clang-tidy` configuration file(s) in project directories,
+which will be automatically updated (if necessary) when you :command:`git pull`
+from the |Gromacs| repository.
+For more about the tool and the :file:`.clang-tidy` configuration file,
+visit http://releases.llvm.org/9.0.0/tools/clang/tools/extra/docs/clang-tidy/index.html
Scripts
-------
the script with ``--help`` option if you want to see what all options it provides
if you need to do some maintenance on the copyright headers themselves.
-``uncrustify.sh``
-^^^^^^^^^^^^^^^^^
-
-The information for ``uncrustify`` is mainly provided for historical reasons,
-as the actual code formatting is now done using ``clang-format``.
-
-This script runs ``uncrustify`` on modified files and reports/applies the results.
-By default, the current HEAD commit is compared to the work tree,
-and files that
-
-1. are different between these two trees and
-2. change under uncrustify
-
-are reported. This behavior can be changed by
-
-1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
- the base of the comparison. A typical use case is to specify ``--rev=HEAD^``
- to check the HEAD commit.
-2. Specifying an action:
-
- - ``check-*``: reports the files that uncrustify changes
- - ``diff-*``: prints the actual diff of what would change
- - ``update-*``: applies the changes to the repository
- - ``*-workdir``: operates on the working directory (files on disk)
- - ``*-index``: operates on the index of the repository
-
- For convenience, if you omit the workdir/index suffix, workdir is assumed
- (i.e., ``diff`` equals ``diff-workdir``).
-3. Specifying ``--uncrustify=off``, which does not run uncrustify.
-
-By default, ``update-*`` refuses to update dirty files (i.e., that differ
-between the disk and the index) to make it easy to revert the changes.
-This can be overridden by adding a ``-f``/``--force`` option.
-
``copyright.sh``
^^^^^^^^^^^^^^^^
This script runs ``copyright.py`` on modified files and reports/applies the results.
-By default, the current HEAD commit is compared to the work tree,
+By default, the current HEAD commit on the source branch is compared to the work tree,
and files that
1. are different between these two trees and
^^^^^^^^^^^^^^^^^^^
This script runs ``clang-format`` on modified files and reports/applies the results.
-By default, the current HEAD commit is compared to the work tree,
+By default, the current HEAD commit on the source branch is compared to the work tree,
and files that
1. are different between these two trees and
between the disk and the index) to make it easy to revert the changes.
This can be overridden by adding a ``-f``/``--force`` option.
+``clang-tidy.sh``
+^^^^^^^^^^^^^^^^^
+
+This script runs the ``clang-tidy`` source code checker on modified files
+and either reports or applies resulting changes. By default, the current
+HEAD commit on the source branch is compared to the work tree,
+and files that
+
+1. are different between these two trees and
+2. change when applying clang-tidy
+
+are reported. This behavior can be changed by
+
+1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
+ the base of the comparison. A typical use case is to specify ``--rev=HEAD^``
+ to check the HEAD commit.
+2. Specifying an action:
+
+ - ``check-*``: reports the files that clang-format changes
+ - ``diff-*``: prints the actual diff of what would change
+ - ``update-*``: applies the changes to the repository
+ - ``*-workdir``: operates on the working directory (files on disk)
+ - ``*-index``: operates on the index of the repository
+
+ For convenience, if you omit the workdir/index suffix, workdir is assumed
+ (i.e., ``diff`` equals ``diff-workdir``).
+3. Specifying ``--tidy=off``, which does not run clang-tidy.
+
+By default, ``update-*`` refuses to update dirty files (i.e., that differ
+between the disk and the index) to make it easy to revert the changes.
+This can be overridden by adding a ``-f``/``--force`` option.
+
+
git pre-commit hook
^^^^^^^^^^^^^^^^^^^
-If you want to run ``uncrustify.sh``, ``copyright.sh`` and/or
+If you want to run ``copyright.sh``, ``clang-tidy.sh`` and/or
``clang-format.sh`` automatically for changes you make, you can
configure a pre-commit hook using ``admin/git-pre-commit``:
1. Copy the ``git-pre-commit`` script to .git/hooks/pre-commit.
-2. Specify the paths to ``uncrustify`` and ``clang-format`` for the hook if you have not already done
+2. Specify the paths to ``run-clang-tidy`` and ``clang-format`` for the hook if you have not already done
so::
- git config hooks.uncrustifypath /path/to/uncrustify
+ git config hooks.runclangtidypath /path/to/run-clang-tidy.py
git config hooks.clangformatpath /path/to/clang-format
3. Set the operation modes for the hook::
- git config hooks.uncrustifymode check
+ git config hooks.clangtidymode check
git config hooks.clangformatmode check
git config hooks.copyrightmode update
With this configuration, all source files modified in the commit are run
-through the respective code formatting tool and checked for correct copyright headers.
-If any file would be changed by ``uncrustify.sh``, ``clang-format.sh`` or ``copyright.sh``,
+through the code formatting tool, are checked with clang-tidy
+and also checked for correct copyright headers.
+If any file would be changed by ``clang-tidy.sh``, ``clang-format.sh`` or ``copyright.sh``,
the names of those files are reported and the commit is prevented.
The issues can be fixed by running the scripts manually.
To disable the hook without removing the ``pre-commit`` file, you can set ::
- git config hooks.uncrustifymode off
+ git config hooks.clangtidymode off
git config hooks.copyrightmode off
git config hooks.clangformatmode off
changes that are getting amended, not for the whole commit. During a rebase,
the hook is not run.
-The actual work is done by the ``admin/uncrustify.sh``, ``admin/clang-format.sh``
+The actual work is done by the ``admin/clang-tidy.sh``, ``admin/clang-format.sh``
and ``admin/copyright.sh`` scripts, which get run with the ``check-index`` action,
-and with ``--uncrustify``, ``--copyright`` and ``--format`` getting set according
+and with ``--copyright`` and ``--format`` getting set according
to the ``git config`` settings.
``reformat_all.sh``
^^^^^^^^^^^^^^^^^^^
-This script runs uncrustify, clang-format, ``copyright.py``, or the include sorter for all
+This script runs clang-format, ``copyright.py``, or the include sorter for all
applicable files in the source tree. See ``reformat_all.sh -h`` for the
invocation.
clang-format on changes is to use a git filter (does not require either of the scripts,
only the ``.gitattributes`` file). You can run ::
- git config filter.complete_formatting.clean \
- "/path/to/uncrustify -c admin/uncrustify.cfg -q -l cpp"
git config filter.clangformat.clean \
"/path/to/clang-format -i"
Commit messages should contain a quick explanation in verb form on what has been
changed or what has been the purpose of the change. If available, the final
part of the message before the ChangeId should be a short section like
-**Fixes #redmine-id** to link the change to a possibly previously
-posted issue, or **Refs #redmine-id** if the present patch is somehow
+**Fixes #issue-id** to link the change to a possibly previously
+posted issue, or **Refs #issue-id** if the present patch is somehow
related to that work without necessarily fixing the whole issue.
Concerning inline code comments
widespread adoption of the method.
* *Advance discussion*: Please communicate with the other developers,
- e.g. on the `developer mailing list`_ mailing list, or `redmine`_ to let them know of the general
+ e.g. on the `developer mailing list`_ mailing list, or `issue tracker`_ to let them know of the general
nature of your plans. This will prevent duplicate or wasted
effort. It is also a good idea to search those resources as well as
the literature and WWW for other projects that may be relevant.
Preparing code for submission
-----------------------------
-|Gromacs| revision control uses a ``git`` repository managed by :ref:`Gerrit <gmx-gerrit>`.
+|Gromacs| uses ``git`` for :doc:`change-management`.
Instead of accepting "pull requests", |Gromacs| changes are submitted as individual
-commits on the tip of the ``master`` branch hosted at https://gerrit.gromacs.org.
+commits on the tip of the ``master`` branch hosted at `gitlab`_.
Preparing, submitting, and managing patches for a change requires a little bit
of set-up. Refer to :doc:`change-management` for information about
-* accessing the |Gromacs| Gerrit server
+* accessing the |Gromacs| *git* repository
* structure of the repository
* source control without merge commits
* ``git`` usage that may be less common in other development work flows
Also requires ImageMagick for converting graphics file formats.
linkchecker
- The linkchecker program is used together with the linkcheckerrc file to ensure
+ `linkchecker <http://wummel.github.io/linkchecker/>`__ is used together with the
+ :file:`docs/linkcheckerrc` file to ensure
that all the links in the documentation can be resolved correctly.
documentation exported from source files
--- /dev/null
+GitLab
+======
+
+The repository contains DockerFiles and GitLab Runner configuration
+files to support automated testing and documentation builds.
+General information on configuring GitLab CI pipelines can be found
+in the official `Gitlab documentation <https://docs.gitlab.com/ee/ci/yaml/>`_.
+
+The GitLab CI configuration entry point is the :file:`.gitlab-ci.yml` file
+at the root of the source tree.
+Configuration templates are found in the files in the
+:file:`admin/ci-templates/` directory.
+
+Docker images used by GitLab Runner are available on `Docker Hub <https://hub.docker.com/u/gromacs>`__.
+Images are (re)built manually using details in :file:`admin/containers`.
+
+This documentation is incomplete, pending resolution of :issue:`3275`.
+
+.. todo:: Expand this documentation to resolve :issue:`3275`
+
+Pipeline execution
+------------------
+
+.. todo:: Discuss the distinct characteristics of |Gromacs| CI pipelines to relevant to job configuration.
+
+.. todo:: Comment on the number of pipelines that can be or which are likely to be running at the same time.
+
+.. note::
+
+ Full automated testing is only available for merge requests originating from
+ branches of the main https://gitlab.com/gromacs/gromacs repository.
+ GitLab CI pipelines created for forked repositories will include fewer jobs
+ in the testing pipeline. Non-trivial merge requests may need to be issued
+ from a branch in the ``gromacs`` project namespace in order to receive
+ sufficient testing before acceptance.
+
+Configuration files
+~~~~~~~~~~~~~~~~~~~
+
+At the root of the repository, :file:`.gitlab-ci.yml` defines the stages and
+some default parameters, then includes files from :file:`admin/gitlab-ci/` to
+define jobs to be executed in the pipelines.
+
+Note that job names beginning with a period (``.``) are
+`"hidden" <https://docs.gitlab.com/ee/ci/yaml/#hidden-keys-jobs>`_.
+Such jobs are not directly eligible to run, but may be used as templates
+via the `*extends* job property <https://docs.gitlab.com/ee/ci/yaml/#extends>`_.
+
+Job parameters
+~~~~~~~~~~~~~~
+
+Refer to https://docs.gitlab.com/ee/ci/yaml for complete documentation on
+GitLab CI job parameters, but note the following GROMACS-specific conventions.
+
+.. glossary::
+
+ before_script
+ Used by several of our templates to prepend shell commands to
+ a job *script* parameter.
+ Avoid using *before-script* directly, and be cautious
+ about nested *extends* overriding multiple *before_script* definitions.
+
+ cache
+ There is no global default, but jobs that build software will likely
+ set *cache*. To explicitly unset *cache* directives, specify a job
+ parameter of ``cache: {}``.
+ Refer to `GitLab docs <https://docs.gitlab.com/ee/ci/yaml/#cache>`__
+ for details. In particular, note the details of cache identity according
+ to `cache:key <https://docs.gitlab.com/ee/ci/yaml/#cachekey>`__
+
+ image
+ Part of the tool chain configuration. Instead of setting *image*
+ directly, *extend* a *.use_<toolchain>* template from
+ :file:`admin/gitlab-ci/global.gitlab-ci.yml`
+
+ rules
+ only
+ except
+ when
+ *Job* parameters for controlling the circumstances under which jobs run.
+ (Some key words may have different meanings when occurring as elements
+ of other parameters, such as *archive:when*, to which this note is not
+ intended to apply.)
+ Instead of setting any of these directly in a job definition, try to use
+ one of the pre-defined behaviors (defined as ``.rules:<something>`` in
+ :file:`admin/gitlab-ci/global.gitlab-ci.yml`).
+ Errors or unexpected behavior will occur if you specify more than one
+ *.rules:...* template, or if you use these parameters in combination
+ with a *.rules...* template.
+ To reduce errors and unexpected behavior, restrict usage of these controls
+ to regular job definitions (don't use in "hidden" or parent jobs).
+
+ tags
+ By `default <https://docs.gitlab.com/ee/ci/yaml/#setting-default-parameters>`__,
+ jobs require the ``k8s-scilifelab`` tag, which identifies Runners in the
+ |Gromacs| infrastructure. A small number of jobs in the first pipeline
+ stage override the default with an empty tag list so that all GitLab
+ users can run basic tests in their forked project.
+
+ variables
+ Many job definitions will add or override keys in *variables*.
+ Refer to `GitLab <https://docs.gitlab.com/ee/ci/yaml/#variables>`__
+ for details of the merging behavior. Refer to :ref:`variables` for local usage.
+
+Schedules and triggers
+~~~~~~~~~~~~~~~~~~~~~~
+
+Pipeline `schedules <https://gitlab.com/help/ci/pipelines/schedules>`__ are
+configured through the GitLab web interface.
+Scheduled pipelines may provide different variable definitions through the
+environment to jobs that run under the ``schedules``
+`condition <https://gitlab.com/help/ci/pipelines/schedules#using-only-and-except>`__.
+
+Nightly scheduled pipelines run against ``master`` and *release* branches in
+the GROMACS repository.
+
+Global templates
+~~~~~~~~~~~~~~~~
+
+In addition to the templates in the main job definition files,
+common "mix-in" functionality and behavioral templates are defined in
+:file:`admin/gitlab-ci/global.gitlab-ci.yml`.
+
+Jobs beginning with ``.use-`` provide mix-in behavior, such as boilerplate for
+jobs using a particular tool chain.
+
+Jobs beginning with a `parameter <https://docs.gitlab.com/ee/ci/yaml>`__
+name allow parameters to be set in a single place for common job characteristics.
+If providing more than a default parameter value, the job name should be suffixed
+by a meaningful descriptor and documented within
+:file:`admin/gitlab-ci/global.gitlab-ci.yml`
+
+Job names
+~~~~~~~~~
+
+Job names should
+
+1. Indicate the purpose of the job.
+2. Indicate relationships between multi-stage tasks.
+3. Distinguish jobs in the same stage.
+4. Distinguish job definitions throughout the configuration.
+
+Jobs may be reassigned to different stages over time, so including the stage
+name in the job name is not helpful, generally. If tags like "pre" and "post,"
+or "build" and "test" are necessary to distinguish phases of, say, "webpage,"
+then such tags can be buried at the end of the job name.
+
+Stylistically, it is helpful to use delimiters like ``:`` to distinguish the
+basic job name from qualifiers or details. Also consider
+`grouping jobs <https://docs.gitlab.com/ee/ci/pipelines/index.html#grouping-jobs>`__
+
+.. _variables:
+
+Variables
+~~~~~~~~~
+
+The GitLab CI framework, GitLab Runner, plugins, and our own scripts set and
+use several `variables <https://docs.gitlab.com/ee/ci/variables/README.html>`__.
+
+Default values are available from the ``.variables:default`` definition in
+:file:`admin/gitlab-ci/global.gitlab-ci.yml`.
+Many of the mix-in / template jobs provide additional or overriding definitions.
+Other variables may be set when making final job definitions.
+
+Variables may control the behvior of GitLab-CI (those beginning with ``CI_``),
+GitLab Runner and supporting infrastructure, or may be used by job definitions,
+or passed along to the environment of executed commands.
+
+*variables* keys beginning with ``KUBERNETES_`` relate to the GitLab Runner
+`Kubernets executor <https://docs.gitlab.com/runner/executors/kubernetes.html#the-kubernetes-executor>`__
+
+Other important variable keys are as follows.
+
+.. glossary::
+ CI_PROJECT_NAMESPACE
+ Distinguishes pipelines created for repositories in the ``gromacs``
+ GitLab project space. May be used to pre-screen jobs to determine
+ whether |Gromacs| GitLab infrastructure is available to the pipeline
+ before the job is created.
+
+ COMPILER_MAJOR_VERSION
+ Integer version number provided by toolchain mix-in for convenience and
+ internal use.
+
+ CMAKE_COMPILER_SCRIPT
+ CMake command line options for a tool chain. A definition is provided by
+ the mix-in toolchain definitions (e.g. ``.use-gcc8``) to be appended to
+ :command:`cmake` calls in a job's *script*.
+
+ CMAKE_MPI_OPTIONS
+ Provide CMake command line arguments to define GROMACS MPI build options.
+
+ GROMACS_RELEASE
+ Read-only environment variable that can be checked to see if a job is
+ executing in a pipeline for preparing a tagged release.
+ Can be set when launching pipelines via the GitLab web interface.
+ For example, see *rules* mix-ins in :file:`admin/gitlab-ci/global.gitlab-ci.yml`.
+
+ EXTRA_INSTALLS
+ List additional OS package requirements. Used in *before_script* for some
+ mix-in job definitions to install additional software dependencies. If
+ using such a job with *extends*, override this variable key with a
+ space-delimited list of packages (default: ``""``). Consider proposing a
+ patch to the base Docker images to include the dependency to reduce
+ pipeline execution time.
+
+.. todo:: Define common variables.
+ ``BUILD_DIR``, ``INSTALL_DIR``, ``CACHE_FALLBACK_KEY``, ...
--- /dev/null
+=============================
+Automation and Infrastructure
+=============================
+
+Through the 2020 release, automated testing and documentation builds are
+performed by a Jenkins installation. With the resolution of :issue:`3272`,
+|Gromacs| is transitioning to GitLab and GitLab Runner.
+
+.. toctree::
+ :maxdepth: 2
+
+ jenkins
+ gitlab
+ containers
+
Understanding Jenkins builds
============================
-This page documents what different Jenkins builds actually run from the
-|Gromacs| source tree. The purpose is two-fold:
+This page documents what different Jenkins builds actually run at
+http://jenkins.gromacs.org/ from the |Gromacs| source tree.
+The purpose is two-fold:
* Provide information on how to interpret Jenkins failures and how to run the
same tasks locally to diagnose issues (in most cases, referring to the
Portability considerations
^^^^^^^^^^^^^^^^^^^^^^^^^^
-Most |Gromacs| files compile as C++14, but some files remain that compile as C99.
+Most |Gromacs| files compile as C++17, but some files remain that compile as C99.
C++ has a lot of features, but to keep the source code maintainable and easy to read,
we will avoid using some of them in |Gromacs| code. The basic principle is to keep things
as simple as possible.
* MSVC supports only a subset of C99 and work-arounds are required in those cases.
-* We should be able to use virtually all C++14 features outside of OpenCL kernels
+* We should be able to use virtually all C++17 features outside of OpenCL kernels
(which compile as C), and for consistency also in CUDA kernels.
C++ Standard Library
--------------------
-|Gromacs| code must support the lowest common denominator of C++14 standard library
+|Gromacs| code must support the lowest common denominator of C++17 standard library
features available on supported platforms.
Some modern features are useful enough to warrant back-porting.
Consistent and forward-compatible headers are provided in ``src/gromacs/compat/``
advanced projects in constant development, and as our needs evolve we will both
relax and tighten many of these points. Some of these changes happen naturally as
part of agreements in code review, while major parts where we don't agree should be
-pushed to a redmine thread. Large changes should be suggested early in the development
+pushed to a `issue tracker`_ thread. Large changes should be suggested early in the development
cycle for each release so we avoid being hit by last-minute compiler bugs just before
a release.
* Use ``optional<T>`` types in situations where there is exactly one,
reason (that is clear to all parties) for having no value of type T,
and where the lack of value is as natural as having any regular
- value of T. Good examples include the return type of a function that
- parses an integer value from a string, searching for a matching
+ value of T, see |linkoptionalboost|. Good examples include the return type of a
+ function that parses an integer value from a string, searching for a matching
element in a range, or providing an optional name for a residue
- type. Prefer some other construct when the logic requires an
- explanation of the reason why no regular value for T exists, ie. do
- not use ``optional<T>`` for error handling.
+ type. Do use optional for lazy loading of resources, e.g., objects that have
+ no default constructor and are hard to construct.
+ Prefer other constructs when the logic requires an explanation of the
+ reason why no regular value for T exists, e.g., do not use ``optional<T>``
+ for error handling.
+ ``optional<T>`` "models an object, not a pointer, even though operator*() and
+ operator->() are defined" (|linkoptionalcppref|). No dynamic memory allocation
+ ever takes place and forward declaration of objects stored in ``optional<T>``
+ does not work. Thus refrain from optional when passing handles; in contrast to
+ unique_ptr, optional has value semantics, not reference semantics.
* Don't use C-style casts; use ``const_cast``, ``static_cast`` or
``reinterpret_cast as appropriate``. See the point on RTTI for
``dynamic_cast``. For emphasizing type (e.g. intentional integer division)
.. |linkrefnotnull1| replace:: `here <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-nullptr>`__
.. |linkrefnotnull2| replace:: `here <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-nullptr>`__
.. |linkrefstringview| replace:: `here <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html#Rstr-view>`__
-
-
+.. |linkoptionalboost| replace:: `here <https://www.boost.org/doc/libs/release/libs/optional>`__
+.. |linkoptionalbartek| replace:: `here <https://www.bfilipek.com/2018/05/using-optional.html>`__
+.. |linkoptionalcppref| replace:: `cppreference <https://en.cppreference.com/w/cpp/utility/optional>`__
.. _implementing exceptions:
See :doc:`doxygen` for details of how the Doxygen documentation is built and
organized.
-.. TODO: Create a separate page (at the front of the developer guide, and/or at
+.. todo:: Create a separate page (at the front of the developer guide, and/or at
the main index.rst) that describes the documentation from readers'
perspective, and move relevant content there. This should contain just an
overview of how the documentation is organized in the source tree.
:hidden:
We are currently switching our build and testing system to use Gitlab
-and the integrated CI system, with information for the general system found
-in the official `Gitlab documentation <https://docs.gitlab.com/ee/ci/yaml/>`_.
-The new configuration for the builds and tests can be found in the file
-``.gitlab-ci.yml``, with the templates for configuring is found in the files in the
-``admin/ci-templates/`` directory. This section is going to be extended
+CI pipelines run on GitLab Runner. This section is going to be extended
with individual build information as it comes available. For now we are
using a combination of building with the previous system on Jenkins
and post-submit verification on Gitlab.
+.. seealso:: :doc:`../infrastructure`
+
.. _releng-triggering-builds:
Triggering builds on Gitlab
-Guidelines for creating meaningful redmine issue reports
-========================================================
+Guidelines for creating meaningful issue reports
+================================================
This section gives some started on how to generate useful issues on the
-|Gromacs| `redmine issue tracker`_. The information here comes to a large extent
+|Gromacs| `issue tracker`_. The information here comes to a large extent
directly from there, to help you in preparing your reports.
-.. _redmine issue tracker: https://redmine.gromacs.org
-
What to report
^^^^^^^^^^^^^^
Please only report issues you have confirmed to be caused by |Gromacs| behaving in an
not be considered as *real*, or at the minimum it will be much harder to analyse to find the actual issue.
-If your inputs are sensitive, then it is possible to create private Redmine issues so that the
+If your inputs are sensitive, then it is possible to create private `issues`_ so that the
developer team can have access to solve the problem, while preventing widespread
visibility on the internet.
The general issue workflow is shown in the figure below:
.. image:: redmine-states.png
- :alt: Sample procedure pathway for issues reported in redmine.
+ :alt: Sample procedure pathway for reported issues.
.. Text below is stolen from the old Gromacs web page
Guidelines for using Doxygen to document the source code are currently in a
section on the page on general Doxygen usage.
:doc:`reportstyle`
- Guidelines for preparing and formatting bug reports on redmine.
+ Guidelines for preparing and formatting bug reports.
:doc:`commitstyle`
Guidelines for formatting git commits when sending in proposed fixes for code review.
-.. TODO: Add more guidelines
+.. todo:: Add more guidelines
doxygen
change-management
- jenkins
+ infrastructure
releng/index
gmxtree
code-formatting
testutils
physical_validation
-.. TODO: Consider what is the most reasonable structure; currently, this list
+.. todo:: :issue:`3032`
+
+ Consider what is the most reasonable structure; currently, this list
here does not make much sense in the overall organization and creates a
confusing TOC for the developer guide.
-.. TODO: Add details for most of the tools, either in the form of links to wiki,
+.. todo:: :issue:`3267`
+
+ Add details for most of the tools, either in the form of links to wiki,
or to a separate page that explains more details.
Change management
Other basic tutorial material for ``git`` can be found on the `web <https://git-scm.com/doc/ext>`__.
-Gerrit
- All code changes go through a code review system at
- http://gerrit.gromacs.org.
-
-Jenkins
- All changes pushed to Gerrit are automatically compiled and otherwise
- checked on various platforms using a continuous integration system at
- http://jenkins.gromacs.org.
- :doc:`jenkins` documents how Jenkins interacts with the build system,
- providing information on how to replicate the builds Jenkins does (e.g., to
+GitLab
+ Bugs and issues, as well as some random features and discussions,
+ are tracked, and all code changes go through a code review system at
+ https://gitlab.com/gromacs/gromacs.
+
+Build testing
+ All changes pushed to GitLab are automatically compiled and otherwise
+ checked on various platforms.
+ :doc:`infrastructure` documents how builds are automated,
+ providing information on how to replicate the builds (e.g., to
diagnose issues).
:doc:`releng/index` provides more information on the technical implementation
of the builds.
-Redmine
- Bugs and issues, as well as some random features and discussions,
- are tracked at http://redmine.gromacs.org.
-
.. _Git Tips & Tricks: http://www.gromacs.org/index.php?title=Developer_Zone/Git/Git_Tips_%26_Tricks
Build system
------------
-.. TODO: details, ASAN, others?
+.. todo:: details, ASAN, others?
CMake
Main tool used in the build system.
formatting that follows |Gromacs| style guidelines described on a separate page:
:doc:`style`.
-uncrustify
- `uncrustify <http://uncrustify.sourceforge.net>`_ is used for automatic
- indentation and other formatting of the source code to follow
- :doc:`formatting`. All code must remain invariant under uncrustify
- with the config at ``admin/uncrustify.cfg``. A patched version of uncrustify is
- used. See :ref:`gmx-uncrustify` for details.
-
clang-format
We use clang-format to enforce a consistent coding style, with the
settings recorded in ``.clang-format`` in the main tree.
See :ref:`gmx-clang-format` for details.
+clang-tidy
+ The source code linter clang-tidy is used to enforce common restrictions to the
+ code, with the checks collected under ``.clang-tidy`` at the top of the main tree.
+ See :ref:`gmx-clang-tidy` for details.
+
``admin/copyright.py``
This Python script adds and formats copyright headers in source files.
``copyright.sh`` (see below) uses the script to check/update copyright years on
changed files automatically.
-``admin/uncrustify.sh``
- This ``bash`` script runs uncrustify for all
- files that have local changes and checks that they conform to the prescribed
- style. Optionally, the script can also apply changes to make the files
- conform. It is included only for historical reasons.
- See :doc:`formatting` for details.
-
``admin/copyright.sh``
This ``bash`` script runs the ``copyright.py`` python script to enforce
correct copyright information in all files that have local changes
and checks that they conform to the prescribed
style. Optionally, the script can also apply changes to make the files
conform.
- This script is automatically run by Jenkins to ensure that all commits adhere
+ This script is automatically run by the CI to ensure that all commits adhere
to :doc:`formatting`. If the copyright job does not succeed, it
means that this script has something to complain.
See :doc:`code-formatting` for details.
``admin/clang-format.sh``
This script enforces coding style using clang-format.
- This script is automatically run by Jenkins to ensure that all commits adhere
+ This script is automatically run by our CI to ensure that all commits adhere
to :doc:`formatting`.
+``admin/clang-tidy.sh``
+ The clang-tidy code correctness restrictions are enforced by this script.
+ The script is also used by the CI to verify the code, in addition to nightly
+ compilations using clang-tidy on the whole tree.
+
``admin/git-pre-commit``
This sample git pre-commit hook can be used if one wants to apply
- ``uncrustify.sh`` and ``clang-format.sh`` automatically before every commit to check for formatting
+ ``clang-tidy.sh``, ``copyright.sh`` and ``clang-format.sh`` automatically
+ before every commit to check for formatting
issues. See :doc:`code-formatting` for details.
``docs/doxygen/includesorter.py``
applied in the formatting script. To check for issues, it is instead integrated into
a ``check-source`` build target. When this target is built, it also checks for
include formatting issues. Internally, it uses the sorter script. This check
- is run in Jenkins as part of the Documentation job.
+ is run in the CI as part of the Documentation job.
Details for the checking mechanism are on a separate page (common for several
checkers): :doc:`gmxtree`.
``admin/reformat_all.sh``
- This ``bash`` script runs uncrustify/clang-format/``copyright.py``/include sorter
+ This ``bash`` script runs clang-format/``copyright.py``/include sorter
on all relevant files in the source tree (or in a particular directory).
The script can also produce the list of files where these scripts are applied,
for use with other scripts. See :doc:`code-formatting` for details.
checking/formatting to apply. Custom attributes are used for specifying some
build system dependencies for easier processing in CMake.
-include-what-you-use
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
mark_as_advanced(GMX_COMPACT_DOXYGEN)
set(USE_PYTHON_SCRIPTS OFF)
-if (PYTHONINTERP_FOUND)
+if (PYTHON_EXECUTABLE)
set(USE_PYTHON_SCRIPTS ON)
endif()
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
"""Add a compound that contains this member."""
self._parents.add(compound)
if isinstance(compound, Class):
- assert self._class is None
+ assert self._class is None, 'Class \"{0}\" was already added. Maybe you have two entities with the same name.'.format(self._class)
self._class = compound
elif isinstance(compound, Namespace):
- assert self._namespace is None
+ assert self._namespace is None, 'Namespace \"{0}\" was already added. Maybe you have two entities with the same name.'.format(self._namespace)
self._namespace = compound
elif isinstance(compound, File):
self._files.add(compound)
elif isinstance(compound, Group):
- assert self._group is None
+ assert self._group is None, 'Group \"{0}\" was already added.'.format(self._group)
self._group = compound
else:
assert False
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
def load_git_attributes(self):
"""Load git attribute information for files."""
args = ['git', 'check-attr', '--stdin', 'filter']
- git_check_attr = subprocess.Popen(args, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, cwd=self._source_root)
- filelist = '\n'.join(map(File.get_relpath, self._files.values()))
- filters = git_check_attr.communicate(filelist.encode())[0].decode()
+ filelist = '\n'.join(map(File.get_relpath, self._files.values())) + '\n'
+ git_check_attr = subprocess.run(args,
+ input=filelist,
+ stdout=subprocess.PIPE,
+ universal_newlines=True,
+ cwd=self._source_root)
+ filters = git_check_attr.stdout
for fileinfo in filters.splitlines():
path, dummy, value = fileinfo.split(': ')
fileobj = self._files.get(path)
args.extend(['-e', define])
args.extend(['--', '*.cpp', '*.c', '*.cu', '*.h', '*.cuh'])
define_re = r'\b(?:' + '|'.join(all_defines)+ r')\b'
- output = subprocess.check_output(args, cwd=self._source_root).decode()
- for line in output.splitlines():
+ completed_process = subprocess.run(args,
+ cwd=self._source_root,
+ universal_newlines=True,
+ stdout=subprocess.PIPE)
+ for line in completed_process.stdout.splitlines():
(filename, text) = line.split('\0')
fileobj = self._files.get(filename)
if fileobj is not None and fileobj not in excluded_files:
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
'stddef.h', 'stdint.h', 'stdio.h', 'stdlib.h', 'string.h',
'time.h']
_std_c_cpp_headers = ['c' + x[:-2] for x in _std_c_headers]
- _std_cpp_headers = ['algorithm', 'array', 'chrono', 'deque', 'exception', 'fstream',
- 'functional', 'initializer_list', 'iomanip', 'ios', 'iosfwd',
- 'iostream', 'istream', 'iterator',
- 'limits', 'list', 'map', 'memory', 'mutex',
- 'new', 'numeric', 'ostream', 'random',
- 'regex', 'set', 'sstream', 'stdexcept', 'streambuf', 'string', 'strstream',
- 'thread', 'tuple', 'type_traits', 'typeindex', 'typeinfo', 'vector',
- 'unordered_map', 'utility']
+ _std_cpp_headers = ['algorithm',
+ 'any',
+ 'array',
+ 'atomic',
+ 'charconv',
+ 'chrono',
+ 'cinttypes',
+ 'cfenv',
+ 'complex',
+ 'cstdint',
+ 'deque',
+ 'exception',
+ 'execution',
+ 'filesystem',
+ 'forward_list',
+ 'fstream',
+ 'functional',
+ 'future',
+ 'initializer_list',
+ 'iomanip',
+ 'ios',
+ 'iosfwd',
+ 'iostream',
+ 'istream',
+ 'iterator',
+ 'limits',
+ 'list',
+ 'locale',
+ 'map',
+ 'memory',
+ 'memory_resource',
+ 'mutex',
+ 'new',
+ 'numeric',
+ 'optional',
+ 'ostream',
+ 'queue',
+ 'random',
+ 'ratio',
+ 'regex',
+ 'scoped_allocator',
+ 'set',
+ 'sstream',
+ 'stack',
+ 'stdexcept',
+ 'streambuf',
+ 'string',
+ 'string_view',
+ 'strstream',
+ 'system_error',
+ 'thread',
+ 'tuple',
+ 'type_traits',
+ 'typeindex',
+ 'typeinfo',
+ 'unordered_map',
+ 'unordered_set',
+ 'valarray',
+ 'variant',
+ 'vector',
+ 'unordered_map',
+ 'utility']
def __init__(self, style='pub-priv', absolute=False):
"""Initialize a sorted with the given style."""
src/gromacs/nbnxm/kernels_simd_2xmm/kernel_common.h: warning: should include "nbnxm_simd.h"
src/gromacs/nbnxm/kernels_simd_4xm/kernel_common.h: warning: should include "nbnxm_simd.h"
+# This seems to be a false positive
+src/gromacs/nbnxm/cuda/nbnxm_cuda_types.h: error: NbnxmGpu: is in internal file(s), but appears in public documentation
+
# Temporary while we change the SIMD implementation
src/gromacs/simd/impl_sparc64_hpc_ace/impl_sparc64_hpc_ace_common.h: warning: should include "simd.h"
*: warning: includes non-local file as "corewrap.h"
src/gmxpre.h: warning: includes non-local file as "swindirect.h"
-# New external API (see https://redmine.gromacs.org/issues/2586) has some unresolved
+# New external API (see https://gitlab.com/gromacs/gromacs/-/issues/2586) has some unresolved
# conflicts with previous definitions of public API, installed API, and other things
# described or implemented in check-source.py, gmxtree.py, gmxtree.rst, and others
# TODO: resolve definitions, update testing heuristics, and activate policy checks
<dd>Required compiler flags.</dd>
</dl>
+Additionally an imported target named `Gromacs::libgromacs` is provided and can
+be used with `target_link_libraries(foo PRIVATE Gromacs::libgromacs)`.
+
Declared macros/functions that can be used for checking for correctness of some
settings:
Operations, factories, and data flow: declaration, definition, and initialization
=================================================================================
-.. todo:: Reference https://redmine.gromacs.org/issues/2993
+.. todo:: Reference https://gitlab.com/gromacs/gromacs/-/issues/2993
Expressing inputs and outputs
-----------------------------
*gmxapi* comes in three parts:
* GROMACS gmxapi library for C++.
-* This Python package, supporting Python 3.5 and higher
+* This Python package, supporting Python 3.6 and higher
* MD restraint plugins and sample gmxapi client code
GROMACS requirements
Build system requirements
-------------------------
-gmxapi can be built for Python 3.5 and higher.
+gmxapi can be built for Python 3.6 and higher.
You will need a C++ 14 compatible compiler and a reasonably up-to-date version
of CMake.
Python environment requirements
-------------------------------
-gmxapi requires Python 3.5 or higher. Check your version with
+gmxapi requires Python 3.6 or higher. Check your version with
:command:`python3 --version` or :command:`python --version`.
.. note::
Sometimes the build environment can choose a different Python interpreter than
the one you intended.
-You can set the ``PYTHON_EXECUTABLE`` CMake variable to explicitly choose the
-Python interpreter for your chosen installation.
-For example: ``-DPYTHON_EXECUTABLE=\`which python\```
+You can set the ``Python3_ROOT`` or ``CMAKE_PREFIX_PATH`` CMake variable to
+explicitly choose the Python installation or *venv* directory.
+
+If you use pyenv or pyenv-virtualenv to dynamically manage your Python version,
+you can help identify a particular version with ``pyenv version-name`` and the
+directory with ``pyenv prefix {version}``. For example::
+
+ -DPython3_ROOT=$(pyenv prefix $(pyenv version-name))
Docker web server
-----------------
.. todo::
Document sample_restraint package. Reference issue
- `3027 <https://redmine.gromacs.org/issues/3027>`_
+ `3027 <https://gitlab.com/gromacs/gromacs/-/issues/3027>`_
.. _gmxapi install troubleshooting:
:py:class:`gmxapi.commandline_operation` relies on the environment :envvar:`PATH`
to locate executables, including the :command:`gmx` wrapper binary.
- Relates to `#2961 <https://redmine.gromacs.org/issues/2961>`__.
+ Relates to `#2961 <https://gitlab.com/gromacs/gromacs/-/issues/2961>`__.
.. _parallelism:
Refer to the :doc:`pythonreference` for complete and granular documentation.
For more information on writing or using pluggable simulation extension code,
-refer to https://redmine.gromacs.org/issues/3133.
+refer to https://gitlab.com/gromacs/gromacs/-/issues/3133.
(For gmxapi 0.0.7 and GROMACS 2019, see https://github.com/kassonlab/sample_restraint)
.. todo:: :issue:`3133`: Replace these links as resources for pluggable extension code become available.
from the command line or ``import gmxapi; help(gmxapi)`` within Python for
package and module documentation.
-.. todo:: Example scripts. See issue `3014 <https://redmine.gromacs.org/issues/3014>`_
+.. todo:: Example scripts. See issue `3014 <https://gitlab.com/gromacs/gromacs/-/issues/3014>`_
Welcome to the |Gromacs| documentation!
=======================================
-.. TODO : consolidate at least some of the material in the
+.. todo::
+
+ Consolidate at least some of the material in the
Documentation links below into the new user guide, along with all
of http://www.gromacs.org/Documentation/Cut-off_schemes,
http://www.gromacs.org/Documentation/Acceleration_and_parallelization
|Gromacs| can be compiled for many operating systems and
architectures. These include any distribution of Linux, Mac OS X or
Windows, and architectures including x86, AMD64/x86-64, several
-PowerPC including POWER8, ARM v7, ARM v8, and SPARC VIII.
+PowerPC including POWER8, ARM v8, and SPARC VIII.
Compiler
^^^^^^^^
-|Gromacs| can be compiled on any platform with ANSI C99 and C++14
+|Gromacs| can be compiled on any platform with ANSI C99 and C++17
compilers, and their respective standard C/C++ libraries. Good
performance on an OS and architecture requires choosing a good
compiler. We recommend gcc, because it is free, widely available and
frequently provides the best performance.
You should strive to use the most recent version of your
-compiler. Since we require full C++14 support the minimum supported
+compiler. Since we require full C++17 support the minimum supported
compiler versions are
-* GNU (gcc) 5.1
-* Intel (icc) 17.0.1
-* LLVM (clang) 3.6
-* Microsoft (MSVC) 2017
+* GNU (gcc/libstdc++) 7
+* Intel (icc) 19.1
+* LLVM (clang/libc++) 5
+* Microsoft (MSVC) 2017 15.7
Other compilers may work (Cray, Pathscale, older clang) but do
not offer competitive performance. We recommend against PGI because
components beside the compiler itself (e.g. assembler or linker);
these are often shipped by your OS distribution's binutils package.
-C++14 support requires adequate support in both the compiler and the
+C++17 support requires adequate support in both the compiler and the
C++ library. The gcc and MSVC compilers include their own standard
libraries and require no further configuration. If your vendor's
compiler also manages the standard library library via compiler flags,
On Linux, both the Intel and clang compiler use the libstdc++ which
comes with gcc as the default C++ library. For |Gromacs|, we require
-the compiler to support libstc++ version 5.1 or higher. To select a
+the compiler to support libstc++ version 7.1 or higher. To select a
particular libstdc++ library, provide the path to g++ with
``-DGMX_GPLUSPLUS_PATH=/path/to/g++``.
On Windows with the Intel compiler, the MSVC standard library is used,
-and at least MSVC 2017 is required. Load the enviroment variables with
+and at least MSVC 2017 15.7 is required. Load the enviroment variables with
vcvarsall.bat.
To build with clang and llvm's libcxx standard library, use
512-wide AVX, including KNL, add ``--enable-avx512`` also.
FFTW will create a fat library with codelets for all different instruction sets,
and pick the fastest supported one at runtime.
-On ARM architectures with NEON SIMD support and IBM Power8 and later, you
+On ARM architectures with SIMD support and IBM Power8 and later, you
definitely want version 3.3.5 or later,
and to compile it with ``--enable-neon`` and ``--enable-vsx``, respectively, for
SIMD support. If you are using a Cray, there is a special modified
``-DGMX_USE_LMFIT=none``.
* zlib is used by TNG for compressing some kinds of trajectory data
* Building the |Gromacs| documentation is optional, and requires
- ImageMagick, pdflatex, bibtex, doxygen, python 3.5, sphinx
+ ImageMagick, pdflatex, bibtex, doxygen, python 3.6, sphinx
|EXPECTED_SPHINX_VERSION|, and pygments.
* The |Gromacs| utility programs often write data files in formats
suitable for the Grace plotting tool, but it is straightforward to
The GPU acceleration has been tested on AMD64/x86-64 platforms with
Linux, Mac OS X and Windows operating systems, but Linux is the
-best-tested and supported of these. Linux running on POWER 8, ARM v7 and v8
+best-tested and supported of these. Linux running on POWER 8 and ARM v8
CPUs also works well.
Experimental support is available for compiling CUDA code, both for host and
have a look at the `continuous integration server used by GROMACS`_,
which runs Jenkins_.
-We test irregularly on ARM v7, ARM v8, Cray, Fujitsu
-PRIMEHPC, Power8, Power9,
+We test irregularly on ARM v8, Cray, Power8, Power9,
Google Native Client and other environments, and
with other compilers and compiler versions, too.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
File formats
============
-.. TODO in future patch: update for accuracy, organize better, improve formatting
+.. todo:: in future patch: update for accuracy, organize better, improve formatting
Summary of file formats
^^^^^^^^^^^^^^^^^^^^^^^
.. highlight:: bash
-.. TODO this needs to be carefully checked that I didn't mess anything up too bad
+.. todo:: this needs to be carefully checked that I didn't mess anything up too bad
.. ifconfig:: gmx_image_convert == 'possible'
Comments on form and content are welcome, please send them to one of
the mailing lists (see our `webpage`_ or this section on
how to :ref:`contribute <gmx-contribute>`), or open an issue
-on our `redmine`_. Corrections can also be made in the |Gromacs| git
+on our `issue tracker`_. Corrections can also be made in the |Gromacs| git
source repository and uploaded to the |Gromacs| `gerrit`_.
We release an updated version of the manual whenever
Citation information
--------------------
-.. TODO needs link to ref list
+.. todo:: needs link to ref list
|GMX_MANUAL_DOI_STRING|
Usage
^^^^^
-To make use of the QM/MM functionality in |Gromacs|, one needs to:
-
-#. introduce link atoms at the QM/MM boundary, if needed;
-
-#. specify which atoms are to be treated at a QM level;
-
-#. specify the QM level, basis set, type of QM/MM interface and so on.
-
-Adding link atoms
-^^^^^^^^^^^^^^^^^
-
-At the bond that connects the QM and MM subsystems, a link atoms is
-introduced. In |Gromacs| the link atom has special atomtype, called LA.
-This atomtype is treated as a hydrogen atom in the QM calculation, and
-as a virtual site in the force-field calculation. The link atoms, if
-any, are part of the system, but have no interaction with any other
-atom, except that the QM force working on it is distributed over the two
-atoms of the bond. In the topology, the link atom (LA), therefore, is
-defined as a virtual site atom:
-
-::
-
- [ virtual_sites2 ]
- LA QMatom MMatom 1 0.65
-
-See sec. :ref:`vsitetop` for more details on how virtual sites are
-treated. The link atom is replaced at every step of the simulation.
-
-In addition, the bond itself is replaced by a constraint:
-
-::
-
- [ constraints ]
- QMatom MMatom 2 0.153
-
-**Note** that, because in our system the QM/MM bond is a carbon-carbon
-bond (0.153 nm), we use a constraint length of 0.153 nm, and dummy
-position of 0.65. The latter is the ratio between the ideal C-H bond
-length and the ideal C-C bond length. With this ratio, the link atom is
-always 0.1 nm away from the ``QMatom``, consistent with the carbon-hydrogen
-bond length. If the QM and MM subsystems are connected by a different
-kind of bond, a different constraint and a different dummy position,
-appropriate for that bond type, are required.
-
-Specifying the QM atoms
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Atoms that should be treated at a QM level of theory, including the link
-atoms, are added to the index file. In addition, the chemical bonds
-between the atoms in the QM region are to be defined as connect bonds
-(bond type 5) in the topology file:
-
-::
-
- [ bonds ]
- QMatom1 QMatom2 5
- QMatom2 QMatom3 5
-
-Specifying the QM/MM simulation parameters
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In the :ref:`mdp` file, the following parameters control a
-QM/MM simulation.
-
-``QMMM = no``
- | If this is set to ``yes``, a QM/MM simulation is
- requested. Several groups of atoms can be described at different
- QM levels separately. These are specified in the QMMM-grps field
- separated by spaces. The level of *ab initio* theory at which the
- groups are described is specified by ``QMmethod`` and
- ``QMbasis`` Fields. Describing the groups at different
- levels of theory is only possible with the ONIOM QM/MM scheme,
- specified by ``QMMMscheme``.
-
-``QMMM-grps =``
- | groups to be described at the QM level
-
-``QMMMscheme = normal``
- | Options are ``normal`` and ``ONIOM``. This
- selects the QM/MM interface. ``normal`` implies that
- the QM subsystem is electronically embedded in the MM subsystem.
- There can only be one ``QMMM-grps`` that is modeled at
- the ``QMmethod`` and ``QMbasis`` level of
- * ab initio* theory. The rest of the system is described at the MM
- level. The QM and MM subsystems interact as follows: MM point
- charges are included in the QM one-electron Hamiltonian and all
- Lennard-Jones interactions are described at the MM level. If
- ``ONIOM`` is selected, the interaction between the
- subsystem is described using the ONIOM method by Morokuma and
- co-workers. There can be more than one QMMM-grps each modeled at a
- different level of QM theory (QMmethod and QMbasis).
-
-``QMmethod =``
- | Method used to compute the energy and gradients on the QM atoms.
- Available methods are AM1, PM3, RHF, UHF, DFT, B3LYP, MP2, CASSCF,
- MMVB and CPMD. For CASSCF, the number of electrons and orbitals
- included in the active space is specified by
- ``CASelectrons`` and ``CASorbitals``. For
- CPMD, the plane-wave cut-off is specified by the
- ``planewavecutoff`` keyword.
-
-``QMbasis =``
- | Gaussian basis set used to expand the electronic wave-function.
- Only Gaussian basis sets are currently available, i.e. STO-3G,
- 3-21G, 3-21G\*, 3-21+G\*, 6-21G, 6-31G, 6-31G\*, 6-31+G\*, and
- 6-311G. For CPMD, which uses plane wave expansion rather than
- atom-centered basis functions, the ``planewavecutoff``
- keyword controls the plane wave expansion.
-
-``QMcharge =``
- | The total charge in *e* of the ``QMMM-grps``. In case
- there are more than one ``QMMM-grps``, the total
- charge of each ONIOM layer needs to be specified separately.
-
-``QMmult =``
- | The multiplicity of the ``QMMM-grps``. In case there
- are more than one ``QMMM-grps``, the multiplicity of
- each ONIOM layer needs to be specified separately.
-
-``CASorbitals =``
- | The number of orbitals to be included in the active space when
- doing a CASSCF computation.
-
-``CASelectrons =``
- | The number of electrons to be included in the active space when
- doing a CASSCF computation.
-
-``SH = no``
- | If this is set to yes, a QM/MM MD simulation on the excited
- state-potential energy surface and enforce a diabatic hop to the
- ground-state when the system hits the conical intersection
- hyperline in the course the simulation. This option only works in
- combination with the CASSCF method.
-
-Output
-^^^^^^
-
-The energies and gradients computed in the QM calculation are added to
-those computed by |Gromacs|. In the :ref:`edr` file there is a
-section for the total QM energy.
-
-Future developments
-^^^^^^^^^^^^^^^^^^^
-
-Several features are currently under development to increase the
-accuracy of the QM/MM interface. One useful feature is the use of
-delocalized MM charges in the QM computations. The most important
-benefit of using such smeared-out charges is that the Coulombic
-potential has a finite value at interatomic distances. In the point
-charge representation, the partially-charged MM atoms close to the QM
-region tend to “over-polarize” the QM system, which leads to artifacts
-in the calculation.
-
-What is needed as well is a transition state optimizer.
+QMMM is currently not supported in GROMACS.
introduced into the release-2016 branch since it diverged from
release-5-1. These will not appear in the final release notes, because
no formal release is thought to have had the problem. Of course, the
-Redmine issues remain available should further discussion arise.
+tracked `issues`_ remain available should further discussion arise.
Fixed bug in v-rescale thermostat & replica exchange
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Updated many aspects of the documentation
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Imported and updated more material from the wiki. Incorporated
-suggestions arising from many Redmine issues. Updated user guide,
+suggestions arising from many tracked issues. Updated user guide,
developer guide, install guide, and reference manual.
Updated mdrun signal help text
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixes where mdrun could behave incorrectly
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
gmx mdrun -append now requires that a checkpoint is found
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Changes anticipated to |Gromacs| 2020 functionality
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Density-guided simulations
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
grompp now warns if macros in mdp "define" field are unused in topology
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Up to a factor 2.5 speed-up of the non-bonded free-energy kernel
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Added support for Hygon Dhyana CPU architecture
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Group cut-off scheme
.. Note to developers!
Please use """"""" to underline the individual entries for fixed issues in the subfolders,
otherwise the formatting on the webpage is messed up.
- Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
a space between the colon and number!
Fixed bug in gmx order -calcdist
--- /dev/null
+Bugs fixed
+^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
+Fixed exported libgromacs CMake target
+""""""""""""""""""""""""""""""""""""""
+
+Update the exported libgromacs CMake target to not depend on non-
+existing include paths and add GMX_DOUBLE define to interface
+definitions. The target now gets exported into the Gromacs namespace.
+
+:issue:`3468`
+
+Fix checkpoint restart with non-zero initial step
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+When restarting from the checkpoint, the init-step mdp parameter was ignored while
+checking if the simulation is already finished. As a result, this check only worked
+properly when init-step was 0 or was not specified.
+
+:issue:`3489`
--- /dev/null
+.. _anticipated-changes:
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
+Changes anticipated to |Gromacs| 2021 functionality
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Functionality deprecated in |Gromacs| 2021
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
--- /dev/null
+New and improved features
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
--- /dev/null
+Highlights
+^^^^^^^^^^
+
+|Gromacs| 2021 was released on INSERT DATE HERE. Patch releases may
+have been made since then, please use the updated versions! Here are
+some highlights of what you can expect, along with more detail in the
+links below!
+
+As always, we've got several useful performance improvements, with or
+without GPUs, all enabled and automated by default. In addition,
+several new features are available for running simulations. We are extremely
+interested in your feedback on how well the new release works on your
+simulations and hardware. The new features are:
+
+* Cool quote autogenerator
+
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
--- /dev/null
+Miscellaneous
+^^^^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
--- /dev/null
+Performance improvements
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
+Extend supported use-cases for GPU version of update and constraints
+""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+GPU version of update and constraints can now be used for FEP, except mass and constraints
+free-energy perturbation.
--- /dev/null
+Portability
+^^^^^^^^^^^
+
+Python environment
+""""""""""""""""""
+
+Where Python is required,
+`CPython <https://www.python.org>`__ versions 3.6 to 3.8 are supported.
+
+CMake now detects Python using
+`FindPython3 <https://cmake.org/cmake/help/v3.13/module/FindPython3.html>`__.
+If you previously used ``PYTHON_EXECUTABLE`` to hint the location of the Python
+interpreter, you should instead specify the Python "root" or "prefix" path
+(the directory containing ``./bin/python3``) with CMake variable
+``Python3_ROOT`` or ``CMAKE_PREFIX_PATH``. As other infrastructure evolves,
+``PYTHON_EXECUTABLE`` may cease to have the desired effect without warning.
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
+CMake
+"""""
+
+Updated required CMake version to 3.13.
+
+C++ standard
+""""""""""""
+
+GROMACS has updated the required C++ standards compliance from C++14 to C++17,
+and requires 2017 standard library features. See the install guide for details.
--- /dev/null
+Removed functionality
+^^^^^^^^^^^^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
--- /dev/null
+Improvements to |Gromacs| tools
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on GitLab, without the
+ a space between the colon and number!
+
functionality supported, whereas patch releases contain only fixes for
issues identified in the corresponding major releases.
-Two versions of |Gromacs| are under active maintenance, the 2020
-series and the 2019 series. In the latter, only highly conservative
+Two versions of |Gromacs| are under active maintenance, the 2021
+series and the 2020 series. In the latter, only highly conservative
fixes will be made, and only to address issues that affect scientific
correctness. Naturally, some of those releases will be made after the
-year 2019 ends, but we keep 2019 in the name so users understand how
+year 2020 ends, but we keep 2019 in the name so users understand how
up to date their version is. Such fixes will also be incorporated into
-the 2020 release series, as appropriate. Around the time the 2021
-release is made, the 2019 series will no longer be maintained.
+the 2021 release series, as appropriate. Around the time the 2022
+release is made, the 2020 series will no longer be maintained.
Where issue numbers are reported in these release notes, more details
-can be found at https://redmine.gromacs.org at that issue number.
+can be found at https://gitlab.com/gromacs/gromacs/-/issues at that issue number.
+
+|Gromacs| 2021 series
+---------------------
+
+.. todolist::
+
+Major release
+^^^^^^^^^^^^^
+
+.. toctree::
+ :maxdepth: 1
+
+ 2021/major/highlights
+ 2021/major/features
+ 2021/major/performance
+ 2021/major/tools
+ 2021/major/bugs-fixed
+ 2021/major/deprecated-functionality
+ 2021/major/removed-functionality
+ 2021/major/portability
+ 2021/major/miscellaneous
+
|Gromacs| 2020 series
---------------------
only fixes for issues identified in the corresponding major releases.
Where issue numbers are reported in these release notes, more details
-can be found at https://redmine.gromacs.org at that issue number.
+can be found at https://gitlab.com/gromacs/gromacs/-/issues at that issue number.
|Gromacs| 5.1 series
-----------------------------------
.. Another useful one-liner to find undocumentedvariables:
.. ( export INPUT_FILE=docs/user-guide/environment-variables.rst; GIT_PAGER="cat "; for ss in `for s in $(git grep getenv | sed 's/.*getenv("\(.*\)".*/\1/' | sort -u | grep '^[A-Z]'); do [ $(grep $s $INPUT_FILE -c) -eq 0 ] && echo $s; done `; do git grep $ss ; done )
-.. TODO: still undocumented GMX_QM_GAUSSIAN_NCPUS
-
Environment Variables
=====================
Analysis and Core Functions
---------------------------
-``GMX_QM_ACCURACY``
- accuracy in Gaussian L510 (MC-SCF) component program.
-
-``GMX_QM_ORCA_BASENAME``
- prefix of :ref:`tpr` files, used in Orca calculations
- for input and output file names.
-
-``GMX_QM_CPMCSCF``
- when set to a nonzero value, Gaussian QM calculations will
- iteratively solve the CP-MCSCF equations.
-
-``GMX_QM_MODIFIED_LINKS_DIR``
- location of modified links in Gaussian.
``DSSP``
used by :ref:`gmx do_dssp` to point to the ``dssp``
executable (not just its path).
-``GMX_QM_GAUSS_DIR``
- directory where Gaussian is installed.
-
-``GMX_QM_GAUSS_EXE``
- name of the Gaussian executable.
-
``GMX_DIPOLE_SPACING``
spacing used by :ref:`gmx dipoles`.
the time unit used in output files, can be
anything in fs, ps, ns, us, ms, s, m or h.
-``GMX_QM_GAUSSIAN_MEMORY``
- memory used for Gaussian QM calculation.
-
``MULTIPROT``
name of the ``multiprot`` executable, used by the
contributed program ``do_multiprot``.
``NCPUS``
number of CPUs to be used for Gaussian QM calculation
-``GMX_ORCA_PATH``
- directory where Orca is installed.
-
-``GMX_QM_SA_STEP``
- simulated annealing step size for Gaussian QM calculation.
-
-``GMX_QM_GROUND_STATE``
- defines state for Gaussian surface hopping calculation.
-
``GMX_TOTAL``
name of the ``total`` executable used by the contributed
``do_shift`` program.
You can choose different values for :mdp:`tinit` and :mdp:`init-step`.
- .. TODO make links work :ref:`Continuing simulations <gmx-cont-simulation>`.
+ .. todo:: Add "Continuing simulations" content (label: gmx-cont-simulation) and link.
+
+ e.g. ``:ref:`Continuing simulations <gmx-cont-simulation>`.``
#. Why can't I do conjugate gradient minimization with constraints?
You can either prepare a new :ref:`mdp` file, or extend the simulation time
in the original :ref:`tpr` file using :ref:`convert-tpr <gmx convert-tpr>`.
- .. TODO #. How do I complete a crashed simulation?
+ .. todo:: #. How do I complete a crashed simulation?
+
+ Need gmx-cont-crash doc target.
+
+ .. code-block:: none
+
+ This can be easily achieved using the checkpoint reading
+ :ref:`available <gmx-cont-crash>` in |Gromacs| versions newer than 4.
- .. This can be easily achieved using the checkpoint reading
- :ref:`available <gmx-cont-crash>` in |Gromacs| versions newer than 4.
+ .. todo:: #. How can I do a simulation at constant pH?
- .. TODO #. How can I do a simulation at constant pH?
+ Need gmx-howto-cph doc target.
- .. This is a rather large topic, and you should at least read the short
- :ref:`Constant pH How-To <gmx-howto-cph>` and all of the literature
- included there to get an overview over the topic.
+ .. code-block:: none
+
+ This is a rather large topic, and you should at least read the short
+ :ref:`Constant pH How-To <gmx-howto-cph>` and all of the literature
+ included there to get an overview over the topic.
#. How should I compute a single-point energy?
Analysis and Visualization
--------------------------
- .. TODO #. How do I visualize a trajectory?
+.. todo:: #. How do I visualize a trajectory?
+
+ gmx-howto-visualize doc target:
+
+ .. code-block:: none
- .. Use one of the number of different programs that can visualize
+ Use one of the number of different programs that can visualize
coordinate :ref:`files and trajectories <gmx-howto-visualize>`.
#. Why am I seeing bonds being created when I watch the trajectory?
* GROMOS 43a1p - 43a1 modified to contain SEP (phosphoserine), TPO (phosphothreonine),
and PTR (phosphotyrosine) (all PO42- forms), and SEPH, TPOH, PTRH (PO4H- forms).
-.. TODO Add new force fields to the list
+.. todo:: Add new force fields to the list
.. _GROMOS: http://www.igc.ethz.ch/gromos/
.. _reference manual: gmx-manual-parent-dir_
|GMX_SOURCE_DOI_STRING|
-.. TODO This is going to require more organization now that
+.. todo::
+
+ This is going to require more organization now that
we are getting more content available.
.. toctree::
See the "run control" section for a working example of the
syntax to use when making .mdp entries, with and without detailed
documentation for values those entries might take. Everything can
- be cross-referenced, see the examples there. TODO Make more
- cross-references.
+ be cross-referenced, see the examples there.
+
+.. todo:: Make more cross-references.
Molecular dynamics parameters (.mdp options)
============================================
The file name can be changed with the ``-awh`` option.
The first :mdp:`awh1-ndim` columns of
each input file should contain the coordinate values, such that each row defines a point in
- coordinate space. Column :mdp:`awh1-ndim` + 1 should contain the PMF value for each point.
+ coordinate space. Column :mdp:`awh1-ndim` + 1 should contain the PMF value (in kT) for each point.
The target distribution column can either follow the PMF (column :mdp:`awh1-ndim` + 2) or
be in the same column as written by :ref:`gmx awh`.
(6)
power 6 for the radial term in the soft-core equation.
- (48)
- (deprecated) power 48 for the radial term in the soft-core equation.
- Note that sc-alpha should generally be much lower (between 0.001 and 0.003).
-
.. mdp:: sc-coul
(no)
Mixed quantum/classical molecular dynamics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. MDP:: QMMM
-
- .. mdp-value:: no
-
- No QM/MM.
-
- .. mdp-value:: yes
-
- Do a QM/MM simulation. Several groups can be described at
- different QM levels separately. These are specified in the
- :mdp:`QMMM-grps` field separated by spaces. The level of *ab
- initio* theory at which the groups are described is specified by
- :mdp:`QMmethod` and :mdp:`QMbasis` Fields. Describing the
- groups at different levels of theory is only possible with the
- ONIOM QM/MM scheme, specified by :mdp:`QMMMscheme`.
-
.. mdp:: QMMM-grps
- groups to be descibed at the QM level (works also in case of MiMiC QM/MM)
-
-.. mdp:: QMMMscheme
-
- .. mdp-value:: normal
-
- normal QM/MM. There can only be one :mdp:`QMMM-grps` that is
- modelled at the :mdp:`QMmethod` and :mdp:`QMbasis` level of
- *ab initio* theory. The rest of the system is described at the
- MM level. The QM and MM subsystems interact as follows: MM point
- charges are included in the QM one-electron hamiltonian and all
- Lennard-Jones interactions are described at the MM level.
-
- .. mdp-value:: ONIOM
-
- The interaction between the subsystem is described using the
- ONIOM method by Morokuma and co-workers. There can be more than
- one :mdp:`QMMM-grps` each modeled at a different level of QM
- theory (:mdp:`QMmethod` and :mdp:`QMbasis`).
-
-.. mdp:: QMmethod
-
- (RHF)
- Method used to compute the energy and gradients on the QM
- atoms. Available methods are AM1, PM3, RHF, UHF, DFT, B3LYP, MP2,
- CASSCF, and MMVB. For CASSCF, the number of electrons and orbitals
- included in the active space is specified by :mdp:`CASelectrons`
- and :mdp:`CASorbitals`.
+ groups to be descibed at the QM level for MiMiC QM/MM
-.. mdp:: QMbasis
-
- (STO-3G)
- Basis set used to expand the electronic wavefuntion. Only Gaussian
- basis sets are currently available, *i.e.* ``STO-3G, 3-21G, 3-21G*,
- 3-21+G*, 6-21G, 6-31G, 6-31G*, 6-31+G*,`` and ``6-311G``.
-
-.. mdp:: QMcharge
-
- (0) [integer]
- The total charge in ``e`` of the :mdp:`QMMM-grps`. In case there are
- more than one :mdp:`QMMM-grps`, the total charge of each ONIOM
- layer needs to be specified separately.
-
-.. mdp:: QMmult
-
- (1) [integer]
- The multiplicity of the :mdp:`QMMM-grps`. In case there are more
- than one :mdp:`QMMM-grps`, the multiplicity of each ONIOM layer
- needs to be specified separately.
-
-.. mdp:: CASorbitals
-
- (0) [integer]
- The number of orbitals to be included in the active space when
- doing a CASSCF computation.
-
-.. mdp:: CASelectrons
-
- (0) [integer]
- The number of electrons to be included in the active space when
- doing a CASSCF computation.
-
-.. MDP:: SH
+.. MDP:: QMMM
.. mdp-value:: no
- No surface hopping. The system is always in the electronic
- ground-state.
-
- .. mdp-value:: yes
-
- Do a QM/MM MD simulation on the excited state-potential energy
- surface and enforce a *diabatic* hop to the ground-state when
- the system hits the conical intersection hyperline in the course
- the simulation. This option only works in combination with the
- CASSCF method.
-
+ QM/MM is no longer supported via these .mdp options. For MiMic, use no here.
Computational Electrophysiology
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Setting "gpu" requires that a compatible CUDA GPU is available,
the simulation uses a single rank.
Update and constraints on a GPU is currently not supported
- with domain decomposition, free-energy, virtual sites,
- Ewald surface correction, replica exchange, constraint pulling,
- orientation restraints and computational electrophysiology.
+ with mass and constraints free-energy perturbation, domain
+ decomposition, virtual sites, Ewald surface correction,
+ replica exchange, constraint pulling, orientation restraints
+ and computational electrophysiology.
``-gpu_id``
A string that specifies the ID numbers of the GPUs that
Subcounters are geared toward developers and have to be enabled during compilation. See
:doc:`/dev-manual/build-system` for more information.
-.. TODO In future patch:
- - red flags in log files, how to interpret wallcycle output
- - hints to devs how to extend wallcycles
+.. todo::
+
+ In future patch:
+ - red flags in log files, how to interpret wallcycle output
+ - hints to devs how to extend wallcycles
.. _gmx-mdrun-on-gpu:
GPU computation of short range nonbonded interactions
.....................................................
-.. TODO make this more elaborate and include figures
+.. todo:: make this more elaborate and include figures
Using the GPU for the short-ranged nonbonded interactions provides
the majority of the available speed-up compared to run using only the CPU.
GPU accelerated calculation of PME
..................................
-.. TODO again, extend this and add some actual useful information concerning performance etc...
+.. todo:: again, extend this and add some actual useful information concerning performance etc...
|Gromacs| now allows the offloading of the PME calculation
to the GPU, to further reduce the load on the CPU and improve usage overlap between
GPU accelerated calculation of bonded interactions (CUDA only)
..............................................................
-.. TODO again, extend this and add some actual useful information concerning performance etc...
+.. todo:: again, extend this and add some actual useful information concerning performance etc...
|Gromacs| now allows the offloading of the bonded part of the PP
workload to a CUDA-compatible GPU. This is treated as part of the PP
#) The only way to know for sure what alternative is best for
your machine is to test and check performance.
-.. TODO: we need to be more concrete here, i.e. what machine/software aspects to take into consideration, when will default run mode be using PME-GPU and when will it not, when/how should the user reason about testing different settings than the default.
+.. todo:: we need to be more concrete here, i.e. what machine/software aspects to take into consideration, when will default run mode be using PME-GPU and when will it not, when/how should the user reason about testing different settings than the default.
-.. TODO someone who knows about the mixed mode should comment further.
+.. todo:: someone who knows about the mixed mode should comment further.
Reducing overheads in GPU accelerated runs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
involves a tradeoff which may outweigh the benefits of reduced GPU driver overhead,
in particular without HyperThreading and with few CPU cores.
-.. TODO In future patch: any tips not covered above
+.. todo:: In future patch: any tips not covered above
Running the OpenCL version of mdrun
-----------------------------------
provide the OpenCL support.
For Intel integrated GPUs, the `Neo driver <https://github.com/intel/compute-runtime/releases>`_ is
recommended.
-TODO: add more Intel driver recommendations
+.. seealso:: :issue:`3268` add more Intel driver recommendations
+
The minimum OpenCL version required is |REQUIRED_OPENCL_MIN_VERSION|. See
also the :ref:`known limitations <opencl-known-limitations>`.
* search the primary literature for publications for parameters for the
residue that are consistent with the force field that is being used.
-.. TODO Once you have determined the parameters and topology for your residue, see
- :ref:`adding a residue to a force field <gmx-add-new-residue>` for instructions on how to proceed.
+.. todo:: gmx-add-new-residue doc target
+
+ Need gmx-add-new-residue doc target.
+
+ .. code-block:: none
+
+ Once you have determined the parameters and topology for your residue, see
+ :ref:`adding a residue to a force field <gmx-add-new-residue>` for instructions on how to proceed.
Long bonds and/or missing atoms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# (system or user) GROMACS installation and (user) Python environment. For a
# system-wide Python environment, the package needs to be built and installed
# (to the ``site-packages`` directory) for each supported Python interpreter.
-# ``setup.py`` can just be invoked with different Python interpreters. We can
-# add CMake infrastructure to allow multiple/repeated PYTHON_EXECUTABLE
-# specification at the GROMACS project level if such a use case is important to
-# HPC site administrators or Linux distribution packagers.
+# ``setup.py`` can just be invoked with different Python interpreters.
#
# To drive the packaging of a Python package distribution archive
# by a higher-level CMake configuration, a CMakeLists.txt file at this level would
# Python package sources
This directory exists as a staging area supporting GROMACS enhancement
-[#2045](https://redmine.gromacs.org/issues/2045),
+[#2045](https://gitlab.com/gromacs/gromacs/-/issues/2045),
which attempts to update the gmxapi efforts from GROMACS 2019,
merge external repositories from
https://github.com/kassonlab/gmxapi
pytest test
For additional discussion on packaging and distribution, see
-https://redmine.gromacs.org/issues/2896
+https://gitlab.com/gromacs/gromacs/-/issues/2896
## Sample MD extension code
Hint: the fork point from `master` and the current git ref can be set as environment variables:
- FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base gerrit_master HEAD`)
+ FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base master HEAD`)
REF=`git show -s --pretty=format:"%h"`
## External project code
`pip install -r requirements.txt`, as above.
Note: scikit-build is only required for convenient management of the Python
-build environment and packaging. See https://redmine.gromacs.org/issues/2896
+build environment and packaging. See https://gitlab.com/gromacs/gromacs/-/issues/2896
# pybind11
Assume you have already checked out the commit you want to build for.
Assume the following definitions.
- git fetch https://github.com/gromacs/gromacs.git master
- git branch gerrit_master FETCH_HEAD
- FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base gerrit_master HEAD`)
+ FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base master HEAD`)
TAG="fr1" # for functional requirement 1
## Building
# Build from the GROMACS image at the current fork point. Tag with the feature
# name or the current revision.
#
-# FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base gerrit_master HEAD`)
+# FORKPOINT=$(git show -s --pretty=format:"%h" `git merge-base master HEAD`)
# REF=`git show -s --pretty=format:"%h"`
# # or
# REF="fr1"
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+# Copyright (c) 2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# Python package requirements for complete build, installation, and testing of
# gmxapi functionality.
-cmake>=3.9.6
+cmake>=3.13
+flake8>=3.7.7
networkx>=2.0
-pip>=10.1
-setuptools>=28.0.0
-scikit-build>=0.7
-# The following packages are not strictly necessary, but allow full documentation
-# builds and testing.
-mpi4py>=2
numpy>=1
+pip>=10.1
+scikit-build>=0.10
+setuptools>=42
+wheel
+# The following packages are not strictly necessary, but allow full testing.
+mpi4py>=3.0.3
pytest>=3.9
include(ExternalProject)
ExternalProject_Add(pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
- GIT_TAG v2.2
+ GIT_TAG v2.5
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/pybind-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/pybind-build"
CONFIGURE_COMMAND ""
-cmake_minimum_required(VERSION 3.9.6)
+cmake_minimum_required(VERSION 3.13.0)
# If you are using this repository as a template, you should probably change the
# project name and adopt your own versioning scheme.
project(sample_restraint VERSION 0.0.8)
# the paackage that should be installed with GROMACS, but the pybind sources
# would only be available to this project with some additional management by
# the parent project CMake configuration.
-# Also reference https://redmine.gromacs.org/issues/2896
+# Also reference https://gitlab.com/gromacs/gromacs/-/issues/2896
if(GMXAPI_EXTENSION_MASTER_PROJECT)
# TODO: (Issue #3027) Handle locally available sources.
set(GMXAPI_EXTENSION_USE_BUNDLED_PYBIND OFF CACHE BOOL
# versions of GROMACS. If building from the command line, you can specify a Python executable with the PYTHON_EXECUTABLE
# variable. For instance, to make sure you are building for your default Python, cmake -DPYTHON_EXECUTABLE=`which python`.
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# CMake modules are in a subdirectory to keep this file cleaner
the Pybind project (ref <https://github.com/pybind/pybind11> ). It
is used to wrap the C++ restraint code and give it a Python
interface.</strike> Note: pybind is currently retrieved while configuring
- with CMake. Ref redmine issues [3027](https://redmine.gromacs.org/issues/3027)
- and [3033](https://redmine.gromacs.org/issues/3033)
+ with CMake. Ref issues [3027](https://gitlab.com/gromacs/gromacs/-/issues/3027)
+ and [3033](https://gitlab.com/gromacs/gromacs/-/issues/3033)
- `tests/` contains C++ and Python tests for the provided code. Update
`CMakeLists.txt` to add your own, based on these examples. C++ unit
tests use [googletest](https://github.com/google/googletest). Python
tests use the [pytest](https://docs.pytest.org/en/latest/). Refer to
those respective projects for more about how they make test-writing
easier. Note: googletest is currently downloaded while configuring with
- CMake. Ref [3033](https://redmine.gromacs.org/issues/3033)
+ CMake. Ref [3033](https://gitlab.com/gromacs/gromacs/-/issues/3033)
- `examples` contains a sample SLURM job script and
`restrained-ensemble.py` gmxapi script that have been used to do
restrained ensemble simulations. `example.py` and `example.ipynb`
# We also build a test file in the spc_water_box pytest test fixture, but we can
# presumably extract both of those from the GROMACS installation, or at least
# through the gmxapi Python package resources.
- # Ref: https://redmine.gromacs.org/issues/2961
+ # Ref: https://gitlab.com/gromacs/gromacs/-/issues/2961
file(DOWNLOAD
https://github.com/kassonlab/sample_restraint/raw/master/tests/data/topol.tpr
${CMAKE_CURRENT_BINARY_DIR}/topol.tpr
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import json
import logging
import os
-import shutil
-import tempfile
-import warnings
-from contextlib import contextmanager
import pytest
-
-def pytest_addoption(parser):
- """Add a command-line user option for the pytest invocation."""
- parser.addoption(
- '--rm',
- action='store',
- default='always',
- choices=['always', 'never', 'success'],
- help='Remove temporary directories "always", "never", or on "success".'
- )
-
-
-@pytest.fixture(scope='session')
-def remove_tempdir(request):
- """pytest fixture to get access to the --rm CLI option."""
- return request.config.getoption('--rm')
-
-
-@contextmanager
-def scoped_chdir(dir):
- oldpath = os.getcwd()
- os.chdir(dir)
- try:
- yield dir
- # If the `with` block using scoped_chdir produces an exception, it will
- # be raised at this point in this function. We want the exception to
- # propagate out of the `with` block, but first we want to restore the
- # original working directory, so we skip `except` but provide a `finally`.
- finally:
- os.chdir(oldpath)
-
-
-@contextmanager
-def _cleandir(remove_tempdir):
- """Context manager for a clean temporary working directory.
-
- Arguments:
- remove_tempdir (str): whether to remove temporary directory "always",
- "never", or on "success"
-
- The context manager will issue a warning for each temporary directory that
- is not removed.
- """
-
- newpath = tempfile.mkdtemp()
-
- def remove():
- shutil.rmtree(newpath)
-
- def warn():
- warnings.warn('Temporary directory not removed: {}'.format(newpath))
-
- if remove_tempdir == 'always':
- callback = remove
- else:
- callback = warn
- try:
- with scoped_chdir(newpath):
- yield newpath
- # If we get to this line, the `with` block using _cleandir did not throw.
- # Clean up the temporary directory unless the user specified `--rm never`.
- # I.e. If the user specified `--rm success`, then we need to toggle from `warn` to `remove`.
- if remove_tempdir != 'never':
- callback = remove
- finally:
- callback()
-
-
-@pytest.fixture
-def cleandir(remove_tempdir):
- """Provide a clean temporary working directory for a test.
-
- Example usage:
-
- import os
- import pytest
-
- @pytest.mark.usefixtures("cleandir")
- def test_cwd_starts_empty():
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(cleandir):
- assert os.listdir(os.getcwd()) == []
- assert os.path.abspath(os.getcwd()) == os.path.abspath(cleandir)
- with open("myfile", "w") as f:
- f.write("hello")
-
- @pytest.mark.usefixtures("cleandir")
- class TestDirectoryInit(object):
- def test_cwd_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- Ref: https://docs.pytest.org/en/latest/fixture.html#using-fixtures-from-classes-modules-or-projects
- """
- with _cleandir(remove_tempdir) as newdir:
- yield newdir
-
-
-@pytest.fixture(scope='session')
-def gmxcli():
- # TODO: (#2896) Find a more canonical way to identify the GROMACS commandline wrapper binary.
- # We should be able to get the GMXRC contents and related hints from a gmxapi
- # package resource or from module attributes of a ``gromacs`` stub package.
- allowed_command_names = ['gmx', 'gmx_mpi']
- command = None
- for command_name in allowed_command_names:
- if command is not None:
- break
- command = shutil.which(command_name)
- if command is None:
- gmxbindir = os.getenv('GMXBIN')
- if gmxbindir is None:
- gromacsdir = os.getenv('GROMACS_DIR')
- if gromacsdir is not None and gromacsdir != '':
- gmxbindir = os.path.join(gromacsdir, 'bin')
- if gmxbindir is None:
- gmxapidir = os.getenv('gmxapi_DIR')
- if gmxapidir is not None and gmxapidir != '':
- gmxbindir = os.path.join(gmxapidir, 'bin')
- if gmxbindir is not None:
- gmxbindir = os.path.abspath(gmxbindir)
- command = shutil.which(command_name, path=gmxbindir)
- if command is None:
- message = "Tests need 'gmx' command line tool, but could not find it on the path."
- raise RuntimeError(message)
- try:
- assert os.access(command, os.X_OK)
- except Exception as E:
- raise RuntimeError('"{}" is not an executable gmx wrapper program'.format(command)) from E
- yield command
+pytest_plugins = ('gmxapi.testsupport',)
@pytest.fixture(scope='class')
Prepare the MD input in a freshly created working directory.
"""
import gmxapi as gmx
+ # TODO: Remove this import when the the spc_water_box fixture is migrated to gmxapi.testsupport
+ from gmxapi.testsupport import _cleandir
# TODO: (#2896) Fetch MD input from package / library data.
# Example:
from gmxapi.simulation.workflow import WorkElement, from_tpr
from gmxapi import version as gmx_version
import pytest
-from gmxapi.testsupport import withmpi_only
logging.getLogger().setLevel(logging.DEBUG)
# create console handler
session.run()
-@withmpi_only
+@pytest.mark.withmpi_only
@pytest.mark.usefixtures("cleandir")
def test_ensemble_potential_withmpi(spc_water_box):
tpr_filename = spc_water_box
--- /dev/null
+#!/bin/bash -x
+
+# Note: E501 specifies a line length limit of 80 characters, but GROMACS allows more.
+# Ref: http://manual.gromacs.org/current/dev-manual/formatting.html
+# Note: --max-complexity can be used to check McCabe complexity. Compliance
+# could be a future goal, but is not yet a GROMACS priority.
+# W503 is ignored in observation of current PEP-8 conventions, but must be
+# explicitly disabled in at least some versions.
+# http://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
+# https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator
+
+# Check gmxapi package sources.
+python -m flake8 --ignore W503 --max-line-length 119 ${HOME}/gmxapi/src/gmxapi
+
+# Check gmxapi unit tests.
+python -m flake8 --ignore W503 --max-line-length 119 ${HOME}/gmxapi/src/test
+
+# Check gmxapi acceptance tests.
+python -m flake8 --ignore W503 --max-line-length 119 ${HOME}/gmxapi/test
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# simplest use case is to allow the `setup.py` file to invoke skbuild to
# configure and run CMake. CMake could be invoked directly by the user or a
# parent package, but the Python distribution would not be packaged automatically.
-# Reference https://redmine.gromacs.org/issues/2896 for additional discussion.
-cmake_minimum_required(VERSION 3.9.6)
+# Reference https://gitlab.com/gromacs/gromacs/-/issues/2896 for additional discussion.
+cmake_minimum_required(VERSION 3.13.0)
# This needs to be set before project() in order to pick up toolchain files
#list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake)
-# OS X deployment target should be >=10.9 for modern C++ compatibility.
+# OS X deployment target should be >=10.14 for modern C++ compatibility.
# Reference https://scikit-build.readthedocs.io/en/latest/generators.html#macosx
# and https://github.com/MacPython/wiki/wiki/Spinning-wheels
-set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9 CACHE STRING
- "OS X deployment target below 10.9 does not use modern standard library"
+set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14 CACHE STRING
+ "OS X deployment target below 10.14 does not use modern standard library"
FORCE)
set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING
"OS X should build Python package for 64-bit architecture"
set(GMXAPI_MASTER_PROJECT ON)
endif()
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Only interpret if() arguments as variables or keywords when unquoted.
if(GMXAPI_USE_BUNDLED_PYBIND)
add_subdirectory(external/pybind)
else()
- # Reference https://redmine.gromacs.org/issues/2896
+ # Reference https://gitlab.com/gromacs/gromacs/-/issues/2896
find_package(pybind11 2.2 REQUIRED)
endif()
target_link_libraries(_gmxapi PRIVATE Gromacs::gmxapi)
# TODO: Determine packaging and installation cases and implementation.
- # Reference https://redmine.gromacs.org/issues/2896 for additional discussion.
+ # Reference https://gitlab.com/gromacs/gromacs/-/issues/2896 for additional discussion.
# Currently, CMake should be run by scikit-build through setup.py for proper Python packaging.
# We don't want to install by default in the outer scope of the GROMACS
# CMake procedure because we could end up trying to install to a system directory
# source distribution archive to be installed in the GROMACS installation
# destination. We can use the build directory as the working directory for
# easier clean-up, as well.
- # TODO: (ref issue #2896) Build and install 'sdist' with GROMACS.
+ # TODO: (ref Issue #2896) Build and install 'sdist' with GROMACS.
# However, we can still produce an importable package for documentation builds and
# basic testing in ${CMAKE_CURRENT_BINARY_DIR}/gmxapi_staging
## pybind11
For simplicity, the pybind headers were retrieved from
-https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz
+https://github.com/pybind/pybind11/archive/v2.5.0.tar.gz
git rm -rf pybind
mkdir -p pybind
- wget https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz
+ wget https://github.com/pybind/pybind11/archive/v2.5.0.tar.gz
tar xvf *.tar.gz
mv pybind11*/include pybind/
mv pybind11*/tools pybind/
std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format()
ssize_t ndim = 0; // Number of dimensions
std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension)
- std::vector<ssize_t> strides; // Number of entries between adjacent entries (for each per dimension)
+ std::vector<ssize_t> strides; // Number of bytes between adjacent entries (for each per dimension)
+ bool readonly = false; // flag to indicate if the underlying storage may be written to
buffer_info() { }
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
- detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in)
+ detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
- shape(std::move(shape_in)), strides(std::move(strides_in)) {
+ shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
for (size_t i = 0; i < (size_t) ndim; ++i)
}
template <typename T>
- buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in)
- : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in)) { }
+ buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
+ : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in), readonly) { }
- buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size)
- : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { }
+ buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, bool readonly=false)
+ : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) { }
template <typename T>
- buffer_info(T *ptr, ssize_t size)
- : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size) { }
+ buffer_info(T *ptr, ssize_t size, bool readonly=false)
+ : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) { }
+
+ template <typename T>
+ buffer_info(const T *ptr, ssize_t size, bool readonly=true)
+ : buffer_info(const_cast<T*>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) { }
explicit buffer_info(Py_buffer *view, bool ownview = true)
: buffer_info(view->buf, view->itemsize, view->format, view->ndim,
- {view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}) {
+ {view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}, view->readonly) {
this->view = view;
this->ownview = ownview;
}
strides = std::move(rhs.strides);
std::swap(view, rhs.view);
std::swap(ownview, rhs.ownview);
+ readonly = rhs.readonly;
return *this;
}
struct private_ctr_tag { };
buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
- detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in)
- : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in)) { }
+ detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in, bool readonly)
+ : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) { }
Py_buffer *view = nullptr;
bool ownview = false;
#include <string_view>
#endif
+#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
+# define PYBIND11_HAS_U8STRING
+#endif
+
NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail)
case return_value_policy::copy:
if (copy_constructor)
valueptr = copy_constructor(src);
- else
- throw cast_error("return_value_policy = copy, but the "
- "object is non-copyable!");
+ else {
+#if defined(NDEBUG)
+ throw cast_error("return_value_policy = copy, but type is "
+ "non-copyable! (compile in debug mode for details)");
+#else
+ std::string type_name(tinfo->cpptype->name());
+ detail::clean_type_id(type_name);
+ throw cast_error("return_value_policy = copy, but type " +
+ type_name + " is non-copyable!");
+#endif
+ }
wrapper->owned = true;
break;
valueptr = move_constructor(src);
else if (copy_constructor)
valueptr = copy_constructor(src);
- else
- throw cast_error("return_value_policy = move, but the "
- "object is neither movable nor copyable!");
+ else {
+#if defined(NDEBUG)
+ throw cast_error("return_value_policy = move, but type is neither "
+ "movable nor copyable! "
+ "(compile in debug mode for details)");
+#else
+ std::string type_name(tinfo->cpptype->name());
+ detail::clean_type_id(type_name);
+ throw cast_error("return_value_policy = move, but type " +
+ type_name + " is neither movable nor copyable!");
+#endif
+ }
wrapper->owned = true;
break;
if (type->operator_new) {
vptr = type->operator_new(type->type_size);
} else {
- #if defined(PYBIND11_CPP17)
+ #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
vptr = ::operator new(type->type_size,
- (std::align_val_t) type->type_align);
+ std::align_val_t(type->type_align));
else
#endif
vptr = ::operator new(type->type_size);
negation<std::is_same<Container, typename Container::value_type>>
>::value>> : is_copy_constructible<typename Container::value_type> {};
-#if !defined(PYBIND11_CPP17)
-// Likewise for std::pair before C++17 (which mandates that the copy constructor not exist when the
-// two types aren't themselves copy constructible).
+// Likewise for std::pair
+// (after C++17 it is mandatory that the copy constructor not exist when the two types aren't themselves
+// copy constructible, but this can not be relied upon when T1 or T2 are themselves containers).
template <typename T1, typename T2> struct is_copy_constructible<std::pair<T1, T2>>
: all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
-#endif
+
+// The same problems arise with std::is_copy_assignable, so we use the same workaround.
+template <typename T, typename SFINAE = void> struct is_copy_assignable : std::is_copy_assignable<T> {};
+template <typename Container> struct is_copy_assignable<Container, enable_if_t<all_of<
+ std::is_copy_assignable<Container>,
+ std::is_same<typename Container::value_type &, typename Container::reference>
+ >::value>> : is_copy_assignable<typename Container::value_type> {};
+template <typename T1, typename T2> struct is_copy_assignable<std::pair<T1, T2>>
+ : all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
NAMESPACE_END(detail)
template <typename CharT> using is_std_char_type = any_of<
std::is_same<CharT, char>, /* std::string */
+#if defined(PYBIND11_HAS_U8STRING)
+ std::is_same<CharT, char8_t>, /* std::u8string */
+#endif
std::is_same<CharT, char16_t>, /* std::u16string */
std::is_same<CharT, char32_t>, /* std::u32string */
std::is_same<CharT, wchar_t> /* std::wstring */
if (res == 0 || res == 1) {
value = (bool) res;
return true;
+ } else {
+ PyErr_Clear();
}
}
return false;
// Simplify life by being able to assume standard char sizes (the standard only guarantees
// minimums, but Python requires exact sizes)
static_assert(!std::is_same<CharT, char>::value || sizeof(CharT) == 1, "Unsupported char size != 1");
+#if defined(PYBIND11_HAS_U8STRING)
+ static_assert(!std::is_same<CharT, char8_t>::value || sizeof(CharT) == 1, "Unsupported char8_t size != 1");
+#endif
static_assert(!std::is_same<CharT, char16_t>::value || sizeof(CharT) == 2, "Unsupported char16_t size != 2");
static_assert(!std::is_same<CharT, char32_t>::value || sizeof(CharT) == 4, "Unsupported char32_t size != 4");
// wchar_t can be either 16 bits (Windows) or 32 (everywhere else)
#if PY_MAJOR_VERSION >= 3
return load_bytes(load_src);
#else
- if (sizeof(CharT) == 1) {
+ if (std::is_same<CharT, char>::value) {
return load_bytes(load_src);
}
// without any encoding/decoding attempt). For other C++ char sizes this is a no-op.
// which supports loading a unicode from a str, doesn't take this path.
template <typename C = CharT>
- bool load_bytes(enable_if_t<sizeof(C) == 1, handle> src) {
+ bool load_bytes(enable_if_t<std::is_same<C, char>::value, handle> src) {
if (PYBIND11_BYTES_CHECK(src.ptr())) {
// We were passed a Python 3 raw bytes; accept it into a std::string or char*
// without any encoding attempt.
}
template <typename C = CharT>
- bool load_bytes(enable_if_t<sizeof(C) != 1, handle>) { return false; }
+ bool load_bytes(enable_if_t<!std::is_same<C, char>::value, handle>) { return false; }
};
template <typename CharT, class Traits, class Allocator>
template <size_t... Is>
bool load_impl(const sequence &seq, bool convert, index_sequence<Is...>) {
+#ifdef __cpp_fold_expressions
+ if ((... || !std::get<Is>(subcasters).load(seq[Is], convert)))
+ return false;
+#else
for (bool r : {std::get<Is>(subcasters).load(seq[Is], convert)...})
if (!r)
return false;
+#endif
return true;
}
template <size_t... Is>
bool load_impl_sequence(function_call &call, index_sequence<Is...>) {
+#ifdef __cpp_fold_expressions
+ if ((... || !std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])))
+ return false;
+#else
for (bool r : {std::get<Is>(argcasters).load(call.args[Is], call.args_convert[Is])...})
if (!r)
return false;
+#endif
return true;
}
template <typename Return, typename Func, size_t... Is, typename Guard>
- Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) {
+ Return call_impl(Func &&f, index_sequence<Is...>, Guard &&) && {
return std::forward<Func>(f)(cast_op<Args>(std::move(std::get<Is>(argcasters)))...);
}
view->len = view->itemsize;
for (auto s : info->shape)
view->len *= s;
+ view->readonly = info->readonly;
+ if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
+ if (view)
+ view->obj = nullptr;
+ PyErr_SetString(PyExc_BufferError, "Writable buffer requested for readonly storage");
+ return -1;
+ }
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
view->format = const_cast<char *>(info->format.c_str());
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
#endif
#define PYBIND11_VERSION_MAJOR 2
-#define PYBIND11_VERSION_MINOR 4
-#define PYBIND11_VERSION_PATCH 3
+#define PYBIND11_VERSION_MINOR 5
+#define PYBIND11_VERSION_PATCH 0
/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode
#if defined(_MSC_VER)
# endif
# pragma warning(push)
# pragma warning(disable: 4510 4610 4512 4005)
-# if defined(_DEBUG)
+# if defined(_DEBUG) && !defined(Py_DEBUG)
# define PYBIND11_DEBUG_MARKER
# undef _DEBUG
# endif
#include <frameobject.h>
#include <pythread.h>
+/* Python #defines overrides on all sorts of core functions, which
+ tends to weak havok in C++ codebases that expect these to work
+ like regular functions (potentially with several overloads) */
#if defined(isalnum)
# undef isalnum
# undef isalpha
# undef toupper
#endif
+#if defined(copysign)
+# undef copysign
+#endif
+
#if defined(_MSC_VER)
# if defined(PYBIND11_DEBUG_MARKER)
# define _DEBUG
#define PYBIND11_STRINGIFY(x) #x
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
#define PYBIND11_CONCAT(first, second) first##second
+#define PYBIND11_ENSURE_INTERNALS_READY \
+ pybind11::detail::get_internals();
#define PYBIND11_CHECK_PYTHON_VERSION \
{ \
static PyObject *pybind11_init(); \
PYBIND11_PLUGIN_IMPL(name) { \
PYBIND11_CHECK_PYTHON_VERSION \
+ PYBIND11_ENSURE_INTERNALS_READY \
try { \
return pybind11_init(); \
} PYBIND11_CATCH_INIT_EXCEPTIONS \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
PYBIND11_PLUGIN_IMPL(name) { \
PYBIND11_CHECK_PYTHON_VERSION \
+ PYBIND11_ENSURE_INTERNALS_READY \
auto m = pybind11::module(PYBIND11_TOSTRING(name)); \
try { \
PYBIND11_CONCAT(pybind11_init_, name)(m); \
object without taking ownership similar to the above
return_value_policy::reference policy. In contrast to that policy, the
function or property’s implicit this argument (called the parent) is
- considered to be the owner of the return value (the child).
+ considered to be the the owner of the return value (the child).
pybind11 then couples the lifetime of the parent to the child via a
reference relationship that ensures that the parent cannot be garbage
collected while Python is still using the child. More advanced
PYBIND11_RUNTIME_EXCEPTION(value_error, PyExc_ValueError)
PYBIND11_RUNTIME_EXCEPTION(type_error, PyExc_TypeError)
PYBIND11_RUNTIME_EXCEPTION(buffer_error, PyExc_BufferError)
+PYBIND11_RUNTIME_EXCEPTION(import_error, PyExc_ImportError)
PYBIND11_RUNTIME_EXCEPTION(cast_error, PyExc_RuntimeError) /// Thrown when pybind11::cast or handle::call fail due to a type casting error
PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used internally
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value))
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
+# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key)
#else
// Usually an int but a long on Cygwin64 with Python 3.x
# define PYBIND11_TLS_KEY_INIT(var) decltype(PyThread_create_key()) var = 0
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
PyThread_set_key_value((key), (value))
# endif
+# define PYBIND11_TLS_FREE(key) (void)key
#endif
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
#if defined(WITH_THREAD)
PYBIND11_TLS_KEY_INIT(tstate);
PyInterpreterState *istate = nullptr;
+ ~internals() {
+ // This destructor is called *after* Py_Finalize() in finalize_interpreter().
+ // That *SHOULD BE* fine. The following details what happens whe PyThread_tss_free is called.
+ // PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does nothing.
+ // PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
+ // PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX). Neither
+ // of those have anything to do with CPython internals.
+ // PyMem_RawFree *requires* that the `tstate` be allocated with the CPython allocator.
+ PYBIND11_TLS_FREE(tstate);
+ }
#endif
};
};
/// Tracks the `internals` and `type_info` ABI version independent of the main library version
-#define PYBIND11_INTERNALS_VERSION 3
+#define PYBIND11_INTERNALS_VERSION 4
/// On MSVC, debug and release builds are not ABI-compatible!
#if defined(_MSC_VER) && defined(_DEBUG)
} catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
} catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return;
} catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
+ } catch (const std::overflow_error &e) { PyErr_SetString(PyExc_OverflowError, e.what()); return;
} catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return;
} catch (...) {
PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
#if PY_MAJOR_VERSION >= 3
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
+ extern "C" PyObject *pybind11_init_impl_##name(); \
extern "C" PyObject *pybind11_init_impl_##name() { \
return pybind11_init_wrapper_##name(); \
}
#else
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
+ extern "C" void pybind11_init_impl_##name(); \
extern "C" void pybind11_init_impl_##name() { \
pybind11_init_wrapper_##name(); \
}
inline void call_operator_delete(void *p, size_t s, size_t a) {
(void)s; (void)a;
-#if defined(PYBIND11_CPP17)
- if (a > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
- ::operator delete(p, s, std::align_val_t(a));
- else
+ #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
+ if (a > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+ #ifdef __cpp_sized_deallocation
+ ::operator delete(p, s, std::align_val_t(a));
+ #else
+ ::operator delete(p, std::align_val_t(a));
+ #endif
+ return;
+ }
+ #endif
+ #ifdef __cpp_sized_deallocation
::operator delete(p, s);
-#else
- ::operator delete(p);
-#endif
+ #else
+ ::operator delete(p);
+ #endif
}
NAMESPACE_END(detail)
buf.strides = py_strides.data();
buf.shape = py_shape.data();
buf.suboffsets = nullptr;
- buf.readonly = false;
+ buf.readonly = info.readonly;
buf.internal = nullptr;
m_ptr = PyMemoryView_FromBuffer(&buf);
return v.release();
}));
+ cl.def("clear",
+ [](Vector &v) {
+ v.clear();
+ },
+ "Clear the contents"
+ );
+
cl.def("extend",
[](Vector &v, const Vector &src) {
v.insert(v.end(), src.begin(), src.end());
// Map assignment when copy-assignable: just copy the value
template <typename Map, typename Class_>
-void map_assignment(enable_if_t<std::is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
+void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
using KeyType = typename Map::key_type;
using MappedType = typename Map::mapped_type;
// Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting
template<typename Map, typename Class_>
void map_assignment(enable_if_t<
- !std::is_copy_assignable<typename Map::mapped_type>::value &&
+ !is_copy_assignable<typename Map::mapped_type>::value &&
is_copy_constructible<typename Map::mapped_type>::value,
Class_> &cl) {
using KeyType = typename Map::key_type;
list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
# Make sure all directory separators are '/'
-string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
-string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
-string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
+string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX "${PYTHON_PREFIX}")
+string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}")
+string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES "${PYTHON_SITE_PACKAGES}")
-if(CMAKE_HOST_WIN32 AND NOT (MSYS OR MINGW))
+if(CMAKE_HOST_WIN32 AND NOT (MINGW AND DEFINED ENV{MSYSTEM}))
set(PYTHON_LIBRARY
"${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib")
set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling modules")
endif()
-set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 3.4)
+set(Python_ADDITIONAL_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4)
find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED)
include(CheckCXXCompilerFlag)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
+
"""
Provide command line operation.
"""
__all__ = ['commandline_operation']
+import os
import shutil
import subprocess
# TODO: Operation returns the output object when called with the shorter signature.
#
@gmx.function_wrapper(output={'erroroutput': str, 'returncode': int})
-def cli(command: NDArray, shell: bool, output: OutputCollectionDescription):
+def cli(command: NDArray, shell: bool, output: OutputCollectionDescription, stdin: str = ''):
"""Execute a command line program in a subprocess.
Configure an executable in a subprocess. Executes when run in an execution
command: a tuple (or list) to be the subprocess arguments, including `executable`
output: mapping of command line flags to output filename arguments
shell: unused (provides forward-compatibility)
+ stdin (str): String input to send to STDIN (terminal input) of the executable.
+
+ Multi-line text sent to *stdin* should be joined into a single string
+ (e.g. ``'\n'.join(list_of_strings) + '\n'``).
+ If multiple strings are provided to *stdin*, gmxapi will assume an ensemble,
+ and will run one operation for each provided string.
+
+ Only string input (:py:func:str) to *stdin* is currently supported.
+ If you have a use case that requires streaming input or binary input,
+ please open an issue or contact the author(s).
Arguments are iteratively added to the command line with standard Python
iteration, so you should use a tuple or list even if you have only one parameter.
# * STDOUT is available if a consuming operation is bound to `output.stdout`.
# * STDERR is available if a consuming operation is bound to `output.stderr`.
# * Otherwise, STDOUT and/or STDERR is(are) closed when command is called.
- #
- # Warning:
- # Commands relying on STDIN cannot be used and is closed when command is called.
# In the operation implementation, we expect the `shell` parameter to be intercepted by the
# wrapper and set to False.
if shell:
raise exceptions.UsageError("Operation does not support shell processing.")
+ if stdin == '':
+ stdin = None
+
if isinstance(command, (str, bytes)):
command = [command]
command = list([arg for arg in command])
- try:
- command[0] = shutil.which(command[0])
- except Exception:
- raise exceptions.ValueError('command argument could not be resolved to an executable file path.')
+
+ executable = shutil.which(command[0])
+ if executable is None:
+ raise exceptions.ValueError('"{}" is not found or not executable.'.format(command[0]))
+ command[0] = executable
# TODO: (FR9) Can OS input/output filehandles be a responsibility of
# the code providing 'resources'?
erroroutput = ''
logger.debug('executing subprocess')
try:
- # TODO: If Python >=3.5 is required, switch to subprocess.run()
- command_output = subprocess.check_output(command,
- shell=shell,
- stdin=subprocess.DEVNULL,
- stderr=subprocess.STDOUT,
- )
- returncode = 0
+ completed_process = subprocess.run(command,
+ shell=shell,
+ input=stdin,
+ check=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ encoding='utf-8',
+ universal_newlines=True
+ )
+ returncode = completed_process.returncode
# TODO: Resource management code should manage a safe data object for `output`.
- # WARNING: We have no reason to assume the output is utf-8 encoded text!!!
- for line in command_output.decode('utf-8').split('\n'):
+ for line in completed_process.stdout.split('\n'):
logger.debug(line)
except subprocess.CalledProcessError as e:
logger.info("commandline operation had non-zero return status when calling {}".format(e.cmd))
- erroroutput = e.output.decode('utf-8')
+ erroroutput = e.output
returncode = e.returncode
- # resources.output.erroroutput.publish(erroroutput)
- # resources.output.returncode.publish(returncode)
- # `publish` is descriptive, but redundant. Access to the output data handler is
- # assumed to coincide with publishing, and we assume data is published when the
- # handler is released. A class with a single `publish` method is overly complex
- # since we can just use the assignment operator.
+ # Publish outputs.
output.erroroutput = erroroutput
output.returncode = returncode
- # TODO: Handle the file output at the higher level wrapper.
- # output.file = None
# TODO: (FR4) Make this a formal operation to properly handle gmxapi data dependencies.
arguments=(),
input_files: dict = None,
output_files: dict = None,
+ stdin: str = None,
**kwargs):
"""Helper function to define a new operation that executes a subprocess in gmxapi data flow.
arguments: list of positional arguments to insert at ``argv[1]``
input_files: mapping of command-line flags to input file names
output_files: mapping of command-line flags to output file names
+ stdin (str): String input to send to STDIN (terminal input) of the executable (optional).
+
+ Multi-line text sent to *stdin* should be joined into a single string.
+ E.g.::
+
+ commandline_operation(..., stdin='\\n'.join(list_of_strings) + '\\n')
+
+ If multiple strings are provided to *stdin*, gmxapi will assume an ensemble,
+ and will run one operation for each provided string.
+
+ Only string input (:py:func:`str`) to *stdin* is currently supported.
+ If you have a use case that requires streaming input or binary input,
+ please open an issue or contact the author(s).
Output:
The output node of the resulting operation handle contains
+
* ``file``: the mapping of CLI flags to filename strings resulting from the ``output_files`` kwarg
* ``erroroutput``: A string of error output (if any) if the process failed.
* ``returncode``: return code of the subprocess.
cli_args = {'command': command,
'shell': shell}
cli_args.update(**kwargs)
+ if stdin is not None:
+ cli_args['stdin'] = str(stdin)
##
# 3. Merge operations
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Note that the current library infrastructure does not provide a way for the
* simulation machinery to express human-readable parameter names with rich
* descriptions, so a few of the most necessary mdrun command line parameters
- * are hard coded here. Ref. https://redmine.gromacs.org/issues/2877
+ * are hard coded here. Ref. https://gitlab.com/gromacs/gromacs/-/issues/2877
*
* For reference and default values, see
* http://manual.gromacs.org/current/onlinehelp/gmx-mdrun.html#options
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Less trivial types (strings, maps, arrays) warrant additional
// design discussion before being exposed through an interface
// like this one.
- // Also reference https://redmine.gromacs.org/issues/2993
+ // Also reference https://gitlab.com/gromacs/gromacs/-/issues/2993
// We can use templates and/or tag dispatch in a more complete
// future implementation.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# gets used correctly.
# ref: https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager
+ if self._done[ensemble_member]:
+ raise exceptions.ProtocolError('Attempting to publish {}[{}] more than once.'.format(self.operation_id, ensemble_member))
+
try:
- if not self._done[ensemble_member]:
- resource = self.__publishing_data_proxy(instance=weakref.proxy(self),
- client_id=ensemble_member)
- yield resource
+ resource = self.__publishing_data_proxy(instance=weakref.proxy(self),
+ client_id=ensemble_member)
except Exception as e:
- message = 'Uncaught {} while providing output-publishing resources for {}.'
- message.format(repr(e), self.operation_id)
- raise exceptions.ApiError(message) from e
- finally:
- logger.debug('Published output for {} member {}'.format(self.operation_id, ensemble_member))
- self._done[ensemble_member] = True
+ logger.debug('Publishing context could not be created due to {}'.format(e))
+ raise e
+
+ yield resource
+ # Note: The remaining lines are skipped if an exception occurs in the `with` block
+ # for the contextmanager suite, which effectively raises at the line after 'yield'.
+ logger.debug('Published output for {} member {}'.format(self.operation_id, ensemble_member))
+ self._done[ensemble_member] = True
def __init__(self, *,
source: DataEdge,
Used internally to implement Futures for the local operation
associated with this resource manager.
+ Raises:
+ exceptions.ApiError if operation runner fails to publish output.
+
+ TODO: More comprehensive error handling for operations that fail to execute.
+
TODO: We need a different implementation for an operation whose output
is served by multiple resource managers. E.g. an operation whose output
is available across the ensemble, but which should only be executed on
# option 1: Make the input and output resources with separate factories and add_resource on
# the runner builder.
# option 2: Pass resource_builder to input_director and then output_director.
- resources = self._resource_factory(input=input, output=output)
+ error_message = 'Got {} while executing {} for operation {}.'
+ try:
+ resources = self._resource_factory(input=input, output=output)
+ except exceptions.TypeError as e:
+ message = error_message.format(e, self._resource_factory, self.operation_id)
+ raise exceptions.ApiError(message) from e
+
runner = self._runner_director(resources)
- runner()
+ try:
+ runner()
+ except Exception as e:
+ message = error_message.format(e, runner, self.operation_id)
+ raise exceptions.ApiError(message) from e
if not self.done():
- raise exceptions.ApiError('update_output implementation failed to update all outputs.')
+ message = 'update_output implementation failed to update all outputs for {}.'
+ message = message.format(self.operation_id)
+ raise exceptions.ApiError(message)
def future(self, name: str, description: ResultDescription):
"""Retrieve a Future for a named output.
For the Python Context, the protocol is for the Context to call the
resource_director instance method, passing input and output containers.
+
+ Raises:
+ exceptions.TypeError if provided resource type does not match input signature.
"""
resources = PyFunctionRunnerResources()
resources.update(input.kwargs)
expected = cls.signature()[name]
got = type(value)
if got != expected:
- raise exceptions.TypeError('Expected {} but got {}.'.format(expected, got))
+ raise exceptions.TypeError(
+ 'Expected {} but got {} for {} resource {}.'.format(expected,
+ got,
+ cls.__basename,
+ name))
return resources
# TODO: (FR4) Update annotations with gmxapi data types. E.g. return -> Future.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
"""Reusable definitions for test modules.
-Define the ``withmpi_only`` test decorator.
+Provides utilities and pytest fixtures for gmxapi and GROMACS tests.
+
+To load these facilities in a pytest environment, set a `pytest_plugins`
+variable in a conftest.py
+(Reference https://docs.pytest.org/en/latest/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file)
+
+ pytest_plugins = "gmxapi.testsupport"
+
+.. seealso:: https://docs.pytest.org/en/latest/plugins.html#findpluginname
.. todo:: Consider moving this to a separate optional package.
"""
+import json
+import logging
+import os
+import shutil
+import tempfile
+import warnings
+from contextlib import contextmanager
+from enum import Enum
+from typing import Union
+
import pytest
-mpi_requirement = 'Test requires mpi4py managing 2 MPI ranks.'
+mpi_status = 'Test requires mpi4py managing 2 MPI ranks.'
+skip_mpi = False
try:
from mpi4py import MPI
if not MPI.Is_initialized():
skip_mpi = True
- reason = mpi_requirement + ' MPI is not initialized'
+ mpi_status += ' MPI is not initialized'
elif MPI.COMM_WORLD.Get_size() < 2:
skip_mpi = True
- reason = mpi_requirement + ' MPI context is too small.'
- else:
- skip_mpi = False
- reason = ''
- withmpi_only = pytest.mark.skipif(skip_mpi, reason=reason)
+ mpi_status += ' MPI context is too small.'
except ImportError:
- withmpi_only = pytest.mark.skip(
- reason=mpi_requirement + ' mpi4py is not available.')
+ skip_mpi = True
+ mpi_status += ' mpi4py is not available.'
+
+
+def pytest_configure(config):
+ config.addinivalue_line("markers", "withmpi_only: test requires mpi4py managing 2 MPI ranks.")
+
+
+def pytest_runtest_setup(item):
+ # Handle the withmpi_only marker.
+ for _ in item.iter_markers(name='withmpi_only'):
+ if skip_mpi:
+ pytest.skip(mpi_status)
+ # The API uses iteration because markers may be duplicated, but we only
+ # care about whether 'withmpi_only' occurs at all.
+ break
+
+
+def pytest_addoption(parser):
+ """Add a command-line user option for the pytest invocation."""
+ parser.addoption(
+ '--rm',
+ action='store',
+ default='always',
+ choices=['always', 'never', 'success'],
+ help='Remove temporary directories "always", "never", or on "success".'
+ )
+
+
+class RmOption(Enum):
+ """Enumerate allowable values of the --rm option."""
+ always = 'always'
+ never = 'never'
+ success = 'success'
+
+
+@pytest.fixture(scope='session')
+def remove_tempdir(request) -> RmOption:
+ """pytest fixture to get access to the --rm CLI option."""
+ arg = request.config.getoption('--rm')
+ return RmOption(arg)
+
+
+@contextmanager
+def scoped_chdir(dir):
+ oldpath = os.getcwd()
+ os.chdir(dir)
+ try:
+ yield dir
+ # If the `with` block using scoped_chdir produces an exception, it will
+ # be raised at this point in this function. We want the exception to
+ # propagate out of the `with` block, but first we want to restore the
+ # original working directory, so we skip `except` but provide a `finally`.
+ finally:
+ os.chdir(oldpath)
+
+
+@contextmanager
+def _cleandir(remove_tempdir: Union[str, RmOption]):
+ """Context manager for a clean temporary working directory.
+
+ Arguments:
+ remove_tempdir (RmOption): whether to remove temporary directory "always",
+ "never", or on "success"
+
+ Raises:
+ ValueError: if remove_tempdir value is not valid.
+
+ The context manager will issue a warning for each temporary directory that
+ is not removed.
+ """
+ if not isinstance(remove_tempdir, RmOption):
+ remove_tempdir = RmOption(remove_tempdir)
+
+ newpath = tempfile.mkdtemp()
+
+ def remove():
+ shutil.rmtree(newpath)
+
+ def warn():
+ warnings.warn('Temporary directory not removed: {}'.format(newpath))
+
+ # Initialize callback function reference
+ if remove_tempdir == RmOption.always:
+ callback = remove
+ else:
+ callback = warn
+
+ try:
+ with scoped_chdir(newpath):
+ yield newpath
+ # If we get to this line, the `with` block using _cleandir did not throw.
+ # Clean up the temporary directory unless the user specified `--rm never`.
+ # I.e. If the user specified `--rm success`, then we need to toggle from `warn` to `remove`.
+ if remove_tempdir != RmOption.never:
+ callback = remove
+ finally:
+ callback()
+
+
+@pytest.fixture
+def cleandir(remove_tempdir: RmOption):
+ """Provide a clean temporary working directory for a test.
+
+ Example usage:
+
+ import os
+ import pytest
+
+ @pytest.mark.usefixtures("cleandir")
+ def test_cwd_starts_empty():
+ assert os.listdir(os.getcwd()) == []
+ with open("myfile", "w") as f:
+ f.write("hello")
+
+ def test_cwd_also_starts_empty(cleandir):
+ assert os.listdir(os.getcwd()) == []
+ assert os.path.abspath(os.getcwd()) == os.path.abspath(cleandir)
+ with open("myfile", "w") as f:
+ f.write("hello")
+
+ @pytest.mark.usefixtures("cleandir")
+ class TestDirectoryInit(object):
+ def test_cwd_starts_empty(self):
+ assert os.listdir(os.getcwd()) == []
+ with open("myfile", "w") as f:
+ f.write("hello")
+
+ def test_cwd_also_starts_empty(self):
+ assert os.listdir(os.getcwd()) == []
+ with open("myfile", "w") as f:
+ f.write("hello")
+
+ Ref: https://docs.pytest.org/en/latest/fixture.html#using-fixtures-from-classes-modules-or-projects
+ """
+ with _cleandir(remove_tempdir) as newdir:
+ yield newdir
+
+
+@pytest.fixture(scope='session')
+def gmxcli():
+ # TODO: (#2896) Find a more canonical way to identify the GROMACS commandline wrapper binary.
+ # We should be able to get the GMXRC contents and related hints from a gmxapi
+ # package resource or from module attributes of a ``gromacs`` stub package.
+ allowed_command_names = ['gmx', 'gmx_mpi']
+ command = None
+ for command_name in allowed_command_names:
+ if command is not None:
+ break
+ command = shutil.which(command_name)
+ if command is None:
+ gmxbindir = os.getenv('GMXBIN')
+ if gmxbindir is None:
+ gromacsdir = os.getenv('GROMACS_DIR')
+ if gromacsdir is not None and gromacsdir != '':
+ gmxbindir = os.path.join(gromacsdir, 'bin')
+ if gmxbindir is None:
+ gmxapidir = os.getenv('gmxapi_DIR')
+ if gmxapidir is not None and gmxapidir != '':
+ gmxbindir = os.path.join(gmxapidir, 'bin')
+ if gmxbindir is not None:
+ gmxbindir = os.path.abspath(gmxbindir)
+ command = shutil.which(command_name, path=gmxbindir)
+ if command is None:
+ message = "Tests need 'gmx' command line tool, but could not find it on the path."
+ raise RuntimeError(message)
+ try:
+ assert os.access(command, os.X_OK)
+ except Exception as E:
+ raise RuntimeError('"{}" is not an executable gmx wrapper program'.format(command)) from E
+ yield command
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
"""
-Provide version and release information.
+gmxapi version and release information.
-Attributes:
- major (int): gmxapi major version number.
- minor (int): gmxapi minor version number.
- patch (int): gmxapi patch level number.
- release (bool): True if imported gmx module is an officially tagged release, else False.
+The ``gmxapi.__version__`` attribute contains a :pep:`version string <440>`.
+The more general way to access the package version is with the
+:py:mod:`pkg_resources <https://setuptools.readthedocs.io/en/latest/pkg_resources.html>` module::
-"""
-import warnings
+ pkg_resources.get_distribution('gmxapi').version
+
+`gmxapi.version` module functions `api_is_at_least()` and `has_feature()`
+support additional convenience and introspection.
+
+.. versionchanged:: 0.2
+
+ This module no longer provides public data attributes.
+ Instead, use the module functions or
+ :py:mod:`packaging.version <https://packaging.pypa.io/en/latest/version/>`.
-__version__ = "0.1.0"
+.. seealso::
-# TODO: (pending infrastructure and further discussion) Configure with CMake.
-# __version__ = "@PROJECT_VERSION@"
-# major = @PROJECT_VERSION_MAJOR@
-# minor = @PROJECT_VERSION_MINOR@
-# patch = @PROJECT_VERSION_PATCH@
+ Consider https://packaging.pypa.io/en/latest/version/ for programmatic
+ handling of the version string. For example::
+
+ from packaging.version import parse
+ gmxapi_version = pkg_resources.get_distribution('gmxapi').version
+ if parse(gmxapi_version).is_prerelease:
+ print('The early bird gets the worm.')
+
+.. todo:: Use pkg_resources.get_distribution('gmxapi').version and
+ "development installations" instead of relying on or publicizing
+ a __version__ attribute.
+"""
+import warnings
-from gmxapi.exceptions import FeatureNotAvailableError
+from .exceptions import FeatureNotAvailableError
-major = 0
-minor = 1
-patch = 0
+# TODO: Version management policy and procedures.
+_major = 0
+_minor = 2
+_micro = 0
+_suffix = 'b1'
-# Note: this is not automatically updated. See RELEASE.txt and https://github.com/kassonlab/gmxapi/issues/152
-release = True
+# Reference https://www.python.org/dev/peps/pep-0440/
+# and https://packaging.pypa.io/en/latest/version/
+__version__ = '{major}.{minor}.{micro}{suffix}'.format(major=_major,
+ minor=_minor,
+ micro=_micro,
+ suffix=_suffix)
# Features added since the initial gmxapi prototype, targeted for version 0.1.
_named_features_0_0 = ['fr1', 'fr3', 'fr7', 'fr15']
# Bugs and bug fixes may be indicated with names consisting of tracked issue URLs.
#
# Features consisting of 'fr' and a numeric suffix are the functional requirements
-# described in roadmap.rst, as described at https://redmine.gromacs.org/issues/2893
+# described in roadmap.rst, as described at https://gitlab.com/gromacs/gromacs/-/issues/2893
#
# fr1: wrap importable Python code.
# fr2: output proxy establishes execution dependency (superseded by fr3)
"""
if not isinstance(major_version, int) or not isinstance(minor_version, int) or not isinstance(patch_version, int):
raise TypeError('Version levels must be provided as integers.')
- if major > major_version:
+ if _major > major_version:
return True
- elif major == major_version and minor >= minor_version:
+ elif _major == major_version and _minor >= minor_version:
return True
- elif major == major_version and minor == minor_version and patch >= patch_version:
+ elif _major == major_version and _minor == minor_version and _micro >= patch_version:
return True
else:
return False
if name in _named_features_0_0:
warnings.warn(
'Old feature name. Use `api_is_at_least(0, 1)` instead of `has_feature({})`.'.format(name),
- category=DeprecationWarning
+ category=DeprecationWarning,
+ stacklevel=2
)
# Check whether the feature is listed in the API specification amendments.
--- /dev/null
+[build-system]
+requires = ['cmake>=3.13',
+ 'scikit-build>=0.10',
+ 'setuptools>=42',
+ 'wheel']
+build-backend = 'setuptools.build_meta:__legacy__'
-cmake>=3.12
-pip>=10.1
+# Requirements for build, installation and testing are provided for convenient
+# use of `pip install -r requirements.txt`. To get a complete list of required
+# packages, such as for completely offline installation, install these pacakges
+# in an empty Python virtual environment and use `pip list` or `pip freeze` to
+# see the actual packages installed, including dependencies, with version info.
+#
+# Note that, ordinarily, build requirements are discovered from pyproject.toml,
+# and run time package dependencies (to be checked during installation) are
+# resolved by setuptools from the `install_requires` argument to setup() in
+# setup.py.
+cmake>=3.13
networkx>=2.0
numpy>=1
-setuptools>=28.0.0
-scikit-build>=0.7
+pip>=10.1
+scikit-build>=0.10
+setuptools>=42
+wheel
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import os
-from skbuild import setup
+# Allow setup.py to be run when scikit-build is not installed, such as to
+# produce source distribution archives with `python setup.py sdist`
+try:
+ from skbuild import setup
+except ImportError:
+ from distutils.core import setup
usage = """
The `gmxapi` package requires an existing GROMACS installation, version 2020 or higher.
setup(
name='gmxapi',
- # TODO: (pending infrastructure and further discussion) Replace with CMake variables from GMXAPI version.
- version='0.1.0.1',
- python_requires='>=3.5, <3.9',
- setup_requires=['cmake>=3.12',
- 'setuptools>=28',
- 'scikit-build>=0.7'],
+ # TODO: single-source version information (currently repeated in gmxapi/version.py)
+ version='0.2.0b1',
+ python_requires='>=3.6, <3.9',
+ install_requires=['networkx>=2.0',
+ 'numpy>=1'],
packages=['gmxapi', 'gmxapi.simulation'],
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import json
import logging
import os
-import shutil
-import tempfile
-import warnings
-from contextlib import contextmanager
-
import pytest
-
-def pytest_addoption(parser):
- """Add a command-line user option for the pytest invocation."""
- parser.addoption(
- '--rm',
- action='store',
- default='always',
- choices=['always', 'never', 'success'],
- help='Remove temporary directories "always", "never", or on "success".'
- )
-
-
-@pytest.fixture(scope='session')
-def remove_tempdir(request):
- """pytest fixture to get access to the --rm CLI option."""
- return request.config.getoption('--rm')
-
-
-@contextmanager
-def scoped_chdir(dir):
- oldpath = os.getcwd()
- os.chdir(dir)
- try:
- yield dir
- # If the `with` block using scoped_chdir produces an exception, it will
- # be raised at this point in this function. We want the exception to
- # propagate out of the `with` block, but first we want to restore the
- # original working directory, so we skip `except` but provide a `finally`.
- finally:
- os.chdir(oldpath)
-
-
-@contextmanager
-def _cleandir(remove_tempdir):
- """Context manager for a clean temporary working directory.
-
- Arguments:
- remove_tempdir (str): whether to remove temporary directory "always",
- "never", or on "success"
-
- The context manager will issue a warning for each temporary directory that
- is not removed.
- """
-
- newpath = tempfile.mkdtemp()
-
- def remove():
- shutil.rmtree(newpath)
-
- def warn():
- warnings.warn('Temporary directory not removed: {}'.format(newpath))
-
- if remove_tempdir == 'always':
- callback = remove
- else:
- callback = warn
- try:
- with scoped_chdir(newpath):
- yield newpath
- # If we get to this line, the `with` block using _cleandir did not throw.
- # Clean up the temporary directory unless the user specified `--rm never`.
- # I.e. If the user specified `--rm success`, then we need to toggle from `warn` to `remove`.
- if remove_tempdir != 'never':
- callback = remove
- finally:
- callback()
-
-
-@pytest.fixture
-def cleandir(remove_tempdir):
- """Provide a clean temporary working directory for a test.
-
- Example usage:
-
- import os
- import pytest
-
- @pytest.mark.usefixtures("cleandir")
- def test_cwd_starts_empty():
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(cleandir):
- assert os.listdir(os.getcwd()) == []
- assert os.path.abspath(os.getcwd()) == os.path.abspath(cleandir)
- with open("myfile", "w") as f:
- f.write("hello")
-
- @pytest.mark.usefixtures("cleandir")
- class TestDirectoryInit(object):
- def test_cwd_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- Ref: https://docs.pytest.org/en/latest/fixture.html#using-fixtures-from-classes-modules-or-projects
- """
- with _cleandir(remove_tempdir) as newdir:
- yield newdir
-
-
-@pytest.fixture(scope='session')
-def gmxcli():
- # TODO: (#2896) Find a more canonical way to identify the GROMACS commandline wrapper binary.
- # We should be able to get the GMXRC contents and related hints from a gmxapi
- # package resource or from module attributes of a ``gromacs`` stub package.
- allowed_command_names = ['gmx', 'gmx_mpi']
- command = None
- for command_name in allowed_command_names:
- if command is not None:
- break
- command = shutil.which(command_name)
- if command is None:
- gmxbindir = os.getenv('GMXBIN')
- if gmxbindir is None:
- gromacsdir = os.getenv('GROMACS_DIR')
- if gromacsdir is not None and gromacsdir != '':
- gmxbindir = os.path.join(gromacsdir, 'bin')
- if gmxbindir is None:
- gmxapidir = os.getenv('gmxapi_DIR')
- if gmxapidir is not None and gmxapidir != '':
- gmxbindir = os.path.join(gmxapidir, 'bin')
- if gmxbindir is not None:
- gmxbindir = os.path.abspath(gmxbindir)
- command = shutil.which(command_name, path=gmxbindir)
- if command is None:
- message = "Tests need 'gmx' command line tool, but could not find it on the path."
- raise RuntimeError(message)
- try:
- assert os.access(command, os.X_OK)
- except Exception as E:
- raise RuntimeError('"{}" is not an executable gmx wrapper program'.format(command)) from E
- yield command
-
+pytest_plugins = ('gmxapi.testsupport',)
@pytest.fixture(scope='class')
def spc_water_box(gmxcli, remove_tempdir):
Prepare the MD input in a freshly created working directory.
"""
import gmxapi as gmx
+ # TODO: Remove this import when the the spc_water_box fixture is migrated to gmxapi.testsupport
+ from gmxapi.testsupport import _cleandir
# TODO: (#2896) Fetch MD input from package / library data.
# Example:
--- /dev/null
+[pytest]
+log_cli=true
+log_level=DEBUG
+junit_family=xunit1
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
operation = commandline.cli(command=[shutil.which('echo'), 'hi', 'there'], shell=False)
assert operation.output.returncode.result() == 0
+ def test_command_with_stdin(self):
+ """Test that cli() can handle string input."""
+ stdin = 'hi\nthere\n'
+ subcommand = '{wc} -l | {grep} -q 2'.format(wc=shutil.which('wc'), grep=shutil.which('grep'))
+
+ operation = commandline.cli(command=['/bin/sh', '-c', subcommand], shell=False, stdin=stdin)
+ assert operation.output.returncode.result() == 0
+ operation = commandline.commandline_operation('/bin/sh', ['-c', subcommand], stdin=stdin)
+ assert operation.output.returncode.result() == 0
+
+ subcommand = '{wc} -l | {grep} -q 1'.format(wc=shutil.which('wc'), grep=shutil.which('grep'))
+
+ operation = commandline.cli(command=['/bin/sh', '-c', subcommand], shell=False, stdin=stdin)
+ assert operation.output.returncode.result() != 0
+ operation = commandline.commandline_operation('/bin/sh', ['-c', subcommand], stdin=stdin)
+ assert operation.output.returncode.result() != 0
+
class CommandLineOperationSimpleTestCase(unittest.TestCase):
"""Test the command line wrapper operation factory."""
import pytest
import gmxapi as gmx
-from gmxapi.testsupport import withmpi_only
# Configure the `logging` module before proceeding any further.
gmx.logger.setLevel(logging.WARNING)
# TODO: better handling of output on unused MPI ranks.
-@withmpi_only
+@pytest.mark.withmpi_only
@pytest.mark.usefixtures('cleandir')
def test_run_trivial_ensemble(spc_water_box, caplog):
from mpi4py import MPI
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import json
import logging
import os
-import shutil
-import tempfile
-import warnings
-from contextlib import contextmanager
import pytest
-
-def pytest_addoption(parser):
- """Add a command-line user option for the pytest invocation."""
- parser.addoption(
- '--rm',
- action='store',
- default='always',
- choices=['always', 'never', 'success'],
- help='Remove temporary directories "always", "never", or on "success".'
- )
-
-
-@pytest.fixture(scope='session')
-def remove_tempdir(request):
- """pytest fixture to get access to the --rm CLI option."""
- return request.config.getoption('--rm')
-
-
-@contextmanager
-def scoped_chdir(dir):
- oldpath = os.getcwd()
- os.chdir(dir)
- try:
- yield dir
- # If the `with` block using scoped_chdir produces an exception, it will
- # be raised at this point in this function. We want the exception to
- # propagate out of the `with` block, but first we want to restore the
- # original working directory, so we skip `except` but provide a `finally`.
- finally:
- os.chdir(oldpath)
-
-
-@contextmanager
-def _cleandir(remove_tempdir):
- """Context manager for a clean temporary working directory.
-
- Arguments:
- remove_tempdir (str): whether to remove temporary directory "always",
- "never", or on "success"
-
- The context manager will issue a warning for each temporary directory that
- is not removed.
- """
-
- newpath = tempfile.mkdtemp()
-
- def remove():
- shutil.rmtree(newpath)
-
- def warn():
- warnings.warn('Temporary directory not removed: {}'.format(newpath))
-
- if remove_tempdir == 'always':
- callback = remove
- else:
- callback = warn
- try:
- with scoped_chdir(newpath):
- yield newpath
- # If we get to this line, the `with` block using _cleandir did not throw.
- # Clean up the temporary directory unless the user specified `--rm never`.
- # I.e. If the user specified `--rm success`, then we need to toggle from `warn` to `remove`.
- if remove_tempdir != 'never':
- callback = remove
- finally:
- callback()
-
-
-@pytest.fixture
-def cleandir(remove_tempdir):
- """Provide a clean temporary working directory for a test.
-
- Example usage:
-
- import os
- import pytest
-
- @pytest.mark.usefixtures("cleandir")
- def test_cwd_starts_empty():
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(cleandir):
- assert os.listdir(os.getcwd()) == []
- assert os.path.abspath(os.getcwd()) == os.path.abspath(cleandir)
- with open("myfile", "w") as f:
- f.write("hello")
-
- @pytest.mark.usefixtures("cleandir")
- class TestDirectoryInit(object):
- def test_cwd_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_also_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- Ref: https://docs.pytest.org/en/latest/fixture.html#using-fixtures-from-classes-modules-or-projects
- """
- with _cleandir(remove_tempdir) as newdir:
- yield newdir
-
-
-@pytest.fixture(scope='session')
-def gmxcli():
- # TODO: (#2896) Find a more canonical way to identify the GROMACS commandline wrapper binary.
- # We should be able to get the GMXRC contents and related hints from a gmxapi
- # package resource or from module attributes of a ``gromacs`` stub package.
- allowed_command_names = ['gmx', 'gmx_mpi']
- command = None
- for command_name in allowed_command_names:
- if command is not None:
- break
- command = shutil.which(command_name)
- if command is None:
- gmxbindir = os.getenv('GMXBIN')
- if gmxbindir is None:
- gromacsdir = os.getenv('GROMACS_DIR')
- if gromacsdir is not None and gromacsdir != '':
- gmxbindir = os.path.join(gromacsdir, 'bin')
- if gmxbindir is None:
- gmxapidir = os.getenv('gmxapi_DIR')
- if gmxapidir is not None and gmxapidir != '':
- gmxbindir = os.path.join(gmxapidir, 'bin')
- if gmxbindir is not None:
- gmxbindir = os.path.abspath(gmxbindir)
- command = shutil.which(command_name, path=gmxbindir)
- if command is None:
- message = "Tests need 'gmx' command line tool, but could not find it on the path."
- raise RuntimeError(message)
- try:
- assert os.access(command, os.X_OK)
- except Exception as E:
- raise RuntimeError('"{}" is not an executable gmx wrapper program'.format(command)) from E
- yield command
+pytest_plugins = ('gmxapi.testsupport',)
@pytest.fixture(scope='class')
Prepare the MD input in a freshly created working directory.
"""
import gmxapi as gmx
+ # TODO: Remove this import when the the spc_water_box fixture is migrated to gmxapi.testsupport
+ from gmxapi.testsupport import _cleandir
# TODO: (#2896) Fetch MD input from package / library data.
# Example:
[pytest]
log_cli=true
log_level=DEBUG
+junit_family=xunit1
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
"""Test gmxapi functionality described in roadmap.rst."""
import gmxapi as gmx
-import pytest
-from gmxapi.version import has_feature
-@pytest.mark.skipif(not has_feature('fr1'),
- reason="Feature level not met.")
def test_fr1():
"""FR1: Wrap importable Python code.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import tempfile
import gmxapi as gmx
-import pytest
-from gmxapi.version import has_feature
-@pytest.mark.skipif(not has_feature('fr3'),
- reason="Feature level not met.")
def test_fr3():
"""FR3: Output proxy can be used as input."""
with tempfile.TemporaryDirectory() as directory:
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import pytest
import gmxapi as gmx
-from gmxapi.version import has_feature
-@pytest.mark.skipif(not has_feature('fr7'),
- reason="Feature level not met.")
+
@pytest.mark.usefixtures('cleandir')
def test_fr7(spc_water_box):
"""FR7: Python bindings for launching simulations.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import gmxapi as gmx
from gmxapi.version import has_feature
-# Ref https://redmine.gromacs.org/issues/3192
+# Ref https://gitlab.com/gromacs/gromacs/-/issues/3192
@pytest.mark.skipif(not has_feature('fr8'),
reason="Feature level not met.")
def test_fr8(spc_water_box):
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
import pytest
import gmxapi as gmx
-from gmxapi.version import has_feature
# Configure the `logging` module before proceeding any further.
gmx.logger.setLevel(logging.WARNING)
formatter = logging.Formatter(rank_tag + '%(name)s:%(levelname)s: %(message)s')
@pytest.mark.usefixtures('cleandir')
-@pytest.mark.skipif(not has_feature('fr15'),
- reason="Feature level not met.")
def test_fr15(spc_water_box, caplog):
"""FR15: Simulation input modification.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
+if(APPLE)
+ set(LD_LIBRARY_PATH "DYLD_LIBRARY_PATH")
+else()
+ set(LD_LIBRARY_PATH "LD_LIBRARY_PATH")
+endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GMXRC.cmakein ${CMAKE_CURRENT_BINARY_DIR}/GMXRC @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GMXRC.bash.cmakein ${CMAKE_CURRENT_BINARY_DIR}/GMXRC.bash @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GMXRC.csh.cmakein ${CMAKE_CURRENT_BINARY_DIR}/GMXRC.csh @ONLY)
# First remove gromacs part of ld_library_path
tmppath=""
-for i in $LD_LIBRARY_PATH; do
+for i in $@LD_LIBRARY_PATH@; do
if test "$i" != "$GMXLDLIB"; then
tmppath="${tmppath}${tmppath:+:}${i}"
fi
done
-LD_LIBRARY_PATH=$tmppath
+@LD_LIBRARY_PATH@=$tmppath
# remove gromacs part of PKG_CONFIG_PATH
tmppath=""
GMXTOOLCHAINDIR=${GMXPREFIX}/@GMX_INSTALL_CMAKEDIR@
GROMACS_DIR=${GMXPREFIX}
-LD_LIBRARY_PATH=${GMXLDLIB}${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH}
+@LD_LIBRARY_PATH@=${GMXLDLIB}${@LD_LIBRARY_PATH@:+:}${@LD_LIBRARY_PATH@}
PKG_CONFIG_PATH=${GMXLDLIB}/pkgconfig${PKG_CONFIG_PATH:+:}${PKG_CONFIG_PATH}
PATH=${GMXBIN}${PATH:+:}${PATH}
#debian/ubuntu needs a : at the end
MANPATH=${GMXMAN}:${MANPATH}
# export should be separate, so /bin/sh understands it
-export GMXBIN GMXLDLIB GMXMAN GMXDATA LD_LIBRARY_PATH PATH MANPATH
+export GMXBIN GMXLDLIB GMXMAN GMXDATA @LD_LIBRARY_PATH@ PATH MANPATH
export PKG_CONFIG_PATH GROMACS_DIR
IFS="$old_IFS"
# repeatedly switch between gmx versions in a shell.
# zero possibly unset vars to avoid warnings
-if (! $?LD_LIBRARY_PATH) setenv LD_LIBRARY_PATH ""
+if (! $?@LD_LIBRARY_PATH@) setenv @LD_LIBRARY_PATH@ ""
if (! $?PKG_CONFIG_PATH) setenv PKG_CONFIG_PATH ""
if (! $?PATH) setenv PATH ""
if (! $?MANPATH) setenv MANPATH ""
# remove previous gromacs part from ld_library_path
set tmppath = ""
-foreach i ( `echo $LD_LIBRARY_PATH | sed "s/:/ /g"` )
+foreach i ( `echo $@LD_LIBRARY_PATH@ | sed "s/:/ /g"` )
if ( "$i" != "$GMXLDLIB" ) then
if ("${tmppath}" == "") then
set tmppath = "$i"
endif
endif
end
-setenv LD_LIBRARY_PATH $tmppath
+setenv @LD_LIBRARY_PATH@ $tmppath
# remove previous gromacs part from PKG_CONFIG_PATH
set tmppath = ""
setenv GROMACS_DIR ${GMXPREFIX}
#make them begin with :
-if ($?LD_LIBRARY_PATH) setenv LD_LIBRARY_PATH ":${LD_LIBRARY_PATH}"
+if ($?@LD_LIBRARY_PATH@) setenv @LD_LIBRARY_PATH@ ":${@LD_LIBRARY_PATH@}"
if ($?PKG_CONFIG_PATH) setenv PKG_CONFIG_PATH ":${PKG_CONFIG_PATH}"
#path is never empty
setenv PATH ${GMXBIN}:${PATH}
-setenv LD_LIBRARY_PATH ${GMXLDLIB}${LD_LIBRARY_PATH}
+setenv @LD_LIBRARY_PATH@ ${GMXLDLIB}${@LD_LIBRARY_PATH@}
setenv PKG_CONFIG_PATH ${GMXLDLIB}/pkgconfig${PKG_CONFIG_PATH}
#debian/ubuntu needs a : at the end
setenv MANPATH ${GMXMAN}:${MANPATH}
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2011,2012,2013,2014,2018, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+# Copyright (c) 2014,2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2014,2016,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2014,2016,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
gmx_target_warning_suppression(template /wd4244 HAS_NO_MSVC_LOSSY_CONVERSION_DOUBLE_TO_REAL)
gmx_target_warning_suppression(template /wd4267 HAS_NO_MSVC_LOSSY_CONVERSION_SIZE_T_TO_INT)
endif()
+# This should be removable once object libraries can directly use target_link_libraries
+# with CMake 3.12, #3290
+target_include_directories(template SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
target_link_libraries(template libgromacs ${GMX_EXE_LINKER_FLAGS})
set(DOCUMENTATION_HTTP_URL_BASE
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald, recommended
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tip4pew TIP4P-Ew TIP 4-point optimized with Ewald
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip3p TIP3P TIP 3-point, recommended
tip4p TIP4P TIP 4-point
tips3p TIPS3P CHARMM TIP 3-point with LJ on H's
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
spc SPC simple point charge
spce SPC/E extended simple point charge
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
tip4p TIP4P TIP 4-point, recommended
tip4pew TIP4PEW TIP 4-point with Ewald
tip3p TIP3P TIP 3-point
-tip5p TIP5P TIP 5-point (see http://redmine.gromacs.org/issues/1348 for issues)
+tip5p TIP5P TIP 5-point (see https://gitlab.com/gromacs/gromacs/-/issues/1348 for issues)
tip5pe TIP5P TIP 5-point improved for Ewald sums
spc SPC simple point charge
spce SPC/E extended simple point charge
# We have many cases where int is converted to float and we don't care
# enough about such potential loss of precision to use explicit casts
# in large numbers of places.
-
+#
+# -google-readability-avoid-underscore-in-googletest-name
+# We need to use underscores for readability for our legacy types
+# and command-line parameter names
+#
Checks: clang-diagnostic-*,-clang-analyzer-*,-clang-analyzer-security.insecureAPI.strcpy,
bugprone-*,misc-*,readability-*,performance-*,mpi-*,
-readability-inconsistent-declaration-parameter-name,
-readability-magic-numbers,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-narrowing-conversions,
- -bugprone-narrowing-conversions
+ -bugprone-narrowing-conversions,
+ -google-readability-avoid-underscore-in-googletest-name
HeaderFilterRegex: .*
CheckOptions:
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
"-Wno-covered-switch-default" #GCC gives maybe-uninitialized without default label and checks for illegal enum values.
"-Wno-switch-enum" # default statement for enum is OK
- # TODO uncomment the next few ignore lines when we upgrade to test with clang 8 in Jenkins
-
- # The barriers we use for tMPI and Nbnxm are sufficient, but it's
- # not known whether they're excessive. We assume they not
- # excessive.
- # "-Wno-atomic-implicit-seq-cst"
-
# We need to use macros like
# GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR. Those will look strange
# if they don't have a semicolon after them, and might confuse
# tools like IDEs also.
- # "-Wno-extra-semi-stmt"
+ "-Wno-extra-semi-stmt"
#Following ones are undecided/TODO
"-Wno-disabled-macro-expansion"
"-Wno-double-promotion")
string(REPLACE " " ";" IGNORED_CLANG_ALL_WARNINGS "${IGNORED_CLANG_ALL_WARNINGS}")
+option(GMX_CLANG_TIDY "Use clang-tidy" OFF)
if (GMX_CLANG_TIDY)
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
+ elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithAssert")
+ elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
+ elseif("${CMAKE_BUILD_TYPE}" STREQUAL "ASAN")
+ else()
+ message(FATAL_ERROR "Can only use clang-tidy with build type containing asserts: Debug, RelWithAssert, RelWithDebInfo, ASAN.")
+ endif()
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+ mark_as_advanced(CMAKE_EXPORT_COMPILE_COMMANDS)
set(CLANG_TIDY "clang-tidy" CACHE STRING "Name of clang-tidy executable")
find_program(CLANG_TIDY_EXE NAMES "${CLANG_TIDY}"
DOC "Path to clang-tidy executable")
if(NOT CLANG_TIDY_EXE)
message(FATAL_ERROR "clang-tidy not found.")
endif()
+ mark_as_advanced(CLANG_TIDY)
+ mark_as_advanced(CLANG_TIDY_EXE)
endif()
-#####
add_subdirectory(external)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# to establish compatibility guarantees consistent with semantic versioning.
# (https://semver.org). When the API is deemed suitably stable, gmxapi 1.0 should
# be tagged. Official GROMACS releases should be mappable to a distinct gmxapi
-# release string. For roadmap details, see https://redmine.gromacs.org/issues/2585
+# release string. For roadmap details, see https://gitlab.com/gromacs/gromacs/-/issues/2585
set(GMXAPI_MAJOR 0)
set(GMXAPI_MINOR 1)
set(GMXAPI_PATCH 0)
gmx_target_compile_options(gmxapi)
target_compile_definitions(gmxapi PRIVATE HAVE_CONFIG_H)
target_include_directories(gmxapi SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
+# Should be possible to change this when resolving #3290
+target_include_directories(gmxapi SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
# Define public interface. Make sure targets linking against `gmxapi` in the build
# system don't accidentally have the implementation headers (this directory))
* process starts and instead manage files (paths) in an absolute and
* immutable way, with abstraction provided through the Context chain-of-responsibility.
* TODO: API abstractions for initializing simulations that may be new or partially
- * complete. Reference gmxapi milestone 13 at https://redmine.gromacs.org/issues/2585
+ * complete. Reference gmxapi milestone 13 at https://gitlab.com/gromacs/gromacs/-/issues/2585
*/
// Create a mock argv. Note that argv[0] is expected to hold the program name.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdrun/legacymdrunoptions.h"
#include "gromacs/mdtypes/mdrunoptions.h"
+// Above are headers for dependencies.
+// Following are public headers for the current module.
#include "gmxapi/context.h"
#include "gmxapi/session.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdrunutility/logging.h"
+// Above are headers for dependencies.
+// Following are public headers for the current module.
#include "gmxapi/context.h"
#include "gmxapi/session.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <string>
#include <vector>
-#include "gmxapi/gmxapicompat.h"
#include "gmxapi/gmxapi.h"
+#include "gmxapi/gmxapicompat.h"
namespace gmxapicompat
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* e.g. MPI, Python, numpy, GROMACS, JSON, etc.
* \todo Actually check the size of the types.
*
- * \see https://redmine.gromacs.org/issues/2993 for discussion.
+ * \see https://gitlab.com/gromacs/gromacs/-/issues/2993 for discussion.
*/
enum class GmxapiType
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <atomic>
#include <functional>
-
#include <memory>
+
#include "gromacs/mdlib/simulationsignal.h"
#include "gromacs/mdlib/stophandler.h"
#include "gromacs/mdrun/runner.h"
+// Public gmxapi headers.
#include "gmxapi/session.h"
#include "gmxapi/md/mdsignals.h"
-#include "session_impl.h"
+// Internal gmxapi headers.
+#include "api/cpp/session_impl.h"
namespace gmxapi
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <map>
-#include "gromacs/mdrunutility/logging.h"
#include "gromacs/mdrun/runner.h"
#include "gromacs/mdrun/simulationcontext.h"
+#include "gromacs/mdrunutility/logging.h"
+// Above are the public headers from other modules.
+// Following are public headers for the current module.
#include "gmxapi/context.h"
#include "gmxapi/md.h"
+#include "gmxapi/status.h"
#include "gmxapi/md/mdmodule.h"
#include "gmxapi/session/resources.h"
-#include "gmxapi/status.h"
+
namespace gmxapi
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \ingroup gmxapi
*/
-#include "gmxapi/session/resources.h"
-
#include <string>
-#include "gmxapi/md/mdsignals.h"
#include "gmxapi/session.h"
+#include "gmxapi/md/mdsignals.h"
+#include "gmxapi/session/resources.h"
namespace gmxapi
{
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# Test public interface.
#
-gmx_add_gtest_executable(
- gmxapi-test
- restraint.cpp
- status.cpp
- system.cpp
- version.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(gmxapi-test
+ CPP_SOURCE_FILES
+ restraint.cpp
+ status.cpp
+ system.cpp
+ version.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
if(NOT GMX_USE_OPENCL)
# GPU resources may not be properly reinitialized between simulations in
# the same process.
# TODO: include this with the other test sources once the issue is resolved
- # Ref https://redmine.gromacs.org/issues/2689
+ # Ref https://gitlab.com/gromacs/gromacs/-/issues/2689
target_sources(gmxapi-test PRIVATE runner.cpp stopsignaler.cpp)
endif()
# Link against the gmxapi libraries and get access to its public (installed) headers.
target_link_libraries(gmxapi-test PRIVATE Gromacs::gmxapi mdrun_test_infrastructure)
-gmx_register_gtest_test(GmxapiExternalInterfaceTests gmxapi-test OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(GmxapiExternalInterfaceTests gmxapi-test OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
set_tests_properties(GmxapiExternalInterfaceTests PROPERTIES
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# Test public interface with MPI.
#
-gmx_add_gtest_executable(
- gmxapi-mpi-test MPI
- restraint.cpp
- status.cpp
- system.cpp
- version.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(gmxapi-mpi-test MPI
+ CPP_SOURCE_FILES
+ restraint.cpp
+ status.cpp
+ system.cpp
+ version.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
if(NOT GMX_USE_OPENCL)
# GPU resources may not be properly reinitialized between simulations in
# the same process.
# TODO: include this with the other test sources once the issue is resolved
- # Ref https://redmine.gromacs.org/issues/2689
+ # Ref https://gitlab.com/gromacs/gromacs/-/issues/2689
target_sources(gmxapi-mpi-test PRIVATE runner.cpp stopsignaler.cpp)
endif()
${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(gmxapi-mpi-test PRIVATE Gromacs::gmxapi mdrun_test_infrastructure)
-gmx_register_gtest_test(GmxapiMpiTests gmxapi-mpi-test MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(GmxapiMpiTests gmxapi-mpi-test MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
* the research papers on the package. Check out http://www.gromacs.org.
*/
#include <memory>
+#include <optional>
-#include "gromacs/compat/optional.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/vectypes.h"
#include "gromacs/restraint/restraintpotential.h"
/*!
* \brief Record the simulation time at the last step active.
*/
- gmx::compat::optional<double> lastSimulationTime_;
+ std::optional<double> lastSimulationTime_;
/*!
* \brief Whether restraint was ever used
#ifndef GROMACS_TESTINGCONFIGURATION_H
#define GROMACS_TESTINGCONFIGURATION_H
-#include <gtest/gtest.h>
+#include "config.h"
#include <string>
#include <vector>
#include "config.h"
+#include <gtest/gtest.h>
+
#include "gromacs/gmxpreprocess/grompp.h"
#include "gromacs/math/vec.h"
#include "gromacs/utility/stringutil.h"
#include "gromacs/utility/textwriter.h"
+#include "programs/mdrun/tests/moduletest.h"
#include "testutils/cmdlinetest.h"
#include "testutils/testfilemanager.h"
-#include "programs/mdrun/tests/moduletest.h"
namespace gmxapi
{
/* set program name, command line, and default values for output options */
gmx_output_env_t* oenv;
- gmx::TimeUnit timeUnit = gmx::TimeUnit_Default;
+ gmx::TimeUnit timeUnit = gmx::TimeUnit::Default;
bool bView{ false }; // argument that says we don't want to view graphs.
- int xvgFormat{ 0 };
- output_env_init(&oenv, gmx::getProgramContext(),
- static_cast<time_unit_t>(timeUnit + 1), // NOLINT(misc-misplaced-widening-cast)
- bView, static_cast<xvg_format_t>(xvgFormat + 1), 0);
+ output_env_init(&oenv, gmx::getProgramContext(), timeUnit, bView, XvgFormat::Xmgrace, 0);
double run_t = irInstance.init_step * irInstance.delta_t + irInstance.init_t;
NodeKey Workflow::addNode(std::unique_ptr<NodeSpecification> spec)
{
// TODO capture provided NodeSpecification.
- // Relates to gmxapi milestone 7, described at https://redmine.gromacs.org/issues/2585
+ // Relates to gmxapi milestone 7, described at https://gitlab.com/gromacs/gromacs/-/issues/2585
throw gmxapi::NotImplementedError("Member function not yet implemented or used.");
(void)spec;
return {};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \todo Not yet implemented.
*/
- NodeKey addNode(std::unique_ptr<NodeSpecification> spec);
+ static NodeKey addNode(std::unique_ptr<NodeSpecification> spec);
/*!
* \brief Get the node specification for a provided key.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-#
# Test private interface.
#
-gmx_add_gtest_executable(
- workflow-details-test
- workflow.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
+gmx_add_gtest_executable(workflow-details-test
+ CPP_SOURCE_FILES
+ workflow.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
)
target_link_libraries(workflow-details-test PRIVATE Gromacs::gmxapi gmxapi-detail mdrun_test_infrastructure)
-gmx_register_gtest_test(GmxapiInternalInterfaceTests workflow-details-test OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(GmxapiInternalInterfaceTests workflow-details-test OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
set_tests_properties(GmxapiInternalInterfaceTests PROPERTIES
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# Test with MPI.
#
-gmx_add_gtest_executable(
- workflow-details-mpi-test MPI
- workflow.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
+gmx_add_gtest_executable(workflow-details-mpi-test MPI
+ CPP_SOURCE_FILES
+ workflow.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
)
target_link_libraries(workflow-details-mpi-test PRIVATE Gromacs::gmxapi gmxapi-detail mdrun_test_infrastructure)
-gmx_register_gtest_test(GmxapiInternalsMpiTests workflow-details-mpi-test MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(GmxapiInternalsMpiTests workflow-details-mpi-test MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
-#include "api/cpp/workflow.h"
-#include "api/cpp/workflow_impl.h"
-#include "api/cpp/include/gmxapi/context.h"
-#include "api/cpp/include/gmxapi/status.h"
-#include "api/cpp/include/gmxapi/system.h"
-
-#include "gromacs/utility/arrayref.h"
-
-#include "api/cpp/tests/testingconfiguration.h"
+#include "workflow.h"
+#include "workflow_impl.h"
+#include "tests/testingconfiguration.h"
namespace gmxapi
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \ingroup gmxapi
*/
-#include "workflow.h"
-
#include <memory>
#include <string>
#include "gmxapi/exceptions.h"
+// Local module internal headers.
+#include "api/cpp/workflow.h"
+
namespace gmxapi
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* Enable code that requires AVX-512 instruction support, without GMX_SIMD=AVX_512 */
#cmakedefine01 SIMD_AVX_512_CXX_SUPPORTED
+/* Whether NBNXM and other SIMD kernels should be compiled */
+#cmakedefine01 GMX_USE_SIMD_KERNELS
+
/* Whether a double-precision configuration may target accuracy equivalent to single precision */
#cmakedefine01 GMX_RELAXED_DOUBLE_PRECISION
/* Use if we cannot rename checkpoints */
#cmakedefine01 GMX_NO_RENAME
-/* Use (modified) Gamess-UK for QM-MM calculations */
-#cmakedefine01 GMX_QMMM_GAMESS
-
-/* Use (modified) Gaussian0x for QM-MM calculations */
-#cmakedefine01 GMX_QMMM_GAUSSIAN
-
-/* Use (modified) Mopac 7 for QM-MM calculations */
-#cmakedefine01 GMX_QMMM_MOPAC
-
-/* Use ORCA for QM-MM calculations */
-#cmakedefine01 GMX_QMMM_ORCA
-
-/* Use cycle counters */
-#cmakedefine01 GMX_CYCLECOUNTERS
-
/* Use sub-counters */
#cmakedefine01 GMX_CYCLE_SUBCOUNTERS
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2019, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
interface for that. So, GTEST_CAN_STREAM_RESULTS is added in
googletest/include/gtest/internal/gtest-port.h to allow the default
behaviour to be applied only if the user hasn't gotten involved.
+
+Some compiler warnings cannot be suppressed through CMake machinery,
+such as for the clang static analyzer, and some lines are removed
+from consideration by wrapping with `#ifndef __clang_analyzer__`
+... `#endif`.
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
- T* get() const { return ptr_; }
-
+ T* get() const {
+#ifndef __clang_analyzer__
+ return ptr_;
+#else
+ return nullptr;
+#endif
+ }
T* release() {
T* const ptr = ptr_;
ptr_ = NULL;
void reset(T* p = NULL) {
if (p != ptr_) {
if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type.
+#ifndef __clang_analyzer__
delete ptr_;
+#endif
}
ptr_ = p;
}
+++ /dev/null
-The header file here provides a C++14-compatible implementation of
-std::optional as nonstd::optional.
-
-This implementation is nearly identical to the reference
-implementation at commit a08fda6c674ae4c9f of
-https://github.com/martinmoene/optional-lite.git.
-
-There is no Doxygen for this code, but it is intended to conform to
-that of std::optional, so look in the usual C++17 documentation for
-std::optional for that.
-
-This will be removed when GROMACS requires C++17, which has a
-standardized version of std::optional.
-
-Some minor fixes were required for portability, which are described in
-comments containing "GMX".
+++ /dev/null
-//
-// Copyright (c) 2014-2018 Martin Moene
-//
-// https://github.com/martinmoene/optional-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-// GMX see README for modification notes
-
-#pragma once
-
-#ifndef NONSTD_OPTIONAL_LITE_HPP
-#define NONSTD_OPTIONAL_LITE_HPP
-
-#define optional_lite_MAJOR 3
-#define optional_lite_MINOR 1
-#define optional_lite_PATCH 1
-
-#define optional_lite_VERSION optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
-
-#define optional_STRINGIFY( x ) optional_STRINGIFY_( x )
-#define optional_STRINGIFY_( x ) #x
-
-// optional-lite configuration:
-
-#define optional_OPTIONAL_DEFAULT 0
-#define optional_OPTIONAL_NONSTD 1
-#define optional_OPTIONAL_STD 2
-
-#if !defined( optional_CONFIG_SELECT_OPTIONAL )
-# define optional_CONFIG_SELECT_OPTIONAL ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
-#endif
-
-// Control presence of exception handling (try and auto discover):
-
-#ifndef optional_CONFIG_NO_EXCEPTIONS
-# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-# define optional_CONFIG_NO_EXCEPTIONS 0
-# else
-# define optional_CONFIG_NO_EXCEPTIONS 1
-# endif
-#endif
-
-// C++ language version detection (C++20 is speculative):
-// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
-
-#ifndef optional_CPLUSPLUS
-# if defined(_MSVC_LANG ) && !defined(__clang__)
-# define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
-# else
-# define optional_CPLUSPLUS __cplusplus
-# endif
-#endif
-
-#define optional_CPP98_OR_GREATER ( optional_CPLUSPLUS >= 199711L )
-#define optional_CPP11_OR_GREATER ( optional_CPLUSPLUS >= 201103L )
-#define optional_CPP11_OR_GREATER_ ( optional_CPLUSPLUS >= 201103L )
-#define optional_CPP14_OR_GREATER ( optional_CPLUSPLUS >= 201402L )
-#define optional_CPP17_OR_GREATER ( optional_CPLUSPLUS >= 201703L )
-#define optional_CPP20_OR_GREATER ( optional_CPLUSPLUS >= 202000L )
-
-// C++ language version (represent 98 as 3):
-
-#define optional_CPLUSPLUS_V ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
-
-// Use C++17 std::optional if available and requested:
-
-#if optional_CPP17_OR_GREATER && defined(__has_include )
-# if __has_include( <optional> )
-# define optional_HAVE_STD_OPTIONAL 1
-# else
-# define optional_HAVE_STD_OPTIONAL 0
-# endif
-#else
-# define optional_HAVE_STD_OPTIONAL 0
-#endif
-
-#define optional_USES_STD_OPTIONAL ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
-
-//
-// in_place: code duplicated in any-lite, expected-lite, optional-lite, value-ptr-lite, variant-lite:
-//
-
-#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
-#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
-
-// C++17 std::in_place in <utility>:
-
-#if optional_CPP17_OR_GREATER
-
-#include <utility>
-
-namespace nonstd {
-
-using std::in_place;
-using std::in_place_type;
-using std::in_place_index;
-using std::in_place_t;
-using std::in_place_type_t;
-using std::in_place_index_t;
-
-#define nonstd_lite_in_place_t( T) std::in_place_t
-#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
-#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
-
-#define nonstd_lite_in_place( T) std::in_place_t{}
-#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
-#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
-
-} // namespace nonstd
-
-#else // optional_CPP17_OR_GREATER
-
-#include <cstddef>
-
-namespace nonstd {
-namespace detail {
-
-template< class T >
-struct in_place_type_tag {};
-
-template< std::size_t K >
-struct in_place_index_tag {};
-
-} // namespace detail
-
-struct in_place_t {};
-
-template< class T >
-inline in_place_t in_place( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
-{
- return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
-{
- return in_place_t();
-}
-
-template< class T >
-inline in_place_t in_place_type( detail::in_place_type_tag<T> /*unused*/ = detail::in_place_type_tag<T>() )
-{
- return in_place_t();
-}
-
-template< std::size_t K >
-inline in_place_t in_place_index( detail::in_place_index_tag<K> /*unused*/ = detail::in_place_index_tag<K>() )
-{
- return in_place_t();
-}
-
-// mimic templated typedef:
-
-#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
-#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
-#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
-
-#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
-#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
-#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
-
-} // namespace nonstd
-
-#endif // optional_CPP17_OR_GREATER
-#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
-
-//
-// Using std::optional:
-//
-
-#if optional_USES_STD_OPTIONAL
-
-#include <optional>
-
-namespace nonstd {
-
- using std::optional;
- using std::bad_optional_access;
- using std::hash;
-
- using std::nullopt;
- using std::nullopt_t;
-
- using std::operator==;
- using std::operator!=;
- using std::operator<;
- using std::operator<=;
- using std::operator>;
- using std::operator>=;
- using std::make_optional;
- using std::swap;
-}
-
-#else // optional_USES_STD_OPTIONAL
-
-#include <cassert>
-#include <utility>
-
-// optional-lite alignment configuration:
-
-#ifndef optional_CONFIG_MAX_ALIGN_HACK
-# define optional_CONFIG_MAX_ALIGN_HACK 0
-#endif
-
-#ifndef optional_CONFIG_ALIGN_AS
-// no default, used in #if defined()
-#endif
-
-#ifndef optional_CONFIG_ALIGN_AS_FALLBACK
-# define optional_CONFIG_ALIGN_AS_FALLBACK double
-#endif
-
-// Compiler warning suppression:
-
-#if defined(__clang__)
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wundef"
-#elif defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wundef"
-#elif defined(_MSC_VER )
-# pragma warning( push )
-#endif
-
-// half-open range [lo..hi):
-#define optional_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
-
-// Compiler versions:
-//
-// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
-// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
-// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
-// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
-// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
-// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
-// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
-// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
-// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
-// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
-
-#if defined(_MSC_VER ) && !defined(__clang__)
-# define optional_COMPILER_MSVC_VER (_MSC_VER )
-# define optional_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
-#else
-# define optional_COMPILER_MSVC_VER 0
-# define optional_COMPILER_MSVC_VERSION 0
-#endif
-
-#define optional_COMPILER_VERSION( major, minor, patch ) ( 10 * (10 * (major) + (minor) ) + (patch) )
-
-#if defined(__GNUC__) && !defined(__clang__)
-# define optional_COMPILER_GNUC_VERSION optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#else
-# define optional_COMPILER_GNUC_VERSION 0
-#endif
-
-#if defined(__clang__)
-# define optional_COMPILER_CLANG_VERSION optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
-#else
-# define optional_COMPILER_CLANG_VERSION 0
-#endif
-
-#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140 )
-# pragma warning( disable: 4345 ) // initialization behavior changed
-#endif
-
-#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150 )
-# pragma warning( disable: 4814 ) // in C++14 'constexpr' will not imply 'const'
-#endif
-
-// Presence of language and library features:
-
-#define optional_HAVE(FEATURE) ( optional_HAVE_##FEATURE )
-
-#ifdef _HAS_CPP0X
-# define optional_HAS_CPP0X _HAS_CPP0X
-#else
-# define optional_HAS_CPP0X 0
-#endif
-
-// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
-
-#if optional_COMPILER_MSVC_VER >= 1900
-# undef optional_CPP11_OR_GREATER
-# define optional_CPP11_OR_GREATER 1
-#endif
-
-#define optional_CPP11_90 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
-#define optional_CPP11_100 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
-#define optional_CPP11_110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
-#define optional_CPP11_120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
-#define optional_CPP11_140 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
-#define optional_CPP11_141 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
-
-#define optional_CPP14_000 (optional_CPP14_OR_GREATER)
-#define optional_CPP17_000 (optional_CPP17_OR_GREATER)
-
-// Presence of C++11 language features:
-
-#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
-#define optional_HAVE_IS_DEFAULT optional_CPP11_140
-#define optional_HAVE_NOEXCEPT optional_CPP11_140
-#define optional_HAVE_NULLPTR optional_CPP11_100
-#define optional_HAVE_REF_QUALIFIER optional_CPP11_140
-
-// Presence of C++14 language features:
-
-#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
-
-// Presence of C++17 language features:
-
-#define optional_HAVE_NODISCARD optional_CPP17_000
-
-// Presence of C++ library features:
-
-#define optional_HAVE_CONDITIONAL optional_CPP11_120
-#define optional_HAVE_REMOVE_CV optional_CPP11_120
-#define optional_HAVE_TYPE_TRAITS optional_CPP11_90
-
-#define optional_HAVE_TR1_TYPE_TRAITS (!! optional_COMPILER_GNUC_VERSION )
-#define optional_HAVE_TR1_ADD_POINTER (!! optional_COMPILER_GNUC_VERSION )
-
-// C++ feature usage:
-
-#if optional_HAVE( CONSTEXPR_11 )
-# define optional_constexpr constexpr
-#else
-# define optional_constexpr /*constexpr*/
-#endif
-
-#if optional_HAVE( IS_DEFAULT )
-# define optional_is_default = default;
-#else
-# define optional_is_default {}
-#endif
-
-#if optional_HAVE( CONSTEXPR_14 )
-# define optional_constexpr14 constexpr
-#else
-# define optional_constexpr14 /*constexpr*/
-#endif
-
-#if optional_HAVE( NODISCARD )
-# define optional_nodiscard [[nodiscard]]
-#else
-# define optional_nodiscard /*[[nodiscard]]*/
-#endif
-
-#if optional_HAVE( NOEXCEPT )
-# define optional_noexcept noexcept
-#else
-# define optional_noexcept /*noexcept*/
-#endif
-
-#if optional_HAVE( NULLPTR )
-# define optional_nullptr nullptr
-#else
-# define optional_nullptr NULL
-#endif
-
-#if optional_HAVE( REF_QUALIFIER )
-// NOLINTNEXTLINE( bugprone-macro-parentheses )
-# define optional_ref_qual &
-# define optional_refref_qual &&
-#else
-# define optional_ref_qual /*&*/
-# define optional_refref_qual /*&&*/
-#endif
-
-// additional includes:
-
-#if optional_CONFIG_NO_EXCEPTIONS
-// already included: <cassert>
-#else
-# include <stdexcept>
-#endif
-
-#if optional_CPP11_OR_GREATER
-# include <functional>
-#endif
-
-#if optional_HAVE( INITIALIZER_LIST )
-# include <initializer_list>
-#endif
-
-#if optional_HAVE( TYPE_TRAITS )
-# include <type_traits>
-#elif optional_HAVE( TR1_TYPE_TRAITS )
-# include <tr1/type_traits>
-#endif
-
-// Method enabling
-
-#if optional_CPP11_OR_GREATER
-
-#define optional_REQUIRES_0(...) \
- template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
-
-#define optional_REQUIRES_T(...) \
- , typename = typename std::enable_if< (__VA_ARGS__), nonstd::optional_lite::detail::enabler >::type
-
-#define optional_REQUIRES_R(R, ...) \
- typename std::enable_if< (__VA_ARGS__), R>::type
-
-#define optional_REQUIRES_A(...) \
- , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
-
-#endif
-
-//
-// optional:
-//
-
-namespace nonstd { namespace optional_lite {
-
-namespace std11 {
-
-#if optional_CPP11_OR_GREATER
- using std::move;
-#else
- template< typename T > T & move( T & t ) { return t; }
-#endif
-
-#if optional_HAVE( CONDITIONAL )
- using std::conditional;
-#else
- template< bool B, typename T, typename F > struct conditional { typedef T type; };
- template< typename T, typename F > struct conditional<false, T, F> { typedef F type; };
-#endif // optional_HAVE_CONDITIONAL
-
-} // namespace std11
-
-#if optional_CPP11_OR_GREATER
-
-/// type traits C++17:
-
-namespace std17 {
-
-#if optional_CPP17_OR_GREATER
-
-using std::is_swappable;
-using std::is_nothrow_swappable;
-
-#elif optional_CPP11_OR_GREATER
-
-namespace detail {
-
-using std::swap;
-
-struct is_swappable
-{
- template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
- static std::true_type test( int /*unused*/ );
-
- template< typename >
- static std::false_type test(...);
-};
-
-struct is_nothrow_swappable
-{
- // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
-
- template< typename T >
- static constexpr bool satisfies()
- {
- return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
- }
-
- template< typename T >
- static auto test( int /*unused*/ ) -> std::integral_constant<bool, satisfies<T>()>{}
-
- template< typename >
- static auto test(...) -> std::false_type;
-};
-
-} // namespace detail
-
-// is [nothow] swappable:
-
-template< typename T >
-struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
-
-template< typename T >
-struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
-
-#endif // optional_CPP17_OR_GREATER
-
-} // namespace std17
-
-/// type traits C++20:
-
-namespace std20 {
-
-template< typename T >
-struct remove_cvref
-{
- typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
-};
-
-} // namespace std20
-
-#endif // optional_CPP11_OR_GREATER
-
-/// class optional
-
-template< typename T >
-class optional;
-
-namespace detail {
-
-// for optional_REQUIRES_T
-
-#if optional_CPP11_OR_GREATER
-enum class enabler{};
-#endif
-
-// C++11 emulation:
-
-struct nulltype{};
-
-template< typename Head, typename Tail >
-struct typelist
-{
- typedef Head head;
- typedef Tail tail;
-};
-
-#if optional_CONFIG_MAX_ALIGN_HACK
-
-// Max align, use most restricted type for alignment:
-
-#define optional_UNIQUE( name ) optional_UNIQUE2( name, __LINE__ )
-#define optional_UNIQUE2( name, line ) optional_UNIQUE3( name, line )
-#define optional_UNIQUE3( name, line ) name ## line
-
-#define optional_ALIGN_TYPE( type ) \
- type optional_UNIQUE( _t ); struct_t< type > optional_UNIQUE( _st )
-
-template< typename T >
-struct struct_t { T _; };
-
-union max_align_t
-{
- optional_ALIGN_TYPE( char );
- optional_ALIGN_TYPE( short int );
- optional_ALIGN_TYPE( int );
- optional_ALIGN_TYPE( long int );
- optional_ALIGN_TYPE( float );
- optional_ALIGN_TYPE( double );
- optional_ALIGN_TYPE( long double );
- optional_ALIGN_TYPE( char * );
- optional_ALIGN_TYPE( short int * );
- optional_ALIGN_TYPE( int * );
- optional_ALIGN_TYPE( long int * );
- optional_ALIGN_TYPE( float * );
- optional_ALIGN_TYPE( double * );
- optional_ALIGN_TYPE( long double * );
- optional_ALIGN_TYPE( void * );
-
-#ifdef HAVE_LONG_LONG
- optional_ALIGN_TYPE( long long );
-#endif
-
- struct Unknown;
-
- Unknown ( * optional_UNIQUE(_) )( Unknown );
- Unknown * Unknown::* optional_UNIQUE(_);
- Unknown ( Unknown::* optional_UNIQUE(_) )( Unknown );
-
- struct_t< Unknown ( * )( Unknown) > optional_UNIQUE(_);
- struct_t< Unknown * Unknown::* > optional_UNIQUE(_);
- struct_t< Unknown ( Unknown::* )(Unknown) > optional_UNIQUE(_);
-};
-
-#undef optional_UNIQUE
-#undef optional_UNIQUE2
-#undef optional_UNIQUE3
-
-#undef optional_ALIGN_TYPE
-
-#elif defined( optional_CONFIG_ALIGN_AS ) // optional_CONFIG_MAX_ALIGN_HACK
-
-// Use user-specified type for alignment:
-
-#define optional_ALIGN_AS( unused ) \
- optional_CONFIG_ALIGN_AS
-
-#else // optional_CONFIG_MAX_ALIGN_HACK
-
-// Determine POD type to use for alignment:
-
-#define optional_ALIGN_AS( to_align ) \
- typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
-
-template< typename T >
-struct alignment_of;
-
-template< typename T >
-struct alignment_of_hack
-{
- char c;
- T t;
- alignment_of_hack();
-};
-
-template< size_t A, size_t S >
-struct alignment_logic
-{
- enum { value = A < S ? A : S };
-};
-
-template< typename T >
-struct alignment_of
-{
- enum { value = alignment_logic<
- sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
-};
-
-template< typename List, size_t N >
-struct type_of_size
-{
- typedef typename std11::conditional<
- N == sizeof( typename List::head ),
- typename List::head,
- typename type_of_size<typename List::tail, N >::type >::type type;
-};
-
-template< size_t N >
-struct type_of_size< nulltype, N >
-{
- typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
-};
-
-template< typename T>
-struct struct_t { T _; };
-
-#define optional_ALIGN_TYPE( type ) \
- typelist< type , typelist< struct_t< type >
-
-struct Unknown;
-
-typedef
- optional_ALIGN_TYPE( char ),
- optional_ALIGN_TYPE( short ),
- optional_ALIGN_TYPE( int ),
- optional_ALIGN_TYPE( long ),
- optional_ALIGN_TYPE( float ),
- optional_ALIGN_TYPE( double ),
- optional_ALIGN_TYPE( long double ),
-
- optional_ALIGN_TYPE( char *),
- optional_ALIGN_TYPE( short * ),
- optional_ALIGN_TYPE( int * ),
- optional_ALIGN_TYPE( long * ),
- optional_ALIGN_TYPE( float * ),
- optional_ALIGN_TYPE( double * ),
- optional_ALIGN_TYPE( long double * ),
-
- optional_ALIGN_TYPE( Unknown ( * )( Unknown ) ),
- optional_ALIGN_TYPE( Unknown * Unknown::* ),
- optional_ALIGN_TYPE( Unknown ( Unknown::* )( Unknown ) ),
-
- nulltype
- > > > > > > > > > > > > > >
- > > > > > > > > > > > > > >
- > > > > > >
- alignment_types;
-
-#undef optional_ALIGN_TYPE
-
-#endif // optional_CONFIG_MAX_ALIGN_HACK
-
-/// C++03 constructed union to hold value.
-
-template< typename T >
-union storage_t
-{
-//private:
-// template< typename > friend class optional;
-
- typedef T value_type;
-
- storage_t() optional_is_default
-
- explicit storage_t( value_type const & v )
- {
- construct_value( v );
- }
-
- void construct_value( value_type const & v )
- {
- ::new( value_ptr() ) value_type( v );
- }
-
-#if optional_CPP11_OR_GREATER
-
- explicit storage_t( value_type && v )
- {
- construct_value( std::move( v ) );
- }
-
- void construct_value( value_type && v )
- {
- ::new( value_ptr() ) value_type( std::move( v ) );
- }
-
- template< class... Args >
- void emplace( Args&&... args )
- {
- ::new( value_ptr() ) value_type( std::forward<Args>(args)... );
- }
-
- template< class U, class... Args >
- void emplace( std::initializer_list<U> il, Args&&... args )
- {
- ::new( value_ptr() ) value_type( il, std::forward<Args>(args)... );
- }
-
-#endif
-
- void destruct_value()
- {
- value_ptr()->~T();
- }
-
- optional_nodiscard value_type const * value_ptr() const
- {
- return as<value_type>();
- }
-
- value_type * value_ptr()
- {
- return as<value_type>();
- }
-
- optional_nodiscard value_type const & value() const optional_ref_qual
- {
- return * value_ptr();
- }
-
- value_type & value() optional_ref_qual
- {
- return * value_ptr();
- }
-
-#if optional_CPP11_OR_GREATER
-
- optional_nodiscard value_type const && value() const optional_refref_qual
- {
- return std::move( value() );
- }
-
- value_type && value() optional_refref_qual
- {
- return std::move( value() );
- }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
-
- using aligned_storage_t = typename std::aligned_storage< sizeof(value_type), alignof(value_type) >::type;
- aligned_storage_t data;
-
-#elif optional_CONFIG_MAX_ALIGN_HACK
-
- typedef struct { unsigned char data[ sizeof(value_type) ]; } aligned_storage_t;
-
- max_align_t hack;
- aligned_storage_t data;
-
-#else
- typedef optional_ALIGN_AS(value_type) align_as_type;
-
- typedef struct { align_as_type data[ 1 + ( sizeof(value_type) - 1 ) / sizeof(align_as_type) ]; } aligned_storage_t;
- aligned_storage_t data;
-
-# undef optional_ALIGN_AS
-
-#endif // optional_CONFIG_MAX_ALIGN_HACK
-
- optional_nodiscard void * ptr() optional_noexcept
- {
- return &data;
- }
-
- optional_nodiscard void const * ptr() const optional_noexcept
- {
- return &data;
- }
-
- template <typename U>
- optional_nodiscard U * as()
- {
- return reinterpret_cast<U*>( ptr() );
- }
-
- template <typename U>
- optional_nodiscard U const * as() const
- {
- return reinterpret_cast<U const *>( ptr() );
- }
-};
-
-} // namespace detail
-
-/// disengaged state tag
-
-struct nullopt_t
-{
- struct init{};
- explicit optional_constexpr nullopt_t( init /*unused*/ ) optional_noexcept {}
-};
-
-#if optional_HAVE( CONSTEXPR_11 )
-constexpr nullopt_t nullopt{ nullopt_t::init{} };
-#else
-// extra parenthesis to prevent the most vexing parse:
-const nullopt_t nullopt(( nullopt_t::init() ));
-#endif
-
-/// optional access error
-
-#if ! optional_CONFIG_NO_EXCEPTIONS
-
-class bad_optional_access : public std::logic_error
-{
-public:
- explicit bad_optional_access()
- : logic_error( "bad optional access" ) {}
-};
-
-#endif //optional_CONFIG_NO_EXCEPTIONS
-
-/// optional
-
-template< typename T>
-class optional
-{
-private:
- template< typename > friend class optional;
-
- typedef void (optional::*safe_bool)() const;
-
-public:
- typedef T value_type;
-
- // x.x.3.1, constructors
-
- // 1a - default construct
- optional_constexpr optional() optional_noexcept
- : has_value_( false )
- , contained()
- {}
-
- // 1b - construct explicitly empty
- // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
- optional_constexpr optional( nullopt_t /*unused*/ ) optional_noexcept
- : has_value_( false )
- , contained()
- {}
-
- // 2 - copy-construct
- optional_constexpr14 optional( optional const & other
-#if optional_CPP11_OR_GREATER
- optional_REQUIRES_A(
- true || std::is_copy_constructible<T>::value
- )
-#endif
- )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( other.contained.value() );
- }
- }
-
-#if optional_CPP11_OR_GREATER
-
- // 3 (C++11) - move-construct from optional
- optional_constexpr14 optional( optional && other
- optional_REQUIRES_A(
- true || std::is_move_constructible<T>::value
- )
- // NOLINTNEXTLINE( performance-noexcept-move-constructor )
- ) noexcept( std::is_nothrow_move_constructible<T>::value )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( std::move( other.contained.value() ) );
- }
- }
-
- // 4a (C++11) - explicit converting copy-construct from optional
- template< typename U >
- explicit optional( optional<U> const & other
- optional_REQUIRES_A(
- std::is_constructible<T, U const &>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && !std::is_convertible< U const & , T>::value /*=> explicit */
- )
- )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( T{ other.contained.value() } );
- }
- }
-#endif // optional_CPP11_OR_GREATER
-
- // 4b (C++98 and later) - non-explicit converting copy-construct from optional
- template< typename U >
- // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
- optional( optional<U> const & other
-#if optional_CPP11_OR_GREATER
- optional_REQUIRES_A(
- std::is_constructible<T, U const &>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && std::is_convertible< U const & , T>::value /*=> non-explicit */
- )
-#endif // optional_CPP11_OR_GREATER
- )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( other.contained.value() );
- }
- }
-
-#if optional_CPP11_OR_GREATER
-
- // 5a (C++11) - explicit converting move-construct from optional
- template< typename U >
- explicit optional( optional<U> && other
- optional_REQUIRES_A(
- std::is_constructible<T, U &&>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && !std::is_convertible< U &&, T>::value /*=> explicit */
- )
- )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( T{ std::move( other.contained.value() ) } );
- }
- }
-
- // 5a (C++11) - non-explicit converting move-construct from optional
- template< typename U >
- // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
- optional( optional<U> && other
- optional_REQUIRES_A(
- std::is_constructible<T, U &&>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && std::is_convertible< U &&, T>::value /*=> non-explicit */
- )
- )
- : has_value_( other.has_value() )
- {
- if ( other.has_value() )
- {
- contained.construct_value( std::move( other.contained.value() ) );
- }
- }
-
- // 6 (C++11) - in-place construct
- template< typename... Args
- optional_REQUIRES_T(
- std::is_constructible<T, Args&&...>::value
- )
- >
- optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
- : has_value_( true )
- , contained( T( std::forward<Args>(args)...) )
- {}
-
- // 7 (C++11) - in-place construct, initializer-list
- template< typename U, typename... Args
- optional_REQUIRES_T(
- std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
- )
- >
- optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
- : has_value_( true )
- , contained( T( il, std::forward<Args>(args)...) )
- {}
-
- // 8a (C++11) - explicit move construct from value
- template< typename U = value_type >
- optional_constexpr explicit optional( U && value
- optional_REQUIRES_A(
- std::is_constructible<T, U&&>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
- && !std::is_convertible<U&&, T>::value /*=> explicit */
- )
- )
- : has_value_( true )
- , contained( T{ std::forward<U>( value ) } )
- {}
-
- // 8b (C++11) - non-explicit move construct from value
- template< typename U = value_type >
- // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
- optional_constexpr optional( U && value
- optional_REQUIRES_A(
- std::is_constructible<T, U&&>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
- && std::is_convertible<U&&, T>::value /*=> non-explicit */
- )
- )
- : has_value_( true )
- , contained( std::forward<U>( value ) )
- {}
-
-#else // optional_CPP11_OR_GREATER
-
- // 8 (C++98)
- optional( value_type const & value )
- : has_value_( true )
- , contained( value )
- {}
-
-#endif // optional_CPP11_OR_GREATER
-
- // x.x.3.2, destructor
-
- ~optional()
- {
- if ( has_value() )
- {
- contained.destruct_value();
- }
- }
-
- // x.x.3.3, assignment
-
- // 1 (C++98and later) - assign explicitly empty
- optional & operator=( nullopt_t /*unused*/) optional_noexcept
- {
- reset();
- return *this;
- }
-
- // 2 (C++98and later) - copy-assign from optional
-#if optional_CPP11_OR_GREATER
- // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
- optional_REQUIRES_R(
- optional &,
- true
-// std::is_copy_constructible<T>::value
-// && std::is_copy_assignable<T>::value
- )
- operator=( optional const & other )
- noexcept(
- std::is_nothrow_move_assignable<T>::value
- && std::is_nothrow_move_constructible<T>::value
- )
-#else
- optional & operator=( optional const & other )
-#endif
- {
- if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
- else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( *other ); }
- else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = *other; }
- return *this;
- }
-
-#if optional_CPP11_OR_GREATER
-
- // 3 (C++11) - move-assign from optional
- // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
- optional_REQUIRES_R(
- optional &,
- true
-// std::is_move_constructible<T>::value
-// && std::is_move_assignable<T>::value
- )
- operator=( optional && other ) noexcept
- {
- if ( (has_value() == true ) && (other.has_value() == false) ) { reset(); }
- else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std::move( *other ) ); }
- else if ( (has_value() == true ) && (other.has_value() == true ) ) { contained.value() = std::move( *other ); }
- return *this;
- }
-
- // 4 (C++11) - move-assign from value
- template< typename U = T >
- // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
- optional_REQUIRES_R(
- optional &,
- std::is_constructible<T , U>::value
- && std::is_assignable<T&, U>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
- && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
- && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
- )
- operator=( U && value )
- {
- if ( has_value() )
- {
- contained.value() = std::forward<U>( value );
- }
- else
- {
- initialize( T( std::forward<U>( value ) ) );
- }
- return *this;
- }
-
-#else // optional_CPP11_OR_GREATER
-
- // 4 (C++98) - copy-assign from value
- template< typename U /*= T*/ >
- optional & operator=( U const & value )
- {
- if ( has_value() ) contained.value() = value;
- else initialize( T( value ) );
- return *this;
- }
-
-#endif // optional_CPP11_OR_GREATER
-
- // 5 (C++98 and later) - converting copy-assign from optional
- template< typename U >
-#if optional_CPP11_OR_GREATER
- // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
- optional_REQUIRES_R(
- optional&,
- std::is_constructible< T , U const &>::value
- && std::is_assignable< T&, U const &>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && !std::is_assignable< T&, optional<U> & >::value
- && !std::is_assignable< T&, optional<U> && >::value
- && !std::is_assignable< T&, optional<U> const & >::value
- && !std::is_assignable< T&, optional<U> const && >::value
- )
-#else
- optional&
-#endif // optional_CPP11_OR_GREATER
- operator=( optional<U> const & other )
- {
- return *this = optional( other );
- }
-
-#if optional_CPP11_OR_GREATER
-
- // 6 (C++11) - converting move-assign from optional
- template< typename U >
- // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator )
- optional_REQUIRES_R(
- optional&,
- std::is_constructible< T , U>::value
- && std::is_assignable< T&, U>::value
- && !std::is_constructible<T, optional<U> & >::value
- && !std::is_constructible<T, optional<U> && >::value
- && !std::is_constructible<T, optional<U> const & >::value
- && !std::is_constructible<T, optional<U> const && >::value
- && !std::is_convertible< optional<U> & , T>::value
- && !std::is_convertible< optional<U> && , T>::value
- && !std::is_convertible< optional<U> const & , T>::value
- && !std::is_convertible< optional<U> const &&, T>::value
- && !std::is_assignable< T&, optional<U> & >::value
- && !std::is_assignable< T&, optional<U> && >::value
- && !std::is_assignable< T&, optional<U> const & >::value
- && !std::is_assignable< T&, optional<U> const && >::value
- )
- operator=( optional<U> && other )
- {
- return *this = optional( std::move( other ) );
- }
-
- // 7 (C++11) - emplace
- template< typename... Args
- optional_REQUIRES_T(
- std::is_constructible<T, Args&&...>::value
- )
- >
- T& emplace( Args&&... args )
- {
- *this = nullopt;
- contained.emplace( std::forward<Args>(args)... );
- has_value_ = true;
- return contained.value();
- }
-
- // 8 (C++11) - emplace, initializer-list
- template< typename U, typename... Args
- optional_REQUIRES_T(
- std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
- )
- >
- T& emplace( std::initializer_list<U> il, Args&&... args )
- {
- *this = nullopt;
- contained.emplace( il, std::forward<Args>(args)... );
- has_value_ = true;
- return contained.value();
- }
-
-#endif // optional_CPP11_OR_GREATER
-
- // x.x.3.4, swap
-
- void swap( optional & other )
-#if optional_CPP11_OR_GREATER
- noexcept(
- std::is_nothrow_move_constructible<T>::value
- && std17::is_nothrow_swappable<T>::value
- )
-#endif
- {
- using std::swap;
- if ( (has_value() == true ) && (other.has_value() == true ) ) { swap( **this, *other ); }
- else if ( (has_value() == false) && (other.has_value() == true ) ) { initialize( std11::move(*other) ); other.reset(); }
- else if ( (has_value() == true ) && (other.has_value() == false) ) { other.initialize( std11::move(**this) ); reset(); }
- }
-
- // x.x.3.5, observers
-
- optional_constexpr value_type const * operator ->() const
- {
- return assert( has_value() ),
- contained.value_ptr();
- }
-
- optional_constexpr14 value_type * operator ->()
- {
- return assert( has_value() ),
- contained.value_ptr();
- }
-
- optional_constexpr value_type const & operator *() const optional_ref_qual
- {
- return assert( has_value() ),
- contained.value();
- }
-
- optional_constexpr14 value_type & operator *() optional_ref_qual
- {
- return assert( has_value() ),
- contained.value();
- }
-
-#if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
-
- optional_constexpr value_type const && operator *() const optional_refref_qual
- {
- return std::move( **this );
- }
-
- optional_constexpr14 value_type && operator *() optional_refref_qual
- {
- return std::move( **this );
- }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
- optional_constexpr explicit operator bool() const optional_noexcept
- {
- return has_value();
- }
-#else
- optional_constexpr operator safe_bool() const optional_noexcept
- {
- return has_value() ? &optional::this_type_does_not_support_comparisons : 0;
- }
-#endif
-
- // NOLINTNEXTLINE( modernize-use-nodiscard )
- /*optional_nodiscard*/ optional_constexpr bool has_value() const optional_noexcept
- {
- return has_value_;
- }
-
- // NOLINTNEXTLINE( modernize-use-nodiscard )
- /*optional_nodiscard*/ optional_constexpr14 value_type const & value() const optional_ref_qual
- {
-#if optional_CONFIG_NO_EXCEPTIONS
- assert( has_value() );
-#else
- if ( ! has_value() )
- {
- throw bad_optional_access();
- }
-#endif
- return contained.value();
- }
-
- optional_constexpr14 value_type & value() optional_ref_qual
- {
-#if optional_CONFIG_NO_EXCEPTIONS
- assert( has_value() );
-#else
- if ( ! has_value() )
- {
- throw bad_optional_access();
- }
-#endif
- return contained.value();
- }
-
-#if optional_HAVE( REF_QUALIFIER ) && ( !optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490 )
-
- // NOLINTNEXTLINE( modernize-use-nodiscard )
- /*optional_nodiscard*/ optional_constexpr value_type const && value() const optional_refref_qual
- {
- return std::move( value() );
- }
-
- optional_constexpr14 value_type && value() optional_refref_qual
- {
- return std::move( value() );
- }
-
-#endif
-
-#if optional_CPP11_OR_GREATER
-
- template< typename U >
- optional_constexpr value_type value_or( U && v ) const optional_ref_qual
- {
- return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
- }
-
- template< typename U >
- optional_constexpr14 value_type value_or( U && v ) optional_refref_qual
- {
- return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
- }
-
-#else
-
- template< typename U >
- optional_constexpr value_type value_or( U const & v ) const
- {
- return has_value() ? contained.value() : static_cast<value_type>( v );
- }
-
-#endif // optional_CPP11_OR_GREATER
-
- // x.x.3.6, modifiers
-
- void reset() optional_noexcept
- {
- if ( has_value() )
- {
- contained.destruct_value();
- }
-
- has_value_ = false;
- }
-
-private:
- void this_type_does_not_support_comparisons() const {}
-
- template< typename V >
- void initialize( V const & value )
- {
- assert( ! has_value() );
- contained.construct_value( value );
- has_value_ = true;
- }
-
-#if optional_CPP11_OR_GREATER
- template< typename V >
- void initialize( V && value )
- {
- assert( ! has_value() );
- contained.construct_value( std::move( value ) );
- has_value_ = true;
- }
-
-#endif
-
-private:
- bool has_value_;
- detail::storage_t< value_type > contained;
-
-};
-
-// Relational operators
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( optional<T> const & x, optional<U> const & y )
-{
- return bool(x) != bool(y) ? false : !bool( x ) ? true : *x == *y;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( optional<T> const & x, optional<U> const & y )
-{
- return !(x == y);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( optional<T> const & x, optional<U> const & y )
-{
- return (!y) ? false : (!x) ? true : *x < *y;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( optional<T> const & x, optional<U> const & y )
-{
- return (y < x);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( optional<T> const & x, optional<U> const & y )
-{
- return !(y < x);
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( optional<T> const & x, optional<U> const & y )
-{
- return !(x < y);
-}
-
-// Comparison with nullopt
-
-template< typename T >
-inline optional_constexpr bool operator==( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
- return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator==( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
- return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator!=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
- return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator!=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
- return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
-{
- return false;
-}
-
-template< typename T >
-inline optional_constexpr bool operator<( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
- return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<=( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
- return (!x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator<=( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
-{
- return true;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>( optional<T> const & x, nullopt_t /*unused*/ ) optional_noexcept
-{
- return bool(x);
-}
-
-template< typename T >
-inline optional_constexpr bool operator>( nullopt_t /*unused*/, optional<T> const & /*unused*/ ) optional_noexcept
-{
- return false;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>=( optional<T> const & /*unused*/, nullopt_t /*unused*/ ) optional_noexcept
-{
- return true;
-}
-
-template< typename T >
-inline optional_constexpr bool operator>=( nullopt_t /*unused*/, optional<T> const & x ) optional_noexcept
-{
- return (!x);
-}
-
-// Comparison with T
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x == v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator==( U const & v, optional<T> const & x )
-{
- return bool(x) ? v == *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x != v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator!=( U const & v, optional<T> const & x )
-{
- return bool(x) ? v != *x : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x < v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<( U const & v, optional<T> const & x )
-{
- return bool(x) ? v < *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x <= v : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator<=( U const & v, optional<T> const & x )
-{
- return bool(x) ? v <= *x : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x > v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>( U const & v, optional<T> const & x )
-{
- return bool(x) ? v > *x : true;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( optional<T> const & x, U const & v )
-{
- return bool(x) ? *x >= v : false;
-}
-
-template< typename T, typename U >
-inline optional_constexpr bool operator>=( U const & v, optional<T> const & x )
-{
- return bool(x) ? v >= *x : true;
-}
-
-// Specialized algorithms
-
-template< typename T
-#if optional_CPP11_OR_GREATER
- optional_REQUIRES_T(
- std::is_move_constructible<T>::value
- && std17::is_swappable<T>::value )
-#endif
->
-void swap( optional<T> & x, optional<T> & y )
-#if optional_CPP11_OR_GREATER
- noexcept( noexcept( x.swap(y) ) )
-#endif
-{
- x.swap( y );
-}
-
-#if optional_CPP11_OR_GREATER
-
-template< typename T >
-optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
-{
- return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
-}
-
-template< typename T, typename...Args >
-optional_constexpr optional<T> make_optional( Args&&... args )
-{
- return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
-}
-
-template< typename T, typename U, typename... Args >
-optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
-{
- return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
-}
-
-#else
-
-template< typename T >
-optional<T> make_optional( T const & value )
-{
- return optional<T>( value );
-}
-
-#endif // optional_CPP11_OR_GREATER
-
-} // namespace optional_lite
-
-using optional_lite::optional;
-using optional_lite::nullopt_t;
-using optional_lite::nullopt;
-using optional_lite::bad_optional_access;
-
-using optional_lite::make_optional;
-
-} // namespace nonstd
-
-#if optional_CPP11_OR_GREATER
-
-// specialize the std::hash algorithm:
-
-namespace std {
-
-template< class T >
-struct hash< nonstd::optional<T> >
-{
-public:
- std::size_t operator()( nonstd::optional<T> const & v ) const optional_noexcept
- {
- return bool( v ) ? std::hash<T>{}( *v ) : 0;
- }
-};
-
-} //namespace std
-
-#endif // optional_CPP11_OR_GREATER
-
-#if defined(__clang__)
-# pragma clang diagnostic pop
-#elif defined(__GNUC__)
-# pragma GCC diagnostic pop
-#elif defined(_MSC_VER )
-# pragma warning( pop )
-#endif
-
-#endif // optional_USES_STD_OPTIONAL
-
-#endif // NONSTD_OPTIONAL_LITE_HPP
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013,2014,2015, The GROMACS development team.
-# Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
endfunction ()
# TODO Reconsider this, as the CUDA driver API is probably a simpler
-# approach, at least for the build system. See Redmine #2530
+# approach, at least for the build system. See Issue #2530
function (gmx_compile_cpp_as_cuda)
_gmx_add_files_to_property(GMX_LIBGROMACS_GPU_IMPL_SOURCES ${ARGN})
endfunction ()
+# Permit the configuration to disable compiling the many nbnxm kernels
+# and others involved in force calculations. Currently only
+# short-ranged and bonded kernels are disabled this way, but in future
+# others may be appropriate. Thus the cmake option is not specific to
+# nbnxm module.
+option(GMX_USE_SIMD_KERNELS "Whether to compile NBNXM and other SIMD kernels" ON)
+mark_as_advanced(GMX_USE_SIMD_KERNELS)
+
# Add these contents first because linking their tests can take a lot
# of time, so we want lots of parallel work still available after
# linking starts.
gmx_manage_lmfit()
target_link_libraries(libgromacs PRIVATE lmfit)
-# Fix everything found by the latest version of clang that we use in
-# Jenkins testing. This should be updated when we update the latest
-# tested version of clang.
-if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^7\.0")
+# Make sure we fix "everything" found by more recent versions of clang.
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
target_compile_options(libgromacs PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS}>)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# for the binary
if (NOT GMX_BUILD_MDRUN_ONLY OR BUILD_SHARED_LIBS)
install(TARGETS libgromacs
+ COMPONENT libraries
EXPORT libgromacs
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- INCLUDES DESTINATION include
- COMPONENT libraries)
+ INCLUDES DESTINATION include)
+ target_compile_definitions(libgromacs PUBLIC $<INSTALL_INTERFACE:GMX_DOUBLE=${GMX_DOUBLE_VALUE}>)
+ add_library(Gromacs::libgromacs ALIAS libgromacs)
endif()
if (NOT GMX_BUILD_MDRUN_ONLY)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2016,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2016,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
endif()
install(EXPORT libgromacs
FILE ${EXPORT_FILE_NAME}
+ NAMESPACE Gromacs::
DESTINATION ${GMX_INSTALL_CMAKEPKGDIR}
COMPONENT libraries)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013,2014,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] bSet Value of the property to check against.
* \throws APIError if \p module is not compatible with the data.
*/
- void checkModuleProperty(const IAnalysisDataModule& module, DataProperty property, bool bSet) const;
+ static void checkModuleProperty(const IAnalysisDataModule& module, DataProperty property, bool bSet);
/*! \brief
* Checks whether a module is compatible with the data properties.
*
void AnalysisDataModuleManager::Impl::checkModuleProperty(const IAnalysisDataModule& module,
DataProperty property,
- bool bSet) const
+ bool bSet)
{
bool bOk = true;
const int flags = module.flags();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/stringutil.h"
#include "gromacs/utility/unique_cptr.h"
-namespace
-{
-
-//! Enum values for plot formats.
-const char* const g_plotFormats[] = { "none", "xmgrace", "xmgr" };
-
-} // namespace
-
namespace gmx
{
AnalysisDataPlotSettings::AnalysisDataPlotSettings() :
selections_(nullptr),
- timeUnit_(TimeUnit_Default),
- plotFormat_(1)
+ timeUnit_(TimeUnit::Default),
+ plotFormat_(XvgFormat::Xmgrace)
{
}
selections_ = selections;
}
+/*! \brief Names for XvgFormat
+ *
+ * Technically this duplicates a definition in pargs.cpp for legacy
+ * support code, but as the latter will go away and the alternatives
+ * are ugly, the duplication is acceptable. */
+const gmx::EnumerationArray<XvgFormat, const char*> c_xvgFormatNames = { { "xmgrace", "xmgr",
+ "none" } };
void AnalysisDataPlotSettings::initOptions(IOptionsContainer* options)
{
options->addOption(
- EnumIntOption("xvg").enumValue(g_plotFormats).store(&plotFormat_).description("Plot formatting"));
+ EnumOption<XvgFormat>("xvg").enumValue(c_xvgFormatNames).store(&plotFormat_).description("Plot formatting"));
}
}
else
{
- // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
- time_unit_t time_unit = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1);
- xvg_format_t xvg_format = (impl_->settings_.plotFormat() > 0
- ? static_cast<xvg_format_t>(impl_->settings_.plotFormat())
- : exvgNONE);
+ const TimeUnit timeUnit = impl_->settings_.timeUnit();
+ const XvgFormat xvgFormat = impl_->settings_.plotFormat();
gmx_output_env_t* oenv;
- output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0);
+ output_env_init(&oenv, getProgramContext(), timeUnit, FALSE, xvgFormat, 0);
const unique_cptr<gmx_output_env_t, output_env_done> oenvGuard(oenv);
impl_->fp_ = xvgropen(impl_->filename_.c_str(), impl_->title_.c_str(), impl_->xlabel_,
impl_->ylabel_, oenv);
const SelectionCollection* selections = impl_->settings_.selectionCollection();
- if (selections != nullptr && output_env_get_xvg_format(oenv) != exvgNONE)
+ if (selections != nullptr && output_env_get_xvg_format(oenv) != XvgFormat::None)
{
selections->printXvgrInfo(impl_->fp_);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/timeunitmanager.h"
#include "gromacs/utility/classhelpers.h"
+enum class XvgFormat : int;
+
namespace gmx
{
TimeUnit timeUnit() const { return timeUnit_; }
/*! \brief
* Returns the plot format.
- *
- * \todo Use a proper enum.
*/
- int plotFormat() const { return plotFormat_; }
+ XvgFormat plotFormat() const { return plotFormat_; }
/*! \brief
* Set selection collection to print as comments into the output.
private:
const SelectionCollection* selections_;
TimeUnit timeUnit_;
- int plotFormat_;
+ XvgFormat plotFormat_;
};
/*! \brief
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013,2014,2019, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
mock_datamodule.cpp)
gmx_add_unit_test(AnalysisDataUnitTests analysisdata-test
- analysisdata.cpp
- arraydata.cpp
- average.cpp
- histogram.cpp
- lifetime.cpp)
+ CPP_SOURCE_FILES
+ analysisdata.cpp
+ arraydata.cpp
+ average.cpp
+ histogram.cpp
+ lifetime.cpp
+ )
target_link_libraries(analysisdata-test PRIVATE analysisdata-test-shared)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void AnalysisDataTestFixture::presentDataFrame(const AnalysisDataTestInput& input, int row, AnalysisDataHandle handle)
{
const AnalysisDataTestInputFrame& frame = input.frame(row);
- handle.startFrame(row, frame.x(), frame.dx());
+ handle.startFrame(row, frame.x(), AnalysisDataTestInputFrame::dx());
for (int i = 0; i < frame.pointSetCount(); ++i)
{
const AnalysisDataTestInputPointSet& points = frame.pointSet(i);
{
if (points.hasError(j))
{
- handle.setPoint(j + points.firstColumn(), points.y(j), points.error(j), points.present(j));
+ handle.setPoint(j + points.firstColumn(), points.y(j), points.error(j),
+ AnalysisDataTestInputPointSet::present(j));
}
else
{
- handle.setPoint(j + points.firstColumn(), points.y(j), points.present(j));
+ handle.setPoint(j + points.firstColumn(), points.y(j),
+ AnalysisDataTestInputPointSet::present(j));
}
}
if (input.isMultipoint())
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Returns the error in column \p i.
real error(int i) const { return values_[i].error; }
//! Returns whether the value in column \p i is present.
- bool present(int /*i*/) const { return true; }
+ static bool present(int /*i*/) { return true; }
//! Returns an AnalysisDataValue for column \p i.
AnalysisDataValue value(int i) const
{
//! Returns x coordinate for the frame.
real x() const { return x_; }
//! Returns error in the x coordinate for the frame.
- real dx() const { return 0.0; }
+ static real dx() { return 0.0; }
//! Number of individual point sets in the frame.
int pointSetCount() const { return pointSets_.size(); }
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/fileio/mrcdensitymap.h"
#include "gromacs/math/multidimarray.h"
#include "gromacs/mdlib/broadcaststructs.h"
-#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/imdmodule.h"
#include "gromacs/utility/classhelpers.h"
#include "gromacs/utility/exceptions.h"
* allow the MdModuleNotifier to statically distinguish the callback
* function type from other 'int' function callbacks.
*
- * \param[in] pbc MdModuleNotification class that contains a variable
- * that enumerates the periodic boundary condition.
+ * \param[in] pbcType enumerates the periodic boundary condition.
*/
- void setPeriodicBoundaryConditionType(PeriodicBoundaryConditionType pbc)
+ void setPeriodicBoundaryConditionType(const PbcType& pbcType)
{
- pbcType_ = std::make_unique<int>(pbc.pbcType);
+ pbcType_ = std::make_unique<PbcType>(pbcType);
}
//! Get the periodic boundary conditions
- int periodicBoundaryConditionType()
+ PbcType periodicBoundaryConditionType()
{
if (pbcType_ == nullptr)
{
//! The local atom set to act on
std::unique_ptr<LocalAtomSet> localAtomSet_;
//! The type of periodic boundary conditions in the simulation
- std::unique_ptr<int> pbcType_;
+ std::unique_ptr<PbcType> pbcType_;
//! The simulation time step
double simulationTimeStep_ = 1;
*/
class DensityFitting final : public IMDModule
{
+
public:
- /*! \brief Construct the density fitting module.
+ //! Construct the density fitting module.
+ explicit DensityFitting() = default;
+
+ /*! \brief Request to be notified during pre-processing.
*
* \param[in] notifier allows the module to subscribe to notifications from MdModules.
*
* The density fitting code subscribes to these notifications:
- * - setting atom group indices in the densityFittingOptions_ by
- * taking a parmeter const IndexGroupsAndNames &
+ * - setting atom group indices in the densityFittingOptions_ from an
+ * index group string by taking a parmeter const IndexGroupsAndNames &
* - storing its internal parameters in a tpr file by writing to a
* key-value-tree during pre-processing by a function taking a
* KeyValueTreeObjectBuilder as parameter
- * - reading its internal parameters from a key-value-tree during
- * simulation setup by taking a const KeyValueTreeObject & parameter
- * - constructing local atom sets in the simulation parameter setup
- * by taking a LocalAtomSetManager * as parameter
- * - the type of periodic boundary conditions that are used
- * by taking a PeriodicBoundaryConditionType as parameter
- * - the writing of checkpoint data
- * by taking a MdModulesWriteCheckpointData as parameter
- * - the reading of checkpoint data
- * by taking a MdModulesCheckpointReadingDataOnMaster as parameter
- * - the broadcasting of checkpoint data
- * by taking MdModulesCheckpointReadingBroadcast as parameter
*/
- explicit DensityFitting(MdModulesNotifier* notifier)
+ void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) override
{
// Callbacks for several kinds of MdModuleNotification are created
// and subscribed, and will be dispatched correctly at run time
// based on the type of the parameter required by the lambda.
- // Setting atom group indices
+ if (!densityFittingOptions_.active())
+ {
+ return;
+ }
+
+ // Setting the atom group indices from index group string
const auto setFitGroupIndicesFunction = [this](const IndexGroupsAndNames& indexGroupsAndNames) {
densityFittingOptions_.setFitGroupIndices(indexGroupsAndNames);
};
- notifier->notifier_.subscribe(setFitGroupIndicesFunction);
+ notifier->preProcessingNotifications_.subscribe(setFitGroupIndicesFunction);
// Writing internal parameters during pre-processing
const auto writeInternalParametersFunction = [this](KeyValueTreeObjectBuilder treeBuilder) {
densityFittingOptions_.writeInternalParametersToKvt(treeBuilder);
};
- notifier->notifier_.subscribe(writeInternalParametersFunction);
-
- // Reading internal parameters during simulation setup
- const auto readInternalParametersFunction = [this](const KeyValueTreeObject& tree) {
- densityFittingOptions_.readInternalParametersFromKvt(tree);
- };
- notifier->notifier_.subscribe(readInternalParametersFunction);
+ notifier->preProcessingNotifications_.subscribe(writeInternalParametersFunction);
// Checking for consistency with all .mdp options
const auto checkEnergyCaluclationFrequencyFunction =
[this](EnergyCalculationFrequencyErrors* energyCalculationFrequencyErrors) {
densityFittingOptions_.checkEnergyCaluclationFrequency(energyCalculationFrequencyErrors);
};
- notifier->notifier_.subscribe(checkEnergyCaluclationFrequencyFunction);
+ notifier->preProcessingNotifications_.subscribe(checkEnergyCaluclationFrequencyFunction);
+ }
+
+ /*! \brief Request to be notified.
+ * The density fitting code subscribes to these notifications:
+ * - reading its internal parameters from a key-value-tree during
+ * simulation setup by taking a const KeyValueTreeObject & parameter
+ * - constructing local atom sets in the simulation parameter setup
+ * by taking a LocalAtomSetManager * as parameter
+ * - the type of periodic boundary conditions that are used
+ * by taking a PeriodicBoundaryConditionType as parameter
+ * - the writing of checkpoint data
+ * by taking a MdModulesWriteCheckpointData as parameter
+ * - the reading of checkpoint data
+ * by taking a MdModulesCheckpointReadingDataOnMaster as parameter
+ * - the broadcasting of checkpoint data
+ * by taking MdModulesCheckpointReadingBroadcast as parameter
+ */
+ void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) override
+ {
+ if (!densityFittingOptions_.active())
+ {
+ return;
+ }
+
+ // Reading internal parameters during simulation setup
+ const auto readInternalParametersFunction = [this](const KeyValueTreeObject& tree) {
+ densityFittingOptions_.readInternalParametersFromKvt(tree);
+ };
+ notifier->simulationSetupNotifications_.subscribe(readInternalParametersFunction);
// constructing local atom sets during simulation setup
const auto setLocalAtomSetFunction = [this](LocalAtomSetManager* localAtomSetManager) {
this->constructLocalAtomSet(localAtomSetManager);
};
- notifier->notifier_.subscribe(setLocalAtomSetFunction);
+ notifier->simulationSetupNotifications_.subscribe(setLocalAtomSetFunction);
// constructing local atom sets during simulation setup
- const auto setPeriodicBoundaryContionsFunction = [this](PeriodicBoundaryConditionType pbc) {
+ const auto setPeriodicBoundaryContionsFunction = [this](const PbcType& pbc) {
this->densityFittingSimulationParameters_.setPeriodicBoundaryConditionType(pbc);
};
- notifier->notifier_.subscribe(setPeriodicBoundaryContionsFunction);
+ notifier->simulationSetupNotifications_.subscribe(setPeriodicBoundaryContionsFunction);
// setting the simulation time step
const auto setSimulationTimeStepFunction = [this](const SimulationTimeStep& simulationTimeStep) {
this->densityFittingSimulationParameters_.setSimulationTimeStep(simulationTimeStep.delta_t);
};
- notifier->notifier_.subscribe(setSimulationTimeStepFunction);
+ notifier->simulationSetupNotifications_.subscribe(setSimulationTimeStepFunction);
// adding output to energy file
const auto requestEnergyOutput =
[this](MdModulesEnergyOutputToDensityFittingRequestChecker* energyOutputRequest) {
this->setEnergyOutputRequest(energyOutputRequest);
};
- notifier->notifier_.subscribe(requestEnergyOutput);
+ notifier->simulationSetupNotifications_.subscribe(requestEnergyOutput);
// writing checkpoint data
const auto checkpointDataWriting = [this](MdModulesWriteCheckpointData checkpointData) {
this->writeCheckpointData(checkpointData);
};
- notifier->notifier_.subscribe(checkpointDataWriting);
+ notifier->checkpointingNotifications_.subscribe(checkpointDataWriting);
// reading checkpoint data
const auto checkpointDataReading = [this](MdModulesCheckpointReadingDataOnMaster checkpointData) {
this->readCheckpointDataOnMaster(checkpointData);
};
- notifier->notifier_.subscribe(checkpointDataReading);
+ notifier->checkpointingNotifications_.subscribe(checkpointDataReading);
// broadcasting checkpoint data
const auto checkpointDataBroadcast = [this](MdModulesCheckpointReadingBroadcast checkpointData) {
this->broadcastCheckpointData(checkpointData);
};
- notifier->notifier_.subscribe(checkpointDataBroadcast);
+ notifier->checkpointingNotifications_.subscribe(checkpointDataBroadcast);
}
//! From IMDModule
*/
void constructLocalAtomSet(LocalAtomSetManager* localAtomSetManager)
{
- if (densityFittingOptions_.active())
- {
- LocalAtomSet atomSet =
- localAtomSetManager->add(densityFittingOptions_.buildParameters().indices_);
- densityFittingSimulationParameters_.setLocalAtomSet(atomSet);
- }
+ LocalAtomSet atomSet = localAtomSetManager->add(densityFittingOptions_.buildParameters().indices_);
+ densityFittingSimulationParameters_.setLocalAtomSet(atomSet);
}
/*! \brief Request energy output to energy file during simulation.
*/
void writeCheckpointData(MdModulesWriteCheckpointData checkpointWriting)
{
- if (densityFittingOptions_.active())
- {
- const DensityFittingForceProviderState& state = forceProvider_->stateToCheckpoint();
- checkpointWriting.builder_.addValue<std::int64_t>(
- DensityFittingModuleInfo::name_ + "-stepsSinceLastCalculation",
- state.stepsSinceLastCalculation_);
- checkpointWriting.builder_.addValue<real>(
- DensityFittingModuleInfo::name_ + "-adaptiveForceConstantScale",
- state.adaptiveForceConstantScale_);
- KeyValueTreeObjectBuilder exponentialMovingAverageKvtEntry =
- checkpointWriting.builder_.addObject(DensityFittingModuleInfo::name_
- + "-exponentialMovingAverageState");
- exponentialMovingAverageStateAsKeyValueTree(exponentialMovingAverageKvtEntry,
- state.exponentialMovingAverageState_);
- }
+ const DensityFittingForceProviderState& state = forceProvider_->stateToCheckpoint();
+ checkpointWriting.builder_.addValue<std::int64_t>(
+ DensityFittingModuleInfo::name_ + "-stepsSinceLastCalculation",
+ state.stepsSinceLastCalculation_);
+ checkpointWriting.builder_.addValue<real>(
+ DensityFittingModuleInfo::name_ + "-adaptiveForceConstantScale",
+ state.adaptiveForceConstantScale_);
+ KeyValueTreeObjectBuilder exponentialMovingAverageKvtEntry = checkpointWriting.builder_.addObject(
+ DensityFittingModuleInfo::name_ + "-exponentialMovingAverageState");
+ exponentialMovingAverageStateAsKeyValueTree(exponentialMovingAverageKvtEntry,
+ state.exponentialMovingAverageState_);
}
/*! \brief Read the internal parameters from the checkpoint file on master
*/
void readCheckpointDataOnMaster(MdModulesCheckpointReadingDataOnMaster checkpointReading)
{
- if (densityFittingOptions_.active())
+ if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
+ + "-stepsSinceLastCalculation"))
{
- if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
- + "-stepsSinceLastCalculation"))
- {
- densityFittingState_.stepsSinceLastCalculation_ =
- checkpointReading
- .checkpointedData_[DensityFittingModuleInfo::name_
- + "-stepsSinceLastCalculation"]
- .cast<std::int64_t>();
- }
- if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
- + "-adaptiveForceConstantScale"))
- {
- densityFittingState_.adaptiveForceConstantScale_ =
- checkpointReading
- .checkpointedData_[DensityFittingModuleInfo::name_
- + "-adaptiveForceConstantScale"]
- .cast<real>();
- }
- if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
- + "-exponentialMovingAverageState"))
- {
- densityFittingState_.exponentialMovingAverageState_ = exponentialMovingAverageStateFromKeyValueTree(
- checkpointReading
- .checkpointedData_[DensityFittingModuleInfo::name_ + "-exponentialMovingAverageState"]
- .asObject());
- }
+ densityFittingState_.stepsSinceLastCalculation_ =
+ checkpointReading
+ .checkpointedData_[DensityFittingModuleInfo::name_
+ + "-stepsSinceLastCalculation"]
+ .cast<std::int64_t>();
+ }
+ if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
+ + "-adaptiveForceConstantScale"))
+ {
+ densityFittingState_.adaptiveForceConstantScale_ =
+ checkpointReading
+ .checkpointedData_[DensityFittingModuleInfo::name_
+ + "-adaptiveForceConstantScale"]
+ .cast<real>();
+ }
+ if (checkpointReading.checkpointedData_.keyExists(DensityFittingModuleInfo::name_
+ + "-exponentialMovingAverageState"))
+ {
+ densityFittingState_.exponentialMovingAverageState_ = exponentialMovingAverageStateFromKeyValueTree(
+ checkpointReading
+ .checkpointedData_[DensityFittingModuleInfo::name_ + "-exponentialMovingAverageState"]
+ .asObject());
}
}
*/
void broadcastCheckpointData(MdModulesCheckpointReadingBroadcast checkpointBroadcast)
{
- if (densityFittingOptions_.active())
+ if (checkpointBroadcast.isParallelRun_)
{
- if (PAR(&(checkpointBroadcast.cr_)))
- {
- block_bc(&(checkpointBroadcast.cr_), densityFittingState_.stepsSinceLastCalculation_);
- block_bc(&(checkpointBroadcast.cr_), densityFittingState_.adaptiveForceConstantScale_);
- block_bc(&(checkpointBroadcast.cr_), densityFittingState_.exponentialMovingAverageState_);
- }
+ block_bc(checkpointBroadcast.communicator_, densityFittingState_.stepsSinceLastCalculation_);
+ block_bc(checkpointBroadcast.communicator_, densityFittingState_.adaptiveForceConstantScale_);
+ block_bc(checkpointBroadcast.communicator_, densityFittingState_.exponentialMovingAverageState_);
}
}
} // namespace
-std::unique_ptr<IMDModule> DensityFittingModuleInfo::create(MdModulesNotifier* notifier)
+std::unique_ptr<IMDModule> DensityFittingModuleInfo::create()
{
- return std::make_unique<DensityFitting>(notifier);
+ return std::make_unique<DensityFitting>();
}
const std::string DensityFittingModuleInfo::name_ = "density-guided-simulation";
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
#include <string>
+enum class PbcType : int;
+
namespace gmx
{
* Fitting an all-atom structure into an experimental cryo-EM density map is a
* typical application.
*/
- static std::unique_ptr<IMDModule> create(MdModulesNotifier* notifier);
+ static std::unique_ptr<IMDModule> create();
//! The name of the module
static const std::string name_;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief
* The methods that determine how amplitudes are spread on a grid in density guided simulations.
*/
-enum class DensityFittingAmplitudeMethod
+enum class DensityFittingAmplitudeMethod : int
{
Unity, //!< same spread amplitude, unity, for all atoms
Mass, //!< atom mass is the spread amplitude
Count
};
-//! The names of the methods to determine the amplitude of the atoms to be spread on a grid
-const EnumerationArray<DensityFittingAmplitudeMethod, const char* const> c_densityFittingAmplitudeMethodNames = {
- { "unity", "mass", "charge" }
-};
-
class DensityFittingAmplitudeLookupImpl;
/*! \internal \brief Class that translates atom properties into amplitudes.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "densityfittingforceprovider.h"
#include <numeric>
+#include <optional>
-#include "gromacs/compat/optional.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/densityfit.h"
#include "gromacs/math/densityfittingforce.h"
basic_mdspan<const float, dynamicExtents3D> referenceDensity,
const TranslateAndScale& transformationToDensityLattice,
const LocalAtomSet& localAtomSet,
- int pbcType,
+ PbcType pbcType,
double simulationTimeStep,
const DensityFittingForceProviderState& state);
~Impl();
DensityFittingAmplitudeLookup amplitudeLookup_;
TranslateAndScale transformationToDensityLattice_;
RVec referenceDensityCenter_;
- int pbcType_;
+ PbcType pbcType_;
//! Optionally scale the force according to a moving average of the similarity
- compat::optional<ExponentialMovingAverage> expAverageSimilarity_;
+ std::optional<ExponentialMovingAverage> expAverageSimilarity_;
};
DensityFittingForceProvider::Impl::~Impl() = default;
basic_mdspan<const float, dynamicExtents3D> referenceDensity,
const TranslateAndScale& transformationToDensityLattice,
const LocalAtomSet& localAtomSet,
- int pbcType,
+ PbcType pbcType,
double simulationTimeStep,
const DensityFittingForceProviderState& state) :
parameters_(parameters),
amplitudeLookup_(parameters_.amplitudeLookupMethod_),
transformationToDensityLattice_(transformationToDensityLattice),
pbcType_(pbcType),
- expAverageSimilarity_(compat::nullopt)
+ expAverageSimilarity_(std::nullopt)
{
if (parameters_.adaptiveForceScaling_)
{
basic_mdspan<const float, dynamicExtents3D> referenceDensity,
const TranslateAndScale& transformationToDensityLattice,
const LocalAtomSet& localAtomSet,
- int pbcType,
+ PbcType pbcType,
double simulationTimeStep,
const DensityFittingForceProviderState& state) :
impl_(new Impl(parameters, referenceDensity, transformationToDensityLattice, localAtomSet, pbcType, simulationTimeStep, state))
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/iforceprovider.h"
#include "gromacs/utility/classhelpers.h"
+enum class PbcType : int;
+
namespace gmx
{
basic_mdspan<const float, dynamicExtents3D> referenceDensity,
const TranslateAndScale& transformationToDensityLattice,
const LocalAtomSet& localAtomSet,
- int pbcType,
+ PbcType pbcType,
double simulationTimeStep,
const DensityFittingForceProviderState& state);
~DensityFittingForceProvider();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/optionsection.h"
#include "gromacs/selection/indexutil.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/keyvaluetreebuilder.h"
#include "gromacs/utility/keyvaluetreetransform.h"
c_adaptiveForceScalingTimeConstantTag_);
}
+//! Name the methods that may be used to evaluate similarity between densities
+static const EnumerationArray<DensitySimilarityMeasureMethod, const char*> c_densitySimilarityMeasureMethodNames = {
+ { "inner-product", "relative-entropy", "cross-correlation" }
+};
+//! The names of the methods to determine the amplitude of the atoms to be spread on a grid
+static const EnumerationArray<DensityFittingAmplitudeMethod, const char*> c_densityFittingAmplitudeMethodNames = {
+ { "unity", "mass", "charge" }
+};
+
void DensityFittingOptions::buildMdpOutput(KeyValueTreeObjectBuilder* builder) const
{
section.addOption(StringOption(c_groupTag_.c_str()).store(&groupString_));
section.addOption(EnumOption<DensitySimilarityMeasureMethod>(c_similarityMeasureTag_.c_str())
- .enumValue(c_densitySimilarityMeasureMethodNames.m_elements)
+ .enumValue(c_densitySimilarityMeasureMethodNames)
.store(¶meters_.similarityMeasureMethod_));
section.addOption(EnumOption<DensityFittingAmplitudeMethod>(c_amplitudeMethodTag_.c_str())
- .enumValue(c_densityFittingAmplitudeMethodNames.m_elements)
+ .enumValue(c_densityFittingAmplitudeMethodNames)
.store(¶meters_.amplitudeLookupMethod_));
section.addOption(RealOption(c_forceConstantTag_.c_str()).store(¶meters_.forceConstant_));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void calculateForces(const ForceProviderInput& forceProviderInput,
ForceProviderOutput* forceProviderOutput) override;
+ void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
+
private:
//! Return whether or not to apply a field
bool isActive() const;
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(AppliedForcesUnitTest applied_forces-test
- densityfitting.cpp
- densityfittingoptions.cpp
- densityfittingamplitudelookup.cpp
- electricfield.cpp
- )
+ CPP_SOURCE_FILES
+ densityfitting.cpp
+ densityfittingoptions.cpp
+ densityfittingamplitudelookup.cpp
+ electricfield.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
KeyValueTreeObject mdpOptionsTree = mdpValueBuilder_.build();
- densityFittingModule_ = DensityFittingModuleInfo::create(¬ifier_);
+ densityFittingModule_ = DensityFittingModuleInfo::create();
// set up options
Options densityFittingModuleOptions;
protected:
KeyValueTreeBuilder mdpValueBuilder_;
- MdModulesNotifier notifier_;
ForceProviders densityFittingForces_;
std::unique_ptr<IMDModule> densityFittingModule_;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
assignOptionsFromKeyValueTree(&densityFittingModuleOptions, transformedMdpValues.object(), nullptr);
}
- KeyValueTreeObject densityFittingSetActiveAsMdpValues()
+ static KeyValueTreeObject densityFittingSetActiveAsMdpValues()
{
// Prepare MDP inputs
KeyValueTreeBuilder mdpValueBuilder;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class ElectricFieldTest : public ::testing::Test
{
public:
- void test(int dim, real E0, real omega, real t0, real sigma, real expectedValue)
+ static void test(int dim, real E0, real omega, real t0, real sigma, real expectedValue)
{
// Make the electric field module
auto module = createElectricFieldModule();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return (nstout_ > 0 && step % nstout_ == 0);
}
-real Awh::applyBiasForcesAndUpdateBias(int ePBC,
+real Awh::applyBiasForcesAndUpdateBias(PbcType pbcType,
const t_mdatoms& mdatoms,
const matrix box,
gmx::ForceWithVirial* forceWithVirial,
wallcycle_start(wallcycle, ewcAWH);
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
/* During the AWH update the potential can instantaneously jump due to either
an bias update or moving the umbrella. The jumps are kept track of and
}
if (PAR(commRecord_))
{
- gmx_bcast(sizeof(potentialOffset_), &potentialOffset_, commRecord_);
+ gmx_bcast(sizeof(potentialOffset_), &potentialOffset_, commRecord_->mpi_comm_mygroup);
}
for (size_t k = 0; k < biasCoupledToSystem_.size(); k++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_enxframe;
struct t_inputrec;
struct t_mdatoms;
+enum class PbcType : int;
namespace gmx
{
* for this).
*
* \param[in] mdatoms Atom properties.
- * \param[in] ePBC Type of periodic boundary conditions.
+ * \param[in] pbcType Type of periodic boundary conditions.
* \param[in] box Box vectors.
* \param[in,out] forceWithVirial Force and virial buffers, should cover at least the local atoms.
* \param[in] t Time.
* \param[in,out] fplog General output file, normally md.log, can be nullptr.
* \returns the potential energy for the bias.
*/
- real applyBiasForcesAndUpdateBias(int ePBC,
+ real applyBiasForcesAndUpdateBias(PbcType pbcType,
const t_mdatoms& mdatoms,
const matrix box,
gmx::ForceWithVirial* forceWithVirial,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/gmxassert.h"
+#include "biasgrid.h"
#include "biasparams.h"
#include "biasstate.h"
#include "biaswriter.h"
#include "dimparams.h"
-#include "grid.h"
struct gmx_multisim_t;
struct t_commrec;
struct AwhParams;
struct AwhPointStateHistory;
class CorrelationGrid;
-class Grid;
+class BiasGrid;
class GridAxis;
class PointState;
/* Data members. */
private:
const std::vector<DimParams> dimParams_; /**< Parameters for each dimension. */
- const Grid grid_; /**< The multidimensional grid organizing the coordinate point locations. */
+ const BiasGrid grid_; /**< The multidimensional grid organizing the coordinate point locations. */
const BiasParams params_; /**< Constant parameters for the method. */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gmxpre.h"
-#include "grid.h"
+#include "biasgrid.h"
#include <cassert>
#include <cmath>
} // namespace
-double getDeviationFromPointAlongGridAxis(const Grid& grid, int dimIndex, int pointIndex, double value)
+double getDeviationFromPointAlongGridAxis(const BiasGrid& grid, int dimIndex, int pointIndex, double value)
{
double coordValue = grid.point(pointIndex).coordValue[dimIndex];
}
}
-void linearGridindexToMultiDim(const Grid& grid, int indexLinear, awh_ivec indexMulti)
+void linearGridindexToMultiDim(const BiasGrid& grid, int indexLinear, awh_ivec indexMulti)
{
awh_ivec numPointsDim;
const int numDimensions = grid.numDimensions();
} // namespace
-int multiDimGridIndexToLinear(const Grid& grid, const awh_ivec indexMulti)
+int multiDimGridIndexToLinear(const BiasGrid& grid, const awh_ivec indexMulti)
{
return multiDimGridIndexToLinear(grid.axis(), indexMulti);
}
* \param[in] grid The grid.
* \param[in] subgridOrigin Vector locating the subgrid origin relative to the grid origin.
* \param[in] subgridNpoints The number of subgrid points in each dimension.
- * \param[in] point Grid point to get subgrid index for.
+ * \param[in] point BiasGrid point to get subgrid index for.
* \param[in,out] subgridIndex Subgrid multidimensional index.
*/
-void gridToSubgridIndex(const Grid& grid,
- const awh_ivec subgridOrigin,
- const awh_ivec subgridNpoints,
- int point,
- awh_ivec subgridIndex)
+void gridToSubgridIndex(const BiasGrid& grid,
+ const awh_ivec subgridOrigin,
+ const awh_ivec subgridNpoints,
+ int point,
+ awh_ivec subgridIndex)
{
/* Get the subgrid index of the given grid point, for each dimension. */
for (int d = 0; d < grid.numDimensions(); d++)
* \param[in] grid The grid.
* \param[in] subgridOrigin Vector locating the subgrid origin relative to the grid origin.
* \param[in] subgridIndex Subgrid multidimensional index to get grid point index for.
- * \param[in,out] gridIndex Grid point index.
+ * \param[in,out] gridIndex BiasGrid point index.
* \returns true if the transformation was successful.
*/
-bool subgridToGridIndex(const Grid& grid, const awh_ivec subgridOrigin, const awh_ivec subgridIndex, int* gridIndex)
+bool subgridToGridIndex(const BiasGrid& grid, const awh_ivec subgridOrigin, const awh_ivec subgridIndex, int* gridIndex)
{
awh_ivec globalIndexDim;
} // namespace
-bool advancePointInSubgrid(const Grid& grid,
- const awh_ivec subgridOrigin,
- const awh_ivec subgridNumPoints,
- int* gridPointIndex)
+bool advancePointInSubgrid(const BiasGrid& grid,
+ const awh_ivec subgridOrigin,
+ const awh_ivec subgridNumPoints,
+ int* gridPointIndex)
{
/* Initialize the subgrid index to the subgrid origin. */
awh_ivec subgridIndex = { 0 };
* number of points in the axis. For a periodic axis, the distance is chosen
* to be in [0, period), i.e. always positive but not the shortest one.
*
- * \param[in] axis Grid axis.
+ * \param[in] axis BiasGrid axis.
* \param[in] x From value.
* \param[in] x0 To value.
* \returns (x - x0) in number of points.
return true;
}
-bool Grid::covers(const awh_dvec value) const
+bool BiasGrid::covers(const awh_dvec value) const
{
return valueIsInGrid(value, axis());
}
return multiDimGridIndexToLinear(axis, indexMulti);
}
-int Grid::nearestIndex(const awh_dvec value) const
+int BiasGrid::nearestIndex(const awh_dvec value) const
{
return getNearestIndexInGrid(value, axis());
}
* The search space for neighbors is a subgrid with size set by a scope cutoff.
* In general not all point within scope will be valid grid points.
*
- * \param[in] pointIndex Grid point index.
+ * \param[in] pointIndex BiasGrid point index.
* \param[in] grid The grid.
* \param[in,out] neighborIndexArray Array to fill with neighbor indices.
*/
-void setNeighborsOfGridPoint(int pointIndex, const Grid& grid, std::vector<int>* neighborIndexArray)
+void setNeighborsOfGridPoint(int pointIndex, const BiasGrid& grid, std::vector<int>* neighborIndexArray)
{
const int c_maxNeighborsAlongAxis =
- 1 + 2 * static_cast<int>(Grid::c_numPointsPerSigma * Grid::c_scopeCutoff);
+ 1 + 2 * static_cast<int>(BiasGrid::c_numPointsPerSigma * BiasGrid::c_scopeCutoff);
awh_ivec numCandidates = { 0 };
awh_ivec subgridOrigin = { 0 };
} // namespace
-void Grid::initPoints()
+void BiasGrid::initPoints()
{
awh_ivec numPointsDimWork = { 0 };
awh_ivec indexWork = { 0 };
numPointsInPeriod_ = static_cast<int>(std::round(period_ / spacing_));
}
-Grid::Grid(const std::vector<DimParams>& dimParams, const AwhDimParams* awhDimParams)
+BiasGrid::BiasGrid(const std::vector<DimParams>& dimParams, const AwhDimParams* awhDimParams)
{
/* Define the discretization along each dimension */
awh_dvec period;
const double* const* data,
int numDataPoints,
const std::string& dataFilename,
- const Grid& grid,
+ const BiasGrid& grid,
const std::string& correctFormatMessage)
{
/* Transform the data into a grid in order to map each grid point to a data point
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \ingroup module_awh
*/
-#ifndef GMX_AWH_GRID_H
-#define GMX_AWH_GRID_H
+#ifndef GMX_AWH_BIASGRID_H
+#define GMX_AWH_BIASGRID_H
#include <memory>
#include <string>
};
/*! \internal
- * \brief The grid, generally multidimensional and periodic.
+ * \brief The grid for a single bias, generally multidimensional and periodic.
*
* The grid discretizes a multidimensional space with some given resolution.
* Each dimension is represented by an axis which sets the spatial extent,
* point spacing and periodicity of the grid in that direction.
*/
-class Grid
+class BiasGrid
{
private:
/*! \brief Initializes the grid points.
* \param[in] dimParams Dimension parameters including the expected inverse variance of the coordinate living on the grid (determines the grid spacing).
* \param[in] awhDimParams Dimension params from inputrec.
*/
- Grid(const std::vector<DimParams>& dimParams, const AwhDimParams* awhDimParams);
+ BiasGrid(const std::vector<DimParams>& dimParams, const AwhDimParams* awhDimParams);
/*! \brief Returns the number of points in the grid.
*
* \param[in] indexMulti Multidimensional grid point index to convert to a linear one.
* \returns the linear index.
*/
-int multiDimGridIndexToLinear(const Grid& grid, const awh_ivec indexMulti);
+int multiDimGridIndexToLinear(const BiasGrid& grid, const awh_ivec indexMulti);
/*! \brief Convert multidimensional array index to a linear one.
*
* \param[in] indexLinear Linear grid point index to convert to a multidimensional one.
* \param[out] indexMulti The multidimensional index.
*/
-void linearGridindexToMultiDim(const Grid& grid, int indexLinear, awh_ivec indexMulti);
+void linearGridindexToMultiDim(const BiasGrid& grid, int indexLinear, awh_ivec indexMulti);
/*! \brief Convert a linear array index to a multidimensional one.
*
* \param[in,out] gridPointIndex Pointer to the starting/next grid point index.
* \returns true if the grid point was updated.
*/
-bool advancePointInSubgrid(const Grid& grid,
- const awh_ivec subgridOrigin,
- const awh_ivec subgridNpoints,
- int* gridPointIndex);
+bool advancePointInSubgrid(const BiasGrid& grid,
+ const awh_ivec subgridOrigin,
+ const awh_ivec subgridNpoints,
+ int* gridPointIndex);
/*! \brief Maps each point in the grid to a point in the data grid.
*
const double* const* data,
int numDataPoints,
const std::string& dataFilename,
- const Grid& grid,
+ const BiasGrid& grid,
const std::string& correctFormatMessage);
/*! \brief
*
* \param[in] grid The grid.
* \param[in] dimIndex Dimensional index in [0, ndim -1].
- * \param[in] pointIndex Grid point index.
+ * \param[in] pointIndex BiasGrid point index.
* \param[in] value Value along the given dimension.
* \returns the deviation of the given value to the given point.
*/
-double getDeviationFromPointAlongGridAxis(const Grid& grid, int dimIndex, int pointIndex, double value);
+double getDeviationFromPointAlongGridAxis(const BiasGrid& grid, int dimIndex, int pointIndex, double value);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
-#include "grid.h"
+#include "biasgrid.h"
namespace gmx
{
*
* \param[in] awhParams AWH parameters.
* \param[in] dimParams Parameters for the dimensions of the coordinate.
- * \param[in] gridAxis The Grid axes.
+ * \param[in] gridAxis The BiasGrid axes.
* \returns the check interval in steps.
*/
int64_t calcCheckCoveringInterval(const AwhParams& awhParams,
zetaTable = zetaTable1d;
}
else if (xArray.size() == 2)
- {
+ { // NOLINT bugprone-branch-clone
zetaTable = zetaTable2d;
}
else
{
- /* TODO... but this is anyway a rough estimate and > 2 dimensions is not so popular. */
+ /* TODO... but this is anyway a rough estimate and > 2 dimensions is not so popular.
+ * Remove the above NOLINT when addressing this */
zetaTable = zetaTable2d;
}
*
* \param[in] dimParams Parameters for the dimensions of the coordinate.
* \param[in] awhBiasParams Bias parameters.
- * \param[in] gridAxis The Grid axes.
+ * \param[in] gridAxis The BiasGrid axes.
* \param[in] beta 1/(k_B T).
* \param[in] samplingTimestep Sampling frequency of probability weights.
* \returns estimate of initial histogram size.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
-#include "grid.h"
+#include "biasgrid.h"
#include "pointstate.h"
namespace gmx
}
if (commRecord->nnodes > 1)
{
- gmx_bcast(arrayRef.size() * sizeof(T), arrayRef.data(), commRecord);
+ gmx_bcast(arrayRef.size() * sizeof(T), arrayRef.data(), commRecord->mpi_comm_mygroup);
}
}
*/
double biasedLogWeightFromPoint(const std::vector<DimParams>& dimParams,
const std::vector<PointState>& points,
- const Grid& grid,
+ const BiasGrid& grid,
int pointIndex,
double pointBias,
const awh_dvec value)
} // namespace
void BiasState::calcConvolvedPmf(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
std::vector<float>* convolvedPmf) const
{
size_t numPoints = grid.numPoints();
* Puts together a string describing a grid point.
*
* \param[in] grid The grid.
- * \param[in] point Grid point index.
+ * \param[in] point BiasGrid point index.
* \returns a string for the point.
*/
-std::string gridPointValueString(const Grid& grid, int point)
+std::string gridPointValueString(const BiasGrid& grid, int point)
{
std::string pointString;
} // namespace
-int BiasState::warnForHistogramAnomalies(const Grid& grid, int biasIndex, double t, FILE* fplog, int maxNumWarnings) const
+int BiasState::warnForHistogramAnomalies(const BiasGrid& grid, int biasIndex, double t, FILE* fplog, int maxNumWarnings) const
{
GMX_ASSERT(fplog != nullptr, "Warnings can only be issued if there is log file.");
const double maxHistogramRatio = 0.5; /* Tolerance for printing a warning about the histogram ratios */
}
double BiasState::calcUmbrellaForceAndPotential(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
int point,
gmx::ArrayRef<double> force) const
{
}
void BiasState::calcConvolvedForce(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
gmx::ArrayRef<const double> probWeightNeighbor,
gmx::ArrayRef<double> forceWorkBuffer,
gmx::ArrayRef<double> force) const
}
double BiasState::moveUmbrella(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
gmx::ArrayRef<const double> probWeightNeighbor,
gmx::ArrayRef<double> biasForce,
int64_t step,
}
}
-void BiasState::doSkippedUpdatesInNeighborhood(const BiasParams& params, const Grid& grid)
+void BiasState::doSkippedUpdatesInNeighborhood(const BiasParams& params, const BiasGrid& grid)
{
double weightHistScaling;
double logPmfsumScaling;
* last update. \param[in] endUpdatelist The end of the rectangular that has been sampled since
* last update. \param[in,out] updateList Local update list to set (assumed >= npoints long).
*/
-void makeLocalUpdateList(const Grid& grid,
+void makeLocalUpdateList(const BiasGrid& grid,
const std::vector<PointState>& points,
const awh_ivec originUpdatelist,
const awh_ivec endUpdatelist,
} // namespace
-void BiasState::resetLocalUpdateRange(const Grid& grid)
+void BiasState::resetLocalUpdateRange(const BiasGrid& grid)
{
const int gridpointIndex = coordState_.gridpointIndex();
for (int d = 0; d < grid.numDimensions(); d++)
bool BiasState::isSamplingRegionCovered(const BiasParams& params,
const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const t_commrec* commRecord,
const gmx_multisim_t* multiSimComm) const
{
}
void BiasState::updateFreeEnergyAndAddSamplesToHistogram(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const BiasParams& params,
const t_commrec* commRecord,
const gmx_multisim_t* multiSimComm,
}
double BiasState::updateProbabilityWeightsAndConvolvedBias(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
std::vector<double, AlignedAllocator<double>>* weight) const
{
/* Only neighbors of the current coordinate value will have a non-negligible chance of getting sampled */
}
double BiasState::calcConvolvedBias(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const awh_dvec& coordValue) const
{
int point = grid.nearestIndex(coordValue);
return (weightSum > 0) ? std::log(weightSum) : -GMX_FLOAT_MAX;
}
-void BiasState::sampleProbabilityWeights(const Grid& grid, gmx::ArrayRef<const double> probWeightNeighbor)
+void BiasState::sampleProbabilityWeights(const BiasGrid& grid, gmx::ArrayRef<const double> probWeightNeighbor)
{
const std::vector<int>& neighbor = grid.point(coordState_.gridpointIndex()).neighbor;
}
}
-void BiasState::sampleCoordAndPmf(const Grid& grid, gmx::ArrayRef<const double> probWeightNeighbor, double convolvedBias)
+void BiasState::sampleCoordAndPmf(const BiasGrid& grid,
+ gmx::ArrayRef<const double> probWeightNeighbor,
+ double convolvedBias)
{
/* Sampling-based deconvolution extracting the PMF.
* Update the PMF histogram with the current coordinate value.
biasHistory->pointState.resize(points_.size());
}
-void BiasState::updateHistory(AwhBiasHistory* biasHistory, const Grid& grid) const
+void BiasState::updateHistory(AwhBiasHistory* biasHistory, const BiasGrid& grid) const
{
GMX_RELEASE_ASSERT(biasHistory->pointState.size() == points_.size(),
"The AWH history setup does not match the AWH state.");
stateHistory->end_index_updatelist = multiDimGridIndexToLinear(grid, endUpdatelist_);
}
-void BiasState::restoreFromHistory(const AwhBiasHistory& biasHistory, const Grid& grid)
+void BiasState::restoreFromHistory(const AwhBiasHistory& biasHistory, const BiasGrid& grid)
{
const AwhBiasStateHistory& stateHistory = biasHistory.state;
void BiasState::broadcast(const t_commrec* commRecord)
{
- gmx_bcast(sizeof(coordState_), &coordState_, commRecord);
+ gmx_bcast(sizeof(coordState_), &coordState_, commRecord->mpi_comm_mygroup);
- gmx_bcast(points_.size() * sizeof(PointState), points_.data(), commRecord);
+ gmx_bcast(points_.size() * sizeof(PointState), points_.data(), commRecord->mpi_comm_mygroup);
- gmx_bcast(weightSumCovering_.size() * sizeof(double), weightSumCovering_.data(), commRecord);
+ gmx_bcast(weightSumCovering_.size() * sizeof(double), weightSumCovering_.data(),
+ commRecord->mpi_comm_mygroup);
- gmx_bcast(sizeof(histogramSize_), &histogramSize_, commRecord);
+ gmx_bcast(sizeof(histogramSize_), &histogramSize_, commRecord->mpi_comm_mygroup);
}
-void BiasState::setFreeEnergyToConvolvedPmf(const std::vector<DimParams>& dimParams, const Grid& grid)
+void BiasState::setFreeEnergyToConvolvedPmf(const std::vector<DimParams>& dimParams, const BiasGrid& grid)
{
std::vector<float> convolvedPmf;
* \param[in,out] pointState The state of the points in this bias.
*/
static void readUserPmfAndTargetDistribution(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const std::string& filename,
int numBias,
int biasIndex,
int numColumns;
int numRows = read_xvg(filenameModified.c_str(), &data, &numColumns);
- /* Check basic data properties here. Grid takes care of more complicated things. */
+ /* Check basic data properties here. BiasGrid takes care of more complicated things. */
if (numRows <= 0)
{
void BiasState::initGridPointState(const AwhBiasParams& awhBiasParams,
const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const BiasParams& params,
const std::string& filename,
int numBias)
BiasState::BiasState(const AwhBiasParams& awhBiasParams,
double histogramSizeInitial,
const std::vector<DimParams>& dimParams,
- const Grid& grid) :
+ const BiasGrid& grid) :
coordState_(awhBiasParams, dimParams, grid),
points_(grid.numPoints()),
weightSumCovering_(grid.numPoints()),
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* The data members of this class are the state variables of the bias.
* All interaction from the outside happens through the Bias class, which
- * holds important helper classes such as DimParams and Grid.
+ * holds important helper classes such as DimParams and BiasGrid.
* This class holds many methods, but more are const methods that compute
* properties of the state.
*
struct AwhBiasHistory;
struct AwhBiasParams;
class BiasParams;
-class Grid;
+class BiasGrid;
class GridAxis;
class PointState;
BiasState(const AwhBiasParams& awhBiasParams,
double histogramSizeInitial,
const std::vector<DimParams>& dimParams,
- const Grid& grid);
+ const BiasGrid& grid);
/*! \brief
* Restore the bias state from history.
* \param[in] biasHistory Bias history struct.
* \param[in] grid The bias grid.
*/
- void restoreFromHistory(const AwhBiasHistory& biasHistory, const Grid& grid);
+ void restoreFromHistory(const AwhBiasHistory& biasHistory, const BiasGrid& grid);
/*! \brief
* Broadcast the bias state over the MPI ranks in this simulation.
* \param[out] biasHistory Bias history struct.
* \param[in] grid The bias grid.
*/
- void updateHistory(AwhBiasHistory* biasHistory, const Grid& grid) const;
+ void updateHistory(AwhBiasHistory* biasHistory, const BiasGrid& grid) const;
private:
/*! \brief Convolves the given PMF using the given AWH bias.
* \param[in,out] convolvedPmf Array returned will be of the same length as the AWH grid to store the convolved PMF in.
*/
void calcConvolvedPmf(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
std::vector<float>* convolvedPmf) const;
/*! \brief
* \param[in] dimParams The bias dimensions parameters
* \param[in] grid The bias grid.
*/
- void setFreeEnergyToConvolvedPmf(const std::vector<DimParams>& dimParams, const Grid& grid);
+ void setFreeEnergyToConvolvedPmf(const std::vector<DimParams>& dimParams, const BiasGrid& grid);
/*! \brief
* Normalize the PMF histogram.
*/
void initGridPointState(const AwhBiasParams& awhBiasParams,
const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const BiasParams& params,
const std::string& filename,
int numBias);
* \param[in] maxNumWarnings Don't issue more than this number of warnings.
* \returns the number of warnings issued.
*/
- int warnForHistogramAnomalies(const Grid& grid, int biasIndex, double t, FILE* fplog, int maxNumWarnings) const;
+ int warnForHistogramAnomalies(const BiasGrid& grid, int biasIndex, double t, FILE* fplog, int maxNumWarnings) const;
/*! \brief
* Calculates and sets the force the coordinate experiences from an umbrella centered at the given point.
* Returns the umbrella potential.
*/
double calcUmbrellaForceAndPotential(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
int point,
gmx::ArrayRef<double> force) const;
* \param[in,out] force Bias force vector to set.
*/
void calcConvolvedForce(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
gmx::ArrayRef<const double> probWeightNeighbor,
gmx::ArrayRef<double> forceWorkBuffer,
gmx::ArrayRef<double> force) const;
* \returns the new potential value.
*/
double moveUmbrella(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
gmx::ArrayRef<const double> probWeightNeighbor,
gmx::ArrayRef<double> biasForce,
int64_t step,
* \param[in] params The bias parameters.
* \param[in] grid The grid.
*/
- void doSkippedUpdatesInNeighborhood(const BiasParams& params, const Grid& grid);
+ void doSkippedUpdatesInNeighborhood(const BiasParams& params, const BiasGrid& grid);
private:
/*! \brief
*
* \param[in] grid The grid.
*/
- void resetLocalUpdateRange(const Grid& grid);
+ void resetLocalUpdateRange(const BiasGrid& grid);
/*! \brief
* Returns the new size of the reference weight histogram in the initial stage.
*/
bool isSamplingRegionCovered(const BiasParams& params,
const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const t_commrec* commRecord,
const gmx_multisim_t* multiSimComm) const;
* \param[in] grid The bias grid.
* \param[in] coordValue The current reaction coordinate value (there are no limits on allowed values).
*/
- void setCoordValue(const Grid& grid, const awh_dvec coordValue)
+ void setCoordValue(const BiasGrid& grid, const awh_dvec coordValue)
{
coordState_.setCoordValue(grid, coordValue);
}
* \param[in,out] updateList Work space to store a temporary list.
*/
void updateFreeEnergyAndAddSamplesToHistogram(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const BiasParams& params,
const t_commrec* commRecord,
const gmx_multisim_t* ms,
*/
double updateProbabilityWeightsAndConvolvedBias(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
std::vector<double, AlignedAllocator<double>>* weight) const;
/*! \brief
* \param[in] grid The grid.
* \param[in] probWeightNeighbor Probability weights of the neighbors.
*/
- void sampleProbabilityWeights(const Grid& grid, gmx::ArrayRef<const double> probWeightNeighbor);
+ void sampleProbabilityWeights(const BiasGrid& grid, gmx::ArrayRef<const double> probWeightNeighbor);
/*! \brief
* Sample the reaction coordinate and PMF for future updates or analysis.
* \param[in] probWeightNeighbor Probability weights of the neighbors.
* \param[in] convolvedBias The convolved bias.
*/
- void sampleCoordAndPmf(const Grid& grid, gmx::ArrayRef<const double> probWeightNeighbor, double convolvedBias);
+ void sampleCoordAndPmf(const BiasGrid& grid,
+ gmx::ArrayRef<const double> probWeightNeighbor,
+ double convolvedBias);
/*! \brief
* Calculates the convolved bias for a given coordinate value.
*
* \returns the convolved bias >= -GMX_FLOAT_MAX.
*/
double calcConvolvedBias(const std::vector<DimParams>& dimParams,
- const Grid& grid,
+ const BiasGrid& grid,
const awh_dvec& coordValue) const;
/*! \brief
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/smalloc.h"
#include "bias.h"
+#include "biasgrid.h"
#include "correlationgrid.h"
-#include "grid.h"
#include "pointstate.h"
namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
-#include "grid.h"
+#include "biasgrid.h"
namespace gmx
{
CoordState::CoordState(const AwhBiasParams& awhBiasParams,
const std::vector<DimParams>& dimParams,
- const Grid& grid)
+ const BiasGrid& grid)
{
for (size_t d = 0; d < dimParams.size(); d++)
{
} // namespace
-void CoordState::sampleUmbrellaGridpoint(const Grid& grid,
+void CoordState::sampleUmbrellaGridpoint(const BiasGrid& grid,
int gridpointIndex,
gmx::ArrayRef<const double> probWeightNeighbor,
int64_t step,
umbrellaGridpoint_ = neighbor[localIndex];
}
-void CoordState::setCoordValue(const Grid& grid, const awh_dvec coordValue)
+void CoordState::setCoordValue(const BiasGrid& grid, const awh_dvec coordValue)
{
/* We need to check for valid (probable) coordinate values, to give
* a clear error message instead of a low-level assertion failure.
*/
if (!axis.isPeriodic())
{
- const double margin = axis.spacing() * c_marginInSigma / Grid::c_numPointsPerSigma;
+ const double margin = axis.spacing() * c_marginInSigma / BiasGrid::c_numPointsPerSigma;
if (coordValue[dim] < axis.origin() - margin
|| coordValue[dim] > axis.origin() + axis.length() + margin)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct AwhBiasParams;
struct AwhBiasStateHistory;
class BiasParams;
-class Grid;
+class BiasGrid;
/*! \internal \brief Keeps track of the current coordinate value, grid index and umbrella location.
*/
* \param[in] dimParams The dimension Parameters.
* \param[in] grid The grid.
*/
- CoordState(const AwhBiasParams& awhBiasParams, const std::vector<DimParams>& dimParams, const Grid& grid);
+ CoordState(const AwhBiasParams& awhBiasParams,
+ const std::vector<DimParams>& dimParams,
+ const BiasGrid& grid);
/*! \brief
* Sample a new umbrella reference point given the current coordinate value.
* \param[in] indexSeed Second random seed, should be the bias Index.
* \returns the index of the sampled point.
*/
- void sampleUmbrellaGridpoint(const Grid& grid,
+ void sampleUmbrellaGridpoint(const BiasGrid& grid,
int gridpointIndex,
gmx::ArrayRef<const double> probWeightNeighbor,
int64_t step,
* \param[in] grid The grid.
* \param[in] coordValue The new coordinate value.
*/
- void setCoordValue(const Grid& grid, const awh_dvec coordValue);
+ void setCoordValue(const BiasGrid& grid, const awh_dvec coordValue);
/*! \brief Restores the coordinate state from history.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct CorrelationGridHistory;
/*! \internal
- * \brief Grid of local correlation tensors.
+ * \brief BiasGrid of local correlation tensors.
*
* This class provides the means for a bias to interaction with the grid
* of correlation tensors. The grid should have the same number of points
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in,out] inp Input file entries.
* \param[in] prefix Prefix for dimension parameters.
* \param[in,out] dimParams AWH dimensional parameters.
- * \param[in] pull_params Pull parameters.
* \param[in,out] wi Struct for bookeeping warnings.
* \param[in] bComment True if comments should be printed.
*/
static void readDimParams(std::vector<t_inpfile>* inp,
const std::string& prefix,
AwhDimParams* dimParams,
- const pull_params_t* pull_params,
warninp_t wi,
bool bComment)
{
/* The pull coordinate indices start at 1 in the input file, at 0 internally */
dimParams->coordIndex = coordIndexInput - 1;
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Start and end values for each coordinate dimension");
+ }
+
+ opt = prefix + "-start";
+ dimParams->origin = get_ereal(inp, opt, 0., wi);
+
+ opt = prefix + "-end";
+ dimParams->end = get_ereal(inp, opt, 0., wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(
+ inp, "The force constant for this coordinate (kJ/mol/nm^2 or kJ/mol/rad^2)");
+ }
+ opt = prefix + "-force-constant";
+ dimParams->forceConstant = get_ereal(inp, opt, 0, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Estimated diffusion constant (nm^2/ps or rad^2/ps)");
+ }
+ opt = prefix + "-diffusion";
+ dimParams->diffusion = get_ereal(inp, opt, 0, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp,
+ "Diameter that needs to be sampled around a point before it is "
+ "considered covered.");
+ }
+ opt = prefix + "-cover-diameter";
+ dimParams->coverDiameter = get_ereal(inp, opt, 0, wi);
+}
+
+/*! \brief
+ * Check the parameters of an AWH bias dimension.
+ *
+ * \param[in] prefix Prefix for dimension parameters.
+ * \param[in,out] dimParams AWH dimensional parameters.
+ * \param[in] pull_params Pull parameters.
+ * \param[in,out] wi Struct for bookeeping warnings.
+ */
+static void checkDimParams(const std::string& prefix,
+ AwhDimParams* dimParams,
+ const pull_params_t* pull_params,
+ warninp_t wi)
+{
+ std::string opt;
+
/* The pull settings need to be consistent with the AWH settings */
if (!(pull_params->coord[dimParams->coordIndex].eType == epullEXTERNAL))
{
gmx_fatal(FARGS,
"The given AWH coordinate index (%d) is larger than the number of pull "
"coordinates (%d)",
- coordIndexInput, pull_params->ncoord);
+ dimParams->coordIndex + 1, pull_params->ncoord);
}
if (pull_params->coord[dimParams->coordIndex].rate != 0)
{
auto message = formatString(
"Setting pull-coord%d-rate (%g) is incompatible with AWH biasing this coordinate",
- coordIndexInput, pull_params->coord[dimParams->coordIndex].rate);
+ dimParams->coordIndex + 1, pull_params->coord[dimParams->coordIndex].rate);
warning_error(wi, message);
}
- /* Grid params for each axis */
+ /* BiasGrid params for each axis */
int eGeom = pull_params->coord[dimParams->coordIndex].eGeom;
- if (bComment)
- {
- printStringNoNewline(inp, "Start and end values for each coordinate dimension");
- }
-
- opt = prefix + "-start";
- dimParams->origin = get_ereal(inp, opt, 0., wi);
-
- opt = prefix + "-end";
- dimParams->end = get_ereal(inp, opt, 0., wi);
-
if (gmx_within_tol(dimParams->end - dimParams->origin, 0, GMX_REAL_EPS))
{
auto message = formatString(
}
}
- if (bComment)
- {
- printStringNoNewline(
- inp, "The force constant for this coordinate (kJ/mol/nm^2 or kJ/mol/rad^2)");
- }
- opt = prefix + "-force-constant";
- dimParams->forceConstant = get_ereal(inp, opt, 0, wi);
+ opt = prefix + "-force-constant";
if (dimParams->forceConstant <= 0)
{
warning_error(wi, "The force AWH bias force constant should be > 0");
}
- if (bComment)
- {
- printStringNoNewline(inp, "Estimated diffusion constant (nm^2/ps or rad^2/ps)");
- }
- opt = prefix + "-diffusion";
- dimParams->diffusion = get_ereal(inp, opt, 0, wi);
-
+ opt = prefix + "-diffusion";
if (dimParams->diffusion <= 0)
{
const double diffusion_default = 1e-5;
dimParams->diffusion = diffusion_default;
}
- if (bComment)
- {
- printStringNoNewline(inp,
- "Diameter that needs to be sampled around a point before it is "
- "considered covered.");
- }
- opt = prefix + "-cover-diameter";
- dimParams->coverDiameter = get_ereal(inp, opt, 0, wi);
-
+ opt = prefix + "-cover-diameter";
if (dimParams->coverDiameter < 0)
{
gmx_fatal(FARGS, "%s (%g) cannot be negative.", opt.c_str(), dimParams->coverDiameter);
* \param[in,out] inp Input file entries.
* \param[in,out] awhBiasParams AWH dimensional parameters.
* \param[in] prefix Prefix for bias parameters.
- * \param[in] ir Input parameter struct.
* \param[in,out] wi Struct for bookeeping warnings.
* \param[in] bComment True if comments should be printed.
*/
-static void read_bias_params(std::vector<t_inpfile>* inp,
- AwhBiasParams* awhBiasParams,
- const std::string& prefix,
- const t_inputrec* ir,
- warninp_t wi,
- bool bComment)
+static void readBiasParams(std::vector<t_inpfile>* inp,
+ AwhBiasParams* awhBiasParams,
+ const std::string& prefix,
+ warninp_t wi,
+ bool bComment)
{
if (bComment)
{
printStringNoNewline(inp, "Estimated initial PMF error (kJ/mol)");
}
- std::string opt = prefix + "-error-init";
- /* We allow using a default value here without warning (but warn the user if the diffusion constant is not set). */
+ std::string opt = prefix + "-error-init";
awhBiasParams->errorInitial = get_ereal(inp, opt, 10, wi);
- if (awhBiasParams->errorInitial <= 0)
- {
- gmx_fatal(FARGS, "%s needs to be > 0.", opt.c_str());
- }
if (bComment)
{
}
opt = prefix + "-equilibrate-histogram";
awhBiasParams->equilibrateHistogram = (get_eeenum(inp, opt, yesno_names, wi) != 0);
- if (awhBiasParams->equilibrateHistogram && awhBiasParams->eGrowth != eawhgrowthEXP_LINEAR)
- {
- auto message =
- formatString("Option %s will only have an effect for histogram growth type '%s'.",
- opt.c_str(), EAWHGROWTH(eawhgrowthEXP_LINEAR));
- warning(wi, message);
- }
if (bComment)
{
opt = prefix + "-target";
awhBiasParams->eTarget = get_eeenum(inp, opt, eawhtarget_names, wi);
+ if (bComment)
+ {
+ printStringNoNewline(inp,
+ "Boltzmann beta scaling factor for target distribution types "
+ "'boltzmann' and 'boltzmann-local'");
+ }
+ opt = prefix + "-target-beta-scaling";
+ awhBiasParams->targetBetaScaling = get_ereal(inp, opt, 0, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Free energy cutoff value for target distribution type 'cutoff'");
+ }
+ opt = prefix + "-target-cutoff";
+ awhBiasParams->targetCutoff = get_ereal(inp, opt, 0, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Initialize PMF and target with user data: no or yes");
+ }
+ opt = prefix + "-user-data";
+ awhBiasParams->bUserData = get_eeenum(inp, opt, yesno_names, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Group index to share the bias with, 0 means not shared");
+ }
+ opt = prefix + "-share-group";
+ awhBiasParams->shareGroup = get_eint(inp, opt, 0, wi);
+
+ if (bComment)
+ {
+ printStringNoNewline(inp, "Dimensionality of the coordinate");
+ }
+ opt = prefix + "-ndim";
+ awhBiasParams->ndim = get_eint(inp, opt, 0, wi);
+
+ /* Check this before starting to read the AWH dimension parameters. */
+ if (awhBiasParams->ndim <= 0 || awhBiasParams->ndim > c_biasMaxNumDim)
+ {
+ gmx_fatal(FARGS, "%s (%d) needs to be > 0 and at most %d\n", opt.c_str(),
+ awhBiasParams->ndim, c_biasMaxNumDim);
+ }
+ snew(awhBiasParams->dimParams, awhBiasParams->ndim);
+ for (int d = 0; d < awhBiasParams->ndim; d++)
+ {
+ bComment = bComment && d == 0;
+ std::string prefixdim = prefix + formatString("-dim%d", d + 1);
+ readDimParams(inp, prefixdim, &awhBiasParams->dimParams[d], wi, bComment);
+ }
+}
+
+/*! \brief
+ * Check the parameters of an AWH bias.
+ *
+ * \param[in] awhBiasParams AWH dimensional parameters.
+ * \param[in] prefix Prefix for bias parameters.
+ * \param[in] ir Input parameter struct.
+ * \param[in,out] wi Struct for bookeeping warnings.
+ */
+static void checkBiasParams(const AwhBiasParams* awhBiasParams,
+ const std::string& prefix,
+ const t_inputrec* ir,
+ warninp_t wi)
+{
+ std::string opt = prefix + "-error-init";
+ if (awhBiasParams->errorInitial <= 0)
+ {
+ gmx_fatal(FARGS, "%s needs to be > 0.", opt.c_str());
+ }
+
+ opt = prefix + "-equilibrate-histogram";
+ if (awhBiasParams->equilibrateHistogram && awhBiasParams->eGrowth != eawhgrowthEXP_LINEAR)
+ {
+ auto message =
+ formatString("Option %s will only have an effect for histogram growth type '%s'.",
+ opt.c_str(), EAWHGROWTH(eawhgrowthEXP_LINEAR));
+ warning(wi, message);
+ }
+
if ((awhBiasParams->eTarget == eawhtargetLOCALBOLTZMANN)
&& (awhBiasParams->eGrowth == eawhgrowthEXP_LINEAR))
{
warning(wi, message);
}
- if (bComment)
- {
- printStringNoNewline(inp,
- "Boltzmann beta scaling factor for target distribution types "
- "'boltzmann' and 'boltzmann-local'");
- }
- opt = prefix + "-target-beta-scaling";
- awhBiasParams->targetBetaScaling = get_ereal(inp, opt, 0, wi);
-
+ opt = prefix + "-target-beta-scaling";
switch (awhBiasParams->eTarget)
{
case eawhtargetBOLTZMANN:
break;
}
- if (bComment)
- {
- printStringNoNewline(inp, "Free energy cutoff value for target distribution type 'cutoff'");
- }
- opt = prefix + "-target-cutoff";
- awhBiasParams->targetCutoff = get_ereal(inp, opt, 0, wi);
-
+ opt = prefix + "-target-cutoff";
switch (awhBiasParams->eTarget)
{
case eawhtargetCUTOFF:
break;
}
- if (bComment)
- {
- printStringNoNewline(inp, "Initialize PMF and target with user data: no or yes");
- }
- opt = prefix + "-user-data";
- awhBiasParams->bUserData = get_eeenum(inp, opt, yesno_names, wi);
-
- if (bComment)
- {
- printStringNoNewline(inp, "Group index to share the bias with, 0 means not shared");
- }
- opt = prefix + "-share-group";
- awhBiasParams->shareGroup = get_eint(inp, opt, 0, wi);
+ opt = prefix + "-share-group";
if (awhBiasParams->shareGroup < 0)
{
warning_error(wi, "AWH bias share-group should be >= 0");
}
- if (bComment)
- {
- printStringNoNewline(inp, "Dimensionality of the coordinate");
- }
- opt = prefix + "-ndim";
- awhBiasParams->ndim = get_eint(inp, opt, 0, wi);
-
+ opt = prefix + "-ndim";
if (awhBiasParams->ndim <= 0 || awhBiasParams->ndim > c_biasMaxNumDim)
{
gmx_fatal(FARGS, "%s (%d) needs to be > 0 and at most %d\n", opt.c_str(),
"currently only a rough guideline."
" You should verify its usefulness for your system before production runs!");
}
- snew(awhBiasParams->dimParams, awhBiasParams->ndim);
for (int d = 0; d < awhBiasParams->ndim; d++)
{
- bComment = bComment && d == 0;
std::string prefixdim = prefix + formatString("-dim%d", d + 1);
- readDimParams(inp, prefixdim, &awhBiasParams->dimParams[d], ir->pull, wi, bComment);
+ checkDimParams(prefixdim, &awhBiasParams->dimParams[d], ir->pull, wi);
}
/* Check consistencies here that cannot be checked at read time at a lower level. */
}
}
-AwhParams* readAndCheckAwhParams(std::vector<t_inpfile>* inp, const t_inputrec* ir, warninp_t wi)
+AwhParams* readAwhParams(std::vector<t_inpfile>* inp, warninp_t wi)
{
AwhParams* awhParams;
snew(awhParams, 1);
printStringNoNewline(inp, "Data output interval in number of steps");
opt = "awh-nstout";
awhParams->nstOut = get_eint(inp, opt, 100000, wi);
- if (awhParams->nstOut <= 0)
- {
- auto message = formatString("Not writing AWH output with AWH (%s = %d) does not make sense",
- opt.c_str(), awhParams->nstOut);
- warning_error(wi, message);
- }
- /* This restriction can be removed by changing a flag of print_ebin() */
- if (ir->nstenergy == 0 || awhParams->nstOut % ir->nstenergy != 0)
- {
- auto message = formatString("%s (%d) should be a multiple of nstenergy (%d)", opt.c_str(),
- awhParams->nstOut, ir->nstenergy);
- warning_error(wi, message);
- }
printStringNoNewline(inp, "Coordinate sampling interval in number of steps");
opt = "awh-nstsample";
printStringNoNewline(inp, "Free energy and bias update interval in number of samples");
opt = "awh-nsamples-update";
awhParams->numSamplesUpdateFreeEnergy = get_eint(inp, opt, 10, wi);
- if (awhParams->numSamplesUpdateFreeEnergy <= 0)
- {
- warning_error(wi, opt + " needs to be an integer > 0");
- }
printStringNoNewline(
inp, "When true, biases with share-group>0 are shared between multiple simulations");
printStringNoNewline(inp, "The number of independent AWH biases");
opt = "awh-nbias";
awhParams->numBias = get_eint(inp, opt, 1, wi);
+ /* Check this before starting to read the AWH biases. */
if (awhParams->numBias <= 0)
{
gmx_fatal(FARGS, "%s needs to be an integer > 0", opt.c_str());
{
bool bComment = (k == 0);
std::string prefixawh = formatString("awh%d", k + 1);
- read_bias_params(inp, &awhParams->awhBiasParams[k], prefixawh, ir, wi, bComment);
+ readBiasParams(inp, &awhParams->awhBiasParams[k], prefixawh, wi, bComment);
+ }
+
+ return awhParams;
+}
+
+void checkAwhParams(const AwhParams* awhParams, const t_inputrec* ir, warninp_t wi)
+{
+ std::string opt;
+
+ if (!ir->bPull)
+ {
+ gmx_fatal(FARGS, "AWH biasing is only compatible with COM pulling turned on");
+ }
+
+ opt = "awh-nstout";
+ if (awhParams->nstOut <= 0)
+ {
+ auto message = formatString("Not writing AWH output with AWH (%s = %d) does not make sense",
+ opt.c_str(), awhParams->nstOut);
+ warning_error(wi, message);
+ }
+ /* This restriction can be removed by changing a flag of print_ebin() */
+ if (ir->nstenergy == 0 || awhParams->nstOut % ir->nstenergy != 0)
+ {
+ auto message = formatString("%s (%d) should be a multiple of nstenergy (%d)", opt.c_str(),
+ awhParams->nstOut, ir->nstenergy);
+ warning_error(wi, message);
+ }
+
+ opt = "awh-nsamples-update";
+ if (awhParams->numSamplesUpdateFreeEnergy <= 0)
+ {
+ warning_error(wi, opt + " needs to be an integer > 0");
+ }
+
+ for (int k = 0; k < awhParams->numBias; k++)
+ {
+ std::string prefixawh = formatString("awh%d", k + 1);
+ checkBiasParams(&awhParams->awhBiasParams[k], prefixawh, ir, wi);
}
/* Do a final consistency check before returning */
{
warning_error(wi, "With AWH init-step should be 0");
}
-
- return awhParams;
}
/*! \brief
const pull_params_t* pull_params,
pull_t* pull_work,
const matrix box,
- int ePBC,
+ PbcType pbcType,
const tensor& compressibility,
const t_grpopts* inputrecGroupOptions,
warninp_t wi)
}
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (int k = 0; k < awhParams->numBias; k++)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_inputrec;
struct pull_params_t;
struct pull_t;
+enum class PbcType : int;
namespace gmx
{
struct AwhParams;
-/*! \brief Allocate, initialize and check the AWH parameters with values from the input file.
+/*! \brief Allocate and initialize the AWH parameters with values from the input file.
*
* \param[in,out] inp Input file entries.
- * \param[in] inputrec Input parameter struct.
* \param[in,out] wi Struct for bookeeping warnings.
* \returns AWH parameters.
*/
-AwhParams* readAndCheckAwhParams(std::vector<t_inpfile>* inp, const t_inputrec* inputrec, warninp_t wi);
+AwhParams* readAwhParams(std::vector<t_inpfile>* inp, warninp_t wi);
+
+/*! \brief Check the AWH parameters.
+ *
+ * \param[in,out] awhParams The AWH parameters.
+ * \param[in] inputrec Input parameter struct.
+ * \param[in,out] wi Struct for bookeeping warnings.
+ */
+void checkAwhParams(const AwhParams* awhParams, const t_inputrec* inputrec, warninp_t wi);
/*! \brief
* \param[in] pull_params Pull parameters.
* \param[in,out] pull_work Pull working struct to register AWH bias in.
* \param[in] box Box vectors.
- * \param[in] ePBC Periodic boundary conditions enum.
+ * \param[in] pbcType Periodic boundary conditions enum.
* \param[in] compressibility Compressibility matrix for pressure coupling, pass all 0 without pressure coupling
* \param[in] inputrecGroupOptions Parameters for atom groups.
* \param[in,out] wi Struct for bookeeping warnings.
const pull_params_t* pull_params,
pull_t* pull_work,
const matrix box,
- int ePBC,
+ PbcType pbcType,
const tensor& compressibility,
const t_grpopts* inputrecGroupOptions,
warninp_t wi);
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2017, by the GROMACS development team, led by
+# Copyright (c) 2017,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(AwhTest awh-test
- bias.cpp biasstate.cpp grid.cpp)
+ CPP_SOURCE_FILES
+ bias.cpp
+ biasgrid.cpp
+ biasstate.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
#include "gmxpre.h"
-#include "gromacs/awh/grid.h"
+#include "gromacs/awh/biasgrid.h"
#include <cmath>
namespace test
{
-TEST(gridTest, neighborhood)
+TEST(biasGridTest, neighborhood)
{
- constexpr double pointsPerScope = Grid::c_scopeCutoff * Grid::c_numPointsPerSigma;
+ constexpr double pointsPerScope = BiasGrid::c_scopeCutoff * BiasGrid::c_numPointsPerSigma;
GMX_RELEASE_ASSERT(std::abs(pointsPerScope - std::round(pointsPerScope)) > 1e-4,
"If the scope is close to an integer number of points, this test can be "
"unstable due to rounding issues");
dimParams.emplace_back(conversionFactor, 1 / (beta * 0.7 * 0.7), beta);
dimParams.emplace_back(conversionFactor, 1 / (beta * 0.1 * 0.1), beta);
- Grid grid(dimParams, awhDimParams.data());
+ BiasGrid grid(dimParams, awhDimParams.data());
const int numPoints = grid.numPoints();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include "gromacs/awh/grid.h"
+#include "gromacs/awh/biasgrid.h"
#include "gromacs/awh/pointstate.h"
#include "gromacs/math/functions.h"
#include "gromacs/mdtypes/awh_params.h"
std::vector<DimParams> dimParams;
dimParams.emplace_back(1.0, 15.0, params.beta);
dimParams.emplace_back(1.0, 15.0, params.beta);
- Grid grid(dimParams, awhBiasParams.dimParams);
+ BiasGrid grid(dimParams, awhBiasParams.dimParams);
BiasParams biasParams(awhParams, awhBiasParams, dimParams, 1.0, 1.0,
BiasParams::DisableUpdateSkips::no, 1, grid.axis(), 0);
biasState_ = std::make_unique<BiasState>(awhBiasParams, 1.0, dimParams, grid);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
char*** argv);
//! Prints the footer at the end of execution.
- void printThanks(FILE* fp);
+ static void printThanks(FILE* fp);
/*! \brief
* Maps module names to module objects.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \returns The beginning of the option name in \p arg, or NULL if
* \p arg does not look like an option.
*/
- const char* toOptionName(const char* arg) const;
+ static const char* toOptionName(const char* arg);
//! Helper object for assigning the options.
OptionsAssigner assigner_;
assigner_.setAcceptBooleanNoPrefix(true);
}
-const char* CommandLineParser::Impl::toOptionName(const char* arg) const
+const char* CommandLineParser::Impl::toOptionName(const char* arg)
{
// Lone '-' or '--' is not an option.
if (arg[0] != '-' || arg[1] == '\0' || (arg[1] == '-' && arg[2] == '\0'))
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdio>
#include <cstring>
-#include "gromacs/compat/string_view.h"
+#include <string_view>
+
#include "gromacs/fileio/filetypes.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/cstringutil.h"
/*! \brief Return the first position within \c filename of the ".partNNNN"
* interior sequence produced by mdrun -noappend, or npos if not found. */
-size_t findSuffixFromNoAppendPosition(const gmx::compat::string_view filename)
+size_t findSuffixFromNoAppendPosition(const std::string_view filename)
{
size_t partPosition = filename.find(".part");
if ((partPosition != decltype(filename)::npos) && (filename.length() - partPosition >= 10)
} // namespace
-bool hasSuffixFromNoAppend(const gmx::compat::string_view filename)
+bool hasSuffixFromNoAppend(const std::string_view filename)
{
return (findSuffixFromNoAppendPosition(filename) != decltype(filename)::npos);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_COMMANDLINE_FILENM_H
#include <string>
+#include <string_view>
#include <vector>
-#include "gromacs/compat/string_view.h"
#include "gromacs/fileio/filetypes.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
*
* If so, it must match "prefix.partNNNN.extension", for four decimal
* digits N and non-empty prefix and extension. */
-bool hasSuffixFromNoAppend(gmx::compat::string_view filename);
+bool hasSuffixFromNoAppend(std::string_view filename);
/*! \brief
* When we do checkpointing, this routine is called to check for previous
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basenetwork.h"
#include "gromacs/utility/classhelpers.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
namespace
{
-/*! \brief
- * Returns the index of the default xvg format.
+//! Names for XvgFormat
+const gmx::EnumerationArray<XvgFormat, const char*> c_xvgFormatNames = { { "xmgrace", "xmgr",
+ "none" } };
+
+/*! \brief Returns the default xvg format, as modified by GMX_VIEW_XVG
+ * if that environment variable is set.
*
* \ingroup module_commandline
*/
-int getDefaultXvgFormat(gmx::ArrayRef<const char* const> xvgFormats)
+XvgFormat getDefaultXvgFormat()
{
const char* const select = getenv("GMX_VIEW_XVG");
if (select != nullptr)
{
- ArrayRef<const char* const>::const_iterator i =
- std::find(xvgFormats.begin(), xvgFormats.end(), std::string(select));
- if (i != xvgFormats.end())
- {
- return std::distance(xvgFormats.begin(), i);
- }
- else
+ for (XvgFormat c : keysOf(c_xvgFormatNames))
{
- return exvgNONE - 1;
+ if (std::strcmp(select, c_xvgFormatNames[c]) == 0)
+ {
+ return c;
+ }
}
+ return XvgFormat::None;
}
- /* The default is the first option */
- return 0;
+ return XvgFormat::Xmgrace;
}
/*! \brief
return;
case etENUM:
{
+ // TODO This is the only use of LegacyEnumOption. It
+ // exists to support dozens of analysis tools use that
+ // don't make sense to fix without either test coverage or
+ // automated refactoring. No new uses of LegacyEnumOption
+ // should be made.
const int defaultIndex = (pa->u.c[0] != nullptr ? nenum(pa->u.c) - 1 : 0);
- data.optionInfo = options->addOption(EnumIntOption(name)
+ data.optionInfo = options->addOption(LegacyEnumOption<int>(name)
.store(&data.enumIndex)
.defaultValue(defaultIndex)
.enumValueFromNullTerminatedArray(pa->u.c + 1)
const char** bugs,
gmx_output_env_t** oenv)
{
- /* This array should match the order of the enum in oenv.h */
- const char* const xvg_formats[] = { "xmgrace", "xmgr", "none" };
-
// Lambda function to test the (local) Flags parameter against a bit mask.
auto isFlagSet = [Flags](unsigned long bits) { return (Flags & bits) == bits; };
{
double tbegin = 0.0, tend = 0.0, tdelta = 0.0;
bool bBeginTimeSet = false, bEndTimeSet = false, bDtSet = false;
- bool bView = false;
- int xvgFormat = 0;
+ bool bView = false;
gmx::OptionsAdapter adapter(*argc, argv);
gmx::Options options;
gmx::OptionsBehaviorCollection behaviors(&options);
options.addOption(gmx::DoubleOption("dt").store(&tdelta).storeIsSet(&bDtSet).timeValue().description(
"Only use frame when t MOD dt = first time (default unit %t)"));
}
- gmx::TimeUnit timeUnit = gmx::TimeUnit_Default;
+ gmx::TimeUnit timeUnit = gmx::TimeUnit::Default;
if (isFlagSet(PCA_TIME_UNIT))
{
std::shared_ptr<gmx::TimeUnitBehavior> timeUnitBehavior(new gmx::TimeUnitBehavior());
{
bXvgr = bXvgr || (fnm[i].ftp == efXVG);
}
- xvgFormat = gmx::getDefaultXvgFormat(xvg_formats);
+ XvgFormat xvgFormat = gmx::getDefaultXvgFormat();
if (bXvgr)
{
- options.addOption(
- gmx::EnumIntOption("xvg").enumValue(xvg_formats).store(&xvgFormat).description("xvg plot formatting"));
+ options.addOption(gmx::EnumOption<XvgFormat>("xvg")
+ .enumValue(gmx::c_xvgFormatNames)
+ .store(&xvgFormat)
+ .description("xvg plot formatting"));
}
/* Now append the program specific arguments */
/* set program name, command line, and default values for output options */
// NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
- output_env_init(oenv, gmx::getProgramContext(), static_cast<time_unit_t>(timeUnit + 1),
- bView, static_cast<xvg_format_t>(xvgFormat + 1), 0);
+ output_env_init(oenv, gmx::getProgramContext(), timeUnit, bView, xvgFormat, 0);
/* Extract Time info from arguments */
if (bBeginTimeSet)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
endif()
gmx_add_unit_test(CommandLineUnitTests commandline-test
- cmdlinehelpmodule.cpp
- cmdlinehelpwriter.cpp
- cmdlinemodulemanager.cpp
- cmdlinemodulemanagertest.cpp
- cmdlineparser.cpp
- cmdlineprogramcontext.cpp
- filenm.cpp
- pargs.cpp)
+ CPP_SOURCE_FILES
+ cmdlinehelpmodule.cpp
+ cmdlinehelpwriter.cpp
+ cmdlinemodulemanager.cpp
+ cmdlinemodulemanagertest.cpp
+ cmdlineparser.cpp
+ cmdlineprogramcontext.cpp
+ filenm.cpp
+ pargs.cpp
+ )
target_link_libraries(commandline-test PRIVATE onlinehelp-test-shared)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/filenameoption.h"
#include "gromacs/options/options.h"
#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/stringstream.h"
#include "gromacs/utility/textwriter.h"
options.addOption(DoubleOption("time").description("Time option (%t)").timeValue().defaultValue(10.0));
options.addOption(StringOption("string").description("String option").defaultValue("test"));
const char* const enumValues[] = { "no", "opt1", "opt2" };
+ enum class TestEnum : int
+ {
+ No,
+ Opt1,
+ Opt2,
+ Count
+ };
+ const gmx::EnumerationArray<TestEnum, const char*> testEnumNames = { { "no", "opt1", "opt2" } };
+
options.addOption(
StringOption("enum").description("Enum option").enumValue(enumValues).defaultEnumIndex(0));
options.addOption(
- EnumIntOption("ienum").description("Enum option").enumValue(enumValues).defaultValue(1));
+ EnumOption<TestEnum>("ienum").description("Enum option").enumValue(testEnumNames).defaultValue(TestEnum::Opt1));
std::string filename;
options.addOption(FileNameOption("f")
}
//! Enum value for testing.
-enum TestEnum
+enum class TestEnum : int
{
- eFoo,
- eBar
+ Foo,
+ Bar,
+ Count
};
/*
svalues.emplace_back("foo");
options.addOption(StringOption("str").description("String option").storeVector(&svalues).multiValue());
- TestEnum evalue = eBar;
- const char* const allowed[] = { "foo", "bar" };
+ TestEnum evalue = TestEnum::Bar;
+ const gmx::EnumerationArray<TestEnum, const char*> allowed = { { "foo", "bar" } };
options.addOption(
EnumOption<TestEnum>("enum").description("Enum option").enumValue(allowed).store(&evalue));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-// Copyright 2017-2019 by Martin Moene
-//
-// string-view lite, a C++17-like string_view for C++98 and later.
-// For more information see https://github.com/martinmoene/string-view-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-/*! \file
- * \brief Provides C++14-compatible implementation of std::string_view.
- *
- * This implementation is nearly identical to the reference
- * implementation at commit bf5824916b6895ccab0dbc2431520ee3b6d4f27f of
- * https://github.com/martinmoene/string_view-lite.git. The code has not
- * been linted with uncrustify so that any future updates to this
- * active repo can be incorporated easily, and //NOLINT comments and
- * braces around if-expressions added to suppress clang-tidy
- * warnings. Comments referring to GMX note those places where a
- * change has been made. The form of those changes have been made to
- * simplify the contents, while making it easy to import any bug fixes
- * that may appear in the source repository.
- *
- * There is no Doxygen for this code, but it is intended to conform to
- * that of std::string_view, so look in the usual C++17 documentation for
- * std::string_view for that.
- *
- * \todo Remove when requiring C++17, which has a standardized version
- * of std::string_view.
- *
- * \author Paul Bauer <paul.bauer.q@gmail.com>
- * \ingroup module_compat
- * \inpublicapi
- */
-// GMX Make include guard conform to GROMACS standards.
-#ifndef GMX_COMPAT_STRINGVIEW_H
-#define GMX_COMPAT_STRINGVIEW_H
-
-// GMX modification to suppress Doxygen checking
-#ifndef DOXYGEN
-
-#define string_view_lite_MAJOR 1
-#define string_view_lite_MINOR 1
-#define string_view_lite_PATCH 0
-
-#define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
-
-#define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x )
-#define nssv_STRINGIFY_( x ) #x
-
-// string-view lite configuration:
-
-#define nssv_STRING_VIEW_DEFAULT 0
-#define nssv_STRING_VIEW_NONSTD 1
-#define nssv_STRING_VIEW_STD 2
-
-#if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
-# define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
-#endif
-
-#if defined( nssv_CONFIG_SELECT_STD_STRING_VIEW ) || defined( nssv_CONFIG_SELECT_NONSTD_STRING_VIEW )
-# error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...
-#endif
-
-#ifndef nssv_CONFIG_STD_SV_OPERATOR
-# define nssv_CONFIG_STD_SV_OPERATOR 0
-#endif
-
-#ifndef nssv_CONFIG_USR_SV_OPERATOR
-# define nssv_CONFIG_USR_SV_OPERATOR 1
-#endif
-
-#ifdef nssv_CONFIG_CONVERSION_STD_STRING
-# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
-# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
-#endif
-
-#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-# define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
-#endif
-
-#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-# define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
-#endif
-
-// Control presence of exception handling (try and auto discover):
-
-#ifndef nssv_CONFIG_NO_EXCEPTIONS
-# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
-# define nssv_CONFIG_NO_EXCEPTIONS 0
-# else
-# define nssv_CONFIG_NO_EXCEPTIONS 1
-# endif
-#endif
-
-// C++ language version detection (C++20 is speculative):
-// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
-
-#ifndef nssv_CPLUSPLUS
-# if defined(_MSVC_LANG ) && !defined(__clang__)
-# define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
-# else
-# define nssv_CPLUSPLUS __cplusplus
-# endif
-#endif
-
-#define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L )
-#define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L )
-#define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )
-#define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L )
-#define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L )
-#define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202000L )
-
-// use C++17 std::string_view if available and requested:
-
-#if nssv_CPP17_OR_GREATER && defined(__has_include )
-# if __has_include( <string_view> )
-# define nssv_HAVE_STD_STRING_VIEW 1
-# else
-# define nssv_HAVE_STD_STRING_VIEW 0
-# endif
-#else
-# define nssv_HAVE_STD_STRING_VIEW 0
-#endif
-
-#define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) )
-
-#define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )
-#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
-
-//
-// Use C++17 std::string_view:
-//
-
-#if nssv_USES_STD_STRING_VIEW
-
-#include <string_view>
-
-// Extensions for std::string:
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-namespace nonstd {
-
-template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
-std::basic_string<CharT, Traits, Allocator>
-to_string( std::basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
-{
- return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
-}
-
-template< class CharT, class Traits, class Allocator >
-std::basic_string_view<CharT, Traits>
-to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
-{
- return std::basic_string_view<CharT, Traits>( s.data(), s.size() );
-}
-
-// Literal operators sv and _sv:
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-
-using namespace std::literals::string_view_literals;
-
-#endif
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-
-inline namespace literals {
-inline namespace string_view_literals {
-
-
-constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1)
-{
- return std::string_view{ str, len };
-}
-
-constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2)
-{
- return std::u16string_view{ str, len };
-}
-
-constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3)
-{
- return std::u32string_view{ str, len };
-}
-
-constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4)
-{
- return std::wstring_view{ str, len };
-}
-
-}} // namespace literals::string_view_literals
-
-#endif // nssv_CONFIG_USR_SV_OPERATOR
-
-} // namespace nonstd
-
-#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-namespace nonstd {
-
-using std::string_view;
-using std::wstring_view;
-using std::u16string_view;
-using std::u32string_view;
-using std::basic_string_view;
-
-// literal "sv" and "_sv", see above
-
-using std::operator==;
-using std::operator!=;
-using std::operator<;
-using std::operator<=;
-using std::operator>;
-using std::operator>=;
-
-using std::operator<<;
-
-} // namespace nonstd
-
-#else // nssv_HAVE_STD_STRING_VIEW
-
-//
-// Before C++17: use string_view lite:
-//
-
-// Compiler versions:
-//
-// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
-// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
-// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
-// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
-// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
-// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
-// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
-// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
-// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
-// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
-
-#if defined(_MSC_VER ) && !defined(__clang__)
-# define nssv_COMPILER_MSVC_VER (_MSC_VER )
-# define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
-#else
-# define nssv_COMPILER_MSVC_VER 0
-# define nssv_COMPILER_MSVC_VERSION 0
-#endif
-
-#define nssv_COMPILER_VERSION( major, minor, patch ) (10 * ( 10 * (major) + (minor)) + (patch))
-
-#if defined(__clang__)
-# define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
-#else
-# define nssv_COMPILER_CLANG_VERSION 0
-#endif
-
-#if defined(__GNUC__) && !defined(__clang__)
-# define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#else
-# define nssv_COMPILER_GNUC_VERSION 0
-#endif
-
-// half-open range [lo..hi):
-#define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
-
-// Presence of language and library features:
-
-#ifdef _HAS_CPP0X
-# define nssv_HAS_CPP0X _HAS_CPP0X
-#else
-# define nssv_HAS_CPP0X 0
-#endif
-
-// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
-
-#if nssv_COMPILER_MSVC_VER >= 1900
-# undef nssv_CPP11_OR_GREATER
-# define nssv_CPP11_OR_GREATER 1
-#endif
-
-#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
-#define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
-#define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
-#define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
-#define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
-#define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
-
-#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
-#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
-
-// Presence of C++11 language features:
-
-#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
-#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
-#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
-#define nssv_HAVE_NOEXCEPT nssv_CPP11_140
-#define nssv_HAVE_NULLPTR nssv_CPP11_100
-#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
-#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
-#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
-#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
-#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
-
-// GMX fixed definitions
-#if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
-# define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
-#endif
-
-// Presence of C++14 language features:
-
-#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
-
-// Presence of C++17 language features:
-
-#define nssv_HAVE_NODISCARD nssv_CPP17_000
-
-// Presence of C++ library features:
-
-#define nssv_HAVE_STD_HASH nssv_CPP11_120
-
-// C++ feature usage:
-
-#if nssv_HAVE_CONSTEXPR_11
-# define nssv_constexpr constexpr
-#else
-# define nssv_constexpr /*constexpr*/
-#endif
-
-#if nssv_HAVE_CONSTEXPR_14
-# define nssv_constexpr14 constexpr
-#else
-# define nssv_constexpr14 /*constexpr*/
-#endif
-
-#if nssv_HAVE_EXPLICIT_CONVERSION
-# define nssv_explicit explicit
-#else
-# define nssv_explicit /*explicit*/
-#endif
-
-#if nssv_HAVE_INLINE_NAMESPACE
-# define nssv_inline_ns inline
-#else
-# define nssv_inline_ns /*inline*/
-#endif
-
-#if nssv_HAVE_NOEXCEPT
-# define nssv_noexcept noexcept
-#else
-# define nssv_noexcept /*noexcept*/
-#endif
-
-//#if nssv_HAVE_REF_QUALIFIER
-//# define nssv_ref_qual &
-//# define nssv_refref_qual &&
-//#else
-//# define nssv_ref_qual /*&*/
-//# define nssv_refref_qual /*&&*/
-//#endif
-
-#if nssv_HAVE_NULLPTR
-# define nssv_nullptr nullptr
-#else
-# define nssv_nullptr NULL
-#endif
-
-#if nssv_HAVE_NODISCARD
-# define nssv_nodiscard [[nodiscard]]
-#else
-# define nssv_nodiscard /*[[nodiscard]]*/
-#endif
-
-// Additional includes:
-
-#include <algorithm>
-#include <cassert>
-#include <iterator>
-#include <limits>
-#include <ostream>
-#include <string> // std::char_traits<>
-
-#if ! nssv_CONFIG_NO_EXCEPTIONS
-# include <stdexcept>
-#endif
-
-#if nssv_CPP11_OR_GREATER
-# include <type_traits>
-#endif
-
-// Clang, GNUC, MSVC warning suppression macros:
-
-#if defined(__clang__)
-# pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wuser-defined-literals"
-#elif defined(__GNUC__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wliteral-suffix"
-#endif // __clang__
-
-#if nssv_COMPILER_MSVC_VERSION >= 140
-# define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
-# define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
-# define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
-#else
-# define nssv_SUPPRESS_MSGSL_WARNING(expr)
-# define nssv_SUPPRESS_MSVC_WARNING(code, descr)
-# define nssv_DISABLE_MSVC_WARNINGS(codes)
-#endif
-
-#if defined(__clang__)
-# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
-#elif defined(__GNUC__)
-# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
-#elif nssv_COMPILER_MSVC_VERSION >= 140
-# define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
-#else
-# define nssv_RESTORE_WARNINGS()
-#endif
-
-// Suppress the following MSVC (GSL) warnings:
-// - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
-// start with an underscore are reserved
-// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
-// use brace initialization, gsl::narrow_cast or gsl::narow
-// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
-
-nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
-//nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
-//nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
-
-namespace nonstd { namespace sv_lite {
-
-template
-<
- class CharT,
- class Traits = std::char_traits<CharT>
->
-class basic_string_view;
-
-//
-// basic_string_view:
-//
-
-template
-<
- class CharT,
- class Traits /* = std::char_traits<CharT> */
->
-class basic_string_view
-{
-public:
- // Member types:
-
- typedef Traits traits_type;
- typedef CharT value_type;
-
- typedef CharT * pointer;
- typedef CharT const * const_pointer;
- typedef CharT & reference;
- typedef CharT const & const_reference;
-
- typedef const_pointer iterator;
- typedef const_pointer const_iterator;
- typedef std::reverse_iterator< const_iterator > reverse_iterator;
- typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
-
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
-
- // 24.4.2.1 Construction and assignment:
-
- nssv_constexpr basic_string_view() nssv_noexcept
- : data_( nssv_nullptr )
- , size_( 0 )
- {}
-
-#if nssv_CPP11_OR_GREATER
- nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;
-#else
- nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept
- : data_( other.data_)
- , size_( other.size_)
- {}
-#endif
-
- nssv_constexpr basic_string_view( CharT const * s, size_type count )
- : data_( s )
- , size_( count )
- {}
-
- nssv_constexpr basic_string_view( CharT const * s)
- : data_( s )
- , size_( Traits::length(s) )
- {}
-
- // Assignment:
-
-#if nssv_CPP11_OR_GREATER
- nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;
-#else
- nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept
- {
- data_ = other.data_;
- size_ = other.size_;
- return *this;
- }
-#endif
-
- // 24.4.2.2 Iterator support:
-
- nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
- nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
-
- nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
- nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
-
- nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); }
- nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); }
-
- nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
- nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
-
- // 24.4.2.3 Capacity:
-
- nssv_constexpr size_type size() const nssv_noexcept { return size_; }
- nssv_constexpr size_type length() const nssv_noexcept { return size_; }
- nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }
-
- // since C++20
- nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept
- {
- return 0 == size_;
- }
-
- // 24.4.2.4 Element access:
-
- nssv_constexpr const_reference operator[]( size_type pos ) const
- {
- return data_at( pos );
- }
-
- nssv_constexpr14 const_reference at( size_type pos ) const
- {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert( pos < size() );
-#else
- if ( pos >= size() )
- {
- throw std::out_of_range("nonst::string_view::at()");
- }
-#endif
- return data_at( pos );
- }
-
- nssv_constexpr const_reference front() const { return data_at( 0 ); }
- nssv_constexpr const_reference back() const { return data_at( size() - 1 ); }
-
- nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
-
- // 24.4.2.5 Modifiers:
-
- nssv_constexpr14 void remove_prefix( size_type n )
- {
- assert( n <= size() );
- data_ += n;
- size_ -= n;
- }
-
- nssv_constexpr14 void remove_suffix( size_type n )
- {
- assert( n <= size() );
- size_ -= n;
- }
-
- nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
- {
- using std::swap;
- swap( data_, other.data_ );
- swap( size_, other.size_ );
- }
-
- // 24.4.2.6 String operations:
-
- size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const
- {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert( pos <= size() );
-#else
- if ( pos > size() )
- {
- throw std::out_of_range("nonst::string_view::copy()");
- }
-#endif
- const size_type rlen = (std::min)( n, size() - pos );
-
- (void) Traits::copy( dest, data() + pos, rlen );
-
- return rlen;
- }
-
- nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const
- {
-#if nssv_CONFIG_NO_EXCEPTIONS
- assert( pos <= size() );
-#else
- if ( pos > size() )
- {
- throw std::out_of_range("nonst::string_view::substr()");
- }
-#endif
- return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
- }
-
- // compare(), 6x:
-
- nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
- {
- if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
- {
- return result;
- }
-
- return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
- }
-
- nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)
- {
- return substr( pos1, n1 ).compare( other );
- }
-
- nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)
- {
- return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );
- }
-
- nssv_constexpr int compare( CharT const * s ) const // (4)
- {
- return compare( basic_string_view( s ) );
- }
-
- nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)
- {
- return substr( pos1, n1 ).compare( basic_string_view( s ) );
- }
-
- nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)
- {
- return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
- }
-
- // 24.4.2.7 Searching:
-
- // starts_with(), 3x, since C++20:
-
- nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1)
- {
- return size() >= v.size() && compare( 0, v.size(), v ) == 0;
- }
-
- nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2)
- {
- return starts_with( basic_string_view( &c, 1 ) );
- }
-
- nssv_constexpr bool starts_with( CharT const * s ) const // (3)
- {
- return starts_with( basic_string_view( s ) );
- }
-
- // ends_with(), 3x, since C++20:
-
- nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1)
- {
- return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;
- }
-
- nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2)
- {
- return ends_with( basic_string_view( &c, 1 ) );
- }
-
- nssv_constexpr bool ends_with( CharT const * s ) const // (3)
- {
- return ends_with( basic_string_view( s ) );
- }
-
- // find(), 4x:
-
- nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
- {
- return assert( v.size() == 0 || v.data() != nssv_nullptr )
- , pos >= size()
- ? npos
- : to_pos( std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
- }
-
- nssv_constexpr14 size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
- {
- return find( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr14 size_type find( CharT const * s, size_type pos, size_type n ) const // (3)
- {
- return find( basic_string_view( s, n ), pos );
- }
-
- nssv_constexpr14 size_type find( CharT const * s, size_type pos = 0 ) const // (4)
- {
- return find( basic_string_view( s ), pos );
- }
-
- // rfind(), 4x:
-
- nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
- {
- if ( size() < v.size() )
- {
- return npos;
- }
-
- if ( v.empty() )
- {
- return (std::min)( size(), pos );
- }
-
- const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
- const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
-
- return result != last ? size_type( result - cbegin() ) : npos;
- }
-
- nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
- {
- return rfind( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3)
- {
- return rfind( basic_string_view( s, n ), pos );
- }
-
- nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4)
- {
- return rfind( basic_string_view( s ), pos );
- }
-
- // find_first_of(), 4x:
-
- nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
- {
- return pos >= size()
- ? npos
- : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
- }
-
- nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
- {
- return find_first_of( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3)
- {
- return find_first_of( basic_string_view( s, n ), pos );
- }
-
- nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4)
- {
- return find_first_of( basic_string_view( s ), pos );
- }
-
- // find_last_of(), 4x:
-
- nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
- {
- return empty()
- ? npos
- : pos >= size()
- ? find_last_of( v, size() - 1 )
- : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );
- }
-
- nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
- {
- return find_last_of( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3)
- {
- return find_last_of( basic_string_view( s, count ), pos );
- }
-
- nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4)
- {
- return find_last_of( basic_string_view( s ), pos );
- }
-
- // find_first_not_of(), 4x:
-
- nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
- {
- return pos >= size()
- ? npos
- : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );
- }
-
- nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
- {
- return find_first_not_of( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
- {
- return find_first_not_of( basic_string_view( s, count ), pos );
- }
-
- nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4)
- {
- return find_first_not_of( basic_string_view( s ), pos );
- }
-
- // find_last_not_of(), 4x:
-
- nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
- {
- return empty()
- ? npos
- : pos >= size()
- ? find_last_not_of( v, size() - 1 )
- : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );
- }
-
- nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
- {
- return find_last_not_of( basic_string_view( &c, 1 ), pos );
- }
-
- nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
- {
- return find_last_not_of( basic_string_view( s, count ), pos );
- }
-
- nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4)
- {
- return find_last_not_of( basic_string_view( s ), pos );
- }
-
- // Constants:
-
-#if nssv_CPP17_OR_GREATER
- static nssv_constexpr size_type npos = size_type(-1);
-#elif nssv_CPP11_OR_GREATER
- enum : size_type { npos = size_type(-1) };
-#else
- enum { npos = size_type(-1) };
-#endif
-
-private:
- struct not_in_view
- {
- const basic_string_view v;
-
- nssv_constexpr not_in_view( basic_string_view v ) : v( v ) {}
-
- nssv_constexpr bool operator()( CharT c ) const
- {
- return npos == v.find_first_of( c );
- }
- };
-
- nssv_constexpr size_type to_pos( const_iterator it ) const
- {
- return it == cend() ? npos : size_type( it - cbegin() );
- }
-
- nssv_constexpr size_type to_pos( const_reverse_iterator it ) const
- {
- return it == crend() ? npos : size_type( crend() - it - 1 );
- }
-
- nssv_constexpr const_reference data_at( size_type pos ) const
- {
-#if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )
- return data_[pos];
-#else
- return assert( pos < size() ), data_[pos];
-#endif
- }
-
-private:
- const_pointer data_;
- size_type size_;
-
-public:
-#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-
- template< class Allocator >
- basic_string_view( std::basic_string<CharT, Traits, Allocator> const & s ) nssv_noexcept
- : data_( s.data() )
- , size_( s.size() )
- {}
-
-#if nssv_HAVE_EXPLICIT_CONVERSION
-
- template< class Allocator >
- explicit operator std::basic_string<CharT, Traits, Allocator>() const
- {
- return to_string( Allocator() );
- }
-
-#endif // nssv_HAVE_EXPLICIT_CONVERSION
-
-#if nssv_CPP11_OR_GREATER
-
- template< class Allocator = std::allocator<CharT> >
- std::basic_string<CharT, Traits, Allocator>
- to_string( Allocator const & a = Allocator() ) const
- {
- return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
- }
-
-#else
-
- std::basic_string<CharT, Traits>
- to_string() const
- {
- return std::basic_string<CharT, Traits>( begin(), end() );
- }
-
- template< class Allocator >
- std::basic_string<CharT, Traits, Allocator>
- to_string( Allocator const & a ) const
- {
- return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
- }
-
-#endif // nssv_CPP11_OR_GREATER
-
-#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-};
-
-//
-// Non-member functions:
-//
-
-// 24.4.3 Non-member comparison functions:
-// lexicographically compare two string views (function template):
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator== (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) == 0 ; }
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator!= (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) != 0 ; }
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator< (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) < 0 ; }
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator<= (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) <= 0 ; }
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator> (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) > 0 ; }
-
-template< class CharT, class Traits >
-nssv_constexpr bool operator>= (
- basic_string_view <CharT, Traits> lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) >= 0 ; }
-
-// Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
-// Implementations shall provide sufficient additional overloads marked
-// constexpr and noexcept so that an object t with an implicit conversion
-// to S can be compared according to Table 67.
-
-#if nssv_CPP11_OR_GREATER && ! nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
-
-#define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
-
-#if nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 140, 150 )
-# define nssv_MSVC_ORDER(x) , int=x
-#else
-# define nssv_MSVC_ORDER(x) /*, int=x*/
-#endif
-
-// ==
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator==(
- basic_string_view <CharT, Traits> lhs,
- nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) == 0; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator==(
- nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
- basic_string_view <CharT, Traits> rhs ) nssv_noexcept
-{ return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
-
-// !=
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator!= (
- basic_string_view < CharT, Traits > lhs,
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
-{ return lhs.size() != rhs.size() || lhs.compare( rhs ) != 0 ; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator!= (
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
- basic_string_view < CharT, Traits > rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) != 0 ; }
-
-// <
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator< (
- basic_string_view < CharT, Traits > lhs,
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) < 0 ; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator< (
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
- basic_string_view < CharT, Traits > rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) < 0 ; }
-
-// <=
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator<= (
- basic_string_view < CharT, Traits > lhs,
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) <= 0 ; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator<= (
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
- basic_string_view < CharT, Traits > rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) <= 0 ; }
-
-// >
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator> (
- basic_string_view < CharT, Traits > lhs,
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) > 0 ; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator> (
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
- basic_string_view < CharT, Traits > rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) > 0 ; }
-
-// >=
-
-template< class CharT, class Traits nssv_MSVC_ORDER(1) >
-nssv_constexpr bool operator>= (
- basic_string_view < CharT, Traits > lhs,
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) >= 0 ; }
-
-template< class CharT, class Traits nssv_MSVC_ORDER(2) >
-nssv_constexpr bool operator>= (
- nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
- basic_string_view < CharT, Traits > rhs ) nssv_noexcept
-{ return lhs.compare( rhs ) >= 0 ; }
-
-#undef nssv_MSVC_ORDER
-#undef nssv_BASIC_STRING_VIEW_I
-
-#endif // nssv_CPP11_OR_GREATER
-
-// 24.4.4 Inserters and extractors:
-
-namespace detail {
-
-template< class Stream >
-void write_padding( Stream & os, std::streamsize n )
-{
- for ( std::streamsize i = 0; i < n; ++i )
- {
- os.rdbuf()->sputc( os.fill() );
- }
-}
-
-template< class Stream, class View >
-Stream & write_to_stream( Stream & os, View const & sv )
-{
- typename Stream::sentry sentry( os );
-
- if ( !os )
- {
- return os;
- }
-
- const std::streamsize length = static_cast<std::streamsize>( sv.length() );
-
- // Whether, and how, to pad:
- const bool pad = ( length < os.width() );
- const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
-
- if ( left_pad )
- {
- write_padding( os, os.width() - length );
- }
-
- // Write span characters:
- os.rdbuf()->sputn( sv.begin(), length );
-
- if ( pad && !left_pad )
- {
- write_padding( os, os.width() - length );
- }
-
- // Reset output stream width:
- os.width( 0 );
-
- return os;
-}
-
-} // namespace detail
-
-template< class CharT, class Traits >
-std::basic_ostream<CharT, Traits> &
-operator<<(
- std::basic_ostream<CharT, Traits>& os,
- basic_string_view <CharT, Traits> sv )
-{
- return detail::write_to_stream( os, sv );
-}
-
-// Several typedefs for common character types are provided:
-
-typedef basic_string_view<char> string_view;
-typedef basic_string_view<wchar_t> wstring_view;
-#if nssv_HAVE_WCHAR16_T
-typedef basic_string_view<char16_t> u16string_view;
-typedef basic_string_view<char32_t> u32string_view;
-#endif
-
-} // namespace sv_lite
-} // namespace nonstd
-
-//
-// 24.4.6 Suffix for basic_string_view literals:
-//
-
-#if nssv_HAVE_USER_DEFINED_LITERALS
-
-namespace nonstd {
-nssv_inline_ns namespace literals {
-nssv_inline_ns namespace string_view_literals {
-
-#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
-
-nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1)
-{
- return nonstd::sv_lite::string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
-{
- return nonstd::sv_lite::u16string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
-{
- return nonstd::sv_lite::u32string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
-{
- return nonstd::sv_lite::wstring_view{ str, len };
-}
-
-#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-
-nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1)
-{
- return nonstd::sv_lite::string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
-{
- return nonstd::sv_lite::u16string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
-{
- return nonstd::sv_lite::u32string_view{ str, len };
-}
-
-nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
-{
- return nonstd::sv_lite::wstring_view{ str, len };
-}
-
-#endif // nssv_CONFIG_USR_SV_OPERATOR
-
-} // namespace string_view_literals
-} // namespace literals
-} // namespace nonstd
-
-#endif
-
-//
-// Extensions for std::string:
-//
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-namespace nonstd {
-namespace sv_lite {
-
-// Exclude MSVC 14 (19.00): it yields ambiguous to_string():
-
-#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
-
-template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
-std::basic_string<CharT, Traits, Allocator>
-to_string( basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
-{
- return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
-}
-
-#else
-
-template< class CharT, class Traits >
-std::basic_string<CharT, Traits>
-to_string( basic_string_view<CharT, Traits> v )
-{
- return std::basic_string<CharT, Traits>( v.begin(), v.end() );
-}
-
-template< class CharT, class Traits, class Allocator >
-std::basic_string<CharT, Traits, Allocator>
-to_string( basic_string_view<CharT, Traits> v, Allocator const & a )
-{
- return std::basic_string<CharT, Traits, Allocator>( v.begin(), v.end(), a );
-}
-
-#endif // nssv_CPP11_OR_GREATER
-
-template< class CharT, class Traits, class Allocator >
-basic_string_view<CharT, Traits>
-to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
-{
- return basic_string_view<CharT, Traits>( s.data(), s.size() );
-}
-
-} // namespace sv_lite
-} // namespace nonstd
-
-#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-
-//
-// make types and algorithms available in namespace nonstd:
-//
-
-namespace nonstd {
-
-using sv_lite::basic_string_view;
-using sv_lite::string_view;
-using sv_lite::wstring_view;
-
-#if nssv_HAVE_WCHAR16_T
-using sv_lite::u16string_view;
-#endif
-#if nssv_HAVE_WCHAR32_T
-using sv_lite::u32string_view;
-#endif
-
-// literal "sv"
-
-using sv_lite::operator==;
-using sv_lite::operator!=;
-using sv_lite::operator<;
-using sv_lite::operator<=;
-using sv_lite::operator>;
-using sv_lite::operator>=;
-
-using sv_lite::operator<<;
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
-using sv_lite::to_string;
-using sv_lite::to_string_view;
-#endif
-
-} // namespace nonstd
-
-// 24.4.5 Hash support (C++11):
-
-// Note: The hash value of a string view object is equal to the hash value of
-// the corresponding string object.
-
-#if nssv_HAVE_STD_HASH
-
-#include <functional>
-
-namespace std {
-
-template<>
-struct hash< nonstd::string_view >
-{
-public:
- std::size_t operator()( nonstd::string_view v ) const nssv_noexcept
- {
- return std::hash<std::string>()( std::string( v.data(), v.size() ) );
- }
-};
-
-template<>
-struct hash< nonstd::wstring_view >
-{
-public:
- std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept
- {
- return std::hash<std::wstring>()( std::wstring( v.data(), v.size() ) );
- }
-};
-
-template<>
-struct hash< nonstd::u16string_view >
-{
-public:
- std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept
- {
- return std::hash<std::u16string>()( std::u16string( v.data(), v.size() ) );
- }
-};
-
-template<>
-struct hash< nonstd::u32string_view >
-{
-public:
- std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept
- {
- return std::hash<std::u32string>()( std::u32string( v.data(), v.size() ) );
- }
-};
-
-} // namespace std
-
-#endif // nssv_HAVE_STD_HASH
-
-nssv_RESTORE_WARNINGS()
-
-#endif // nssv_HAVE_STD_STRING_VIEW
-
-namespace gmx
-{
-namespace compat
-{
- using namespace nonstd;
-} // namespace compat
-} // namespace gmx
-
-// GMX modification to suppress Doxygen checking
-#endif // DOXYGEN
-
-#endif
-string_view.cpp filter=copyright
-optional.cpp filter=copyright
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
if (GMX_BUILD_UNITTESTS)
gmx_add_unit_test(CompatibilityHelpersTests compat-test
- optional.cpp
- pointers.cpp
- string_view.cpp
- )
- check_cxx_compiler_flag("-Wno-unused-member-function" HAS_NO_UNUSED_MEMBER_FUNCTION)
- if (HAS_NO_UNUSED_MEMBER_FUNCTION)
- set_source_files_properties(optional.cpp PROPERTIES COMPILE_FLAGS -Wno-unused-member-function)
- endif()
+ CPP_SOURCE_FILES
+ pointers.cpp
+ )
+ # Maintainer note: The files here may be borrowed from other projects, and
+ # can require additional handling for compiler flags, warning suppression,
+ # etcetera. Rather than documenting best practices and tips here, we refer
+ # the reader to the `git` repository history for examples of how integration
+ # caveats have been handled in the past (for borrowed code that has since
+ # been removed when it became unnecessary).
endif()
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-//
-// Copyright 2014-2018 by Martin Moene
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-// optional lite is inspired on std::optional by Fernando Cacciola and Andrzej Krzemienski
-// and on expected lite by Martin Moene.
-
-/*! \internal \file
- * \brief Tests for C++14-compatible implementation of std::optional.
- *
- * These tests are similer to those used in commit 7f4c6d4b4c8 of
- * https://github.com/martinmoene/optional-lite.git. The code has not
- * been linted with uncrustify so that any future updates to this
- * active repo can be incorporated easily, and //NOLINT comments added
- * to suppress clang-tidy warnings. The form of those
- * changes have been made to simplify the contents, while making it
- * easy to import any bug fixes that may appear in the source
- * repository.
- *
- * \todo Remove when requiring C++17, which has a standardized version
- * of std::optional.
- *
- * \author Mark Abraham <mark.j.abraham@gmail.com>
- * \ingroup module_compat
- */
-#include "gmxpre.h"
-
-#include "gromacs/compat/optional.h"
-
-#include <initializer_list>
-#include <iostream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "gromacs/utility/strconvert.h"
-
-// GMX modification to suppress Doxygen checking
-#ifndef DOXYGEN
-
-namespace gmx
-{
-
-using namespace compat;
-
-#if optional_USES_STD_OPTIONAL && defined(__APPLE__)
-# define opt_value( o ) *o
-#else
-# define opt_value( o ) o.value()
-#endif
-
-namespace {
-
-struct nonpod { nonpod(){} };
-
-struct Implicit { int x; Implicit(int v) : x(v) {} };
-struct Explicit { int x; explicit Explicit(int v) : x(v) {} };
-
-bool operator==( Implicit a, Implicit b ) { return a.x == b.x; }
-bool operator==( Explicit a, Explicit b ) { return a.x == b.x; }
-
-std::ostream & operator<<( std::ostream & os, Implicit i ) { return os << "Implicit:" << i.x; }
-std::ostream & operator<<( std::ostream & os, Explicit e ) { return os << "Explicit:" << e.x; }
-
-// ensure comparison of pointers for lest:
-
-// const void * lest_nullptr = 0;
-
-// The following tracer code originates as Oracle from Optional by
-// Andrzej Krzemienski, https://github.com/akrzemi1/Optional.
-
-enum State
-{
- /* 0 */ default_constructed,
- /* 1 */ value_copy_constructed,
- /* 2 */ value_move_constructed,
- /* 3 */ copy_constructed,
- /* 4 */ move_constructed,
- /* 5 */ move_assigned,
- /* 6 */ copy_assigned,
- /* 7 */ value_copy_assigned,
- /* 8 */ value_move_assigned,
- /* 9 */ moved_from,
- /*10 */ value_constructed
-};
-
-struct V
-{
- State state;
- int value;
-
- V( ) : state( default_constructed ), value( deflt() ) {}
- V( int v ) : state( value_constructed ), value( v ) {}
-
- bool operator==( V const & rhs ) const { return state == rhs.state && value == rhs.value; }
- bool operator==( int val ) const { return value == val; }
-
- static int deflt() { return 42; }
-};
-
-struct S
-{
- State state;
- V value;
-
- S( ) : state( default_constructed ) {}
- S( V const & v ) : state( value_copy_constructed ), value( v ) {}
- S( S const & s ) : state( copy_constructed ), value( s.value ) {}
-
- S & operator=( V const & v ) { state = value_copy_assigned; value = v; return *this; }
- S & operator=( const S & s ) { state = copy_assigned ; value = s.value; return *this; }
-
-#if optional_CPP11_OR_GREATER
- S( V && v ) : state( value_move_constructed ), value( std::move( v ) ) { v.state = moved_from; } //NOLINT(performance-move-const-arg)
- S( S && s ) : state( move_constructed ), value( std::move( s.value ) ) { s.state = moved_from; } //NOLINT(performance-noexcept-move-constructor,performance-move-const-arg)
-
- S & operator=( V && v ) { state = value_move_assigned ; value = std::move( v ); v.state = moved_from; return *this; } //NOLINT(performance-noexcept-move-constructor,performance-move-const-arg,bugprone-use-after-move)
- S & operator=( S && s ) { state = move_assigned ; value = std::move( s.value ); s.state = moved_from; return *this; } //NOLINT(performance-noexcept-move-constructor,performance-move-const-arg)
-#endif
-
- bool operator==( S const & rhs ) const { return state == rhs.state && value == rhs.value; }
-};
-
-inline std::ostream & operator<<( std::ostream & os, V const & v )
-{
- return os << "[V:" << toString( v.value ) << "]";
-}
-
-struct NoDefault
-{
- NoDefault( NoDefault const & ) {} //NOLINT(readability-named-parameter)
- NoDefault & operator=( NoDefault const & ) { return *this; } //NOLINT(readability-named-parameter)
-
-#if optional_CPP11_OR_GREATER
- NoDefault( NoDefault && ) = default;
- NoDefault & operator=( NoDefault && ) = default;
-#endif
-
-private:
- NoDefault();
-};
-
-struct CopyOnly
-{
- CopyOnly( CopyOnly const & ) {} //NOLINT(readability-named-parameter)
- CopyOnly & operator=( CopyOnly const & ) { return *this; } //NOLINT(readability-named-parameter)
-
-private:
- CopyOnly();
-#if optional_CPP11_OR_GREATER
- CopyOnly( CopyOnly && ) = delete;
- CopyOnly & operator=( CopyOnly && ) = delete;
-#endif
-};
-
-struct MoveOnly
-{
-#if optional_CPP11_OR_GREATER
- MoveOnly( MoveOnly && ) = default;
- MoveOnly & operator=( MoveOnly && ) = default;
-#endif
-
-private:
- MoveOnly();
- MoveOnly( MoveOnly const & );
- MoveOnly & operator=( MoveOnly const & );
-};
-
-struct NoDefaultCopyMove
-{
- std::string text;
- NoDefaultCopyMove( std::string txt ) : text( txt ) {} //NOLINT(readability-named-parameter,performance-unnecessary-value-param)
-
-private:
- NoDefaultCopyMove();
- NoDefaultCopyMove( NoDefaultCopyMove const & );
- NoDefaultCopyMove & operator=( NoDefaultCopyMove const & );
-#if optional_CPP11_OR_GREATER
- NoDefaultCopyMove( NoDefaultCopyMove && ) = delete;
- NoDefaultCopyMove & operator=( NoDefaultCopyMove && ) = delete;
-#endif
-};
-
-#if optional_CPP11_OR_GREATER
-struct InitList
-{
- std::vector<int> vec;
- char c;
- S s;
-
- InitList( std::initializer_list<int> il, char k, S const & t )
- : vec( il ), c( k ), s( t ) {}
-
- InitList( std::initializer_list<int> il, char k, S && t )
- : vec( il ), c( k ), s( std::move( t ) ) {}
-};
-#endif
-
-} // anonymous namespace
-
-//
-// test specification:
-//
-
-TEST(OptionalTest, UnionCanContainNonPodTypes)
-{
- SCOPED_TRACE("union: A C++03 union can only contain POD types");
- union U
- {
- char c;
-#if optional_CPP11_OR_GREATER
- nonpod np;
-#endif
- };
-}
-
-//
-// optional member operations:
-//
-
-// construction:
-
-TEST(OptionalTest, CanDefaultConstructEmpty)
-{
- SCOPED_TRACE("optional: Allows to default construct an empty optional (1a)");
- optional<int> a;
-
- EXPECT_TRUE( !a );
-}
-
-TEST(OptionalTest, CanConstructFromNullopt)
-{
- SCOPED_TRACE("optional: Allows to explicitly construct a disengaged, empty optional via nullopt (1b)");
- optional<int> a( nullopt );
-
- EXPECT_TRUE( !a );
-}
-
-TEST(OptionalTest, CanDefaultConstructUsingNonDefaultConstructibleType)
-{
- SCOPED_TRACE("optional: Allows to default construct an empty optional with a non-default-constructible (1a)");
-// FAILS: NoDefault nd;
-// FAILS: NoDefaultCopyMove ndcm;
- optional<NoDefault> ond;
- optional<CopyOnly> oco;
- optional<MoveOnly> omo;
- optional<NoDefaultCopyMove> ondcm;
-
- EXPECT_TRUE( !ond );
- EXPECT_TRUE( !oco );
- EXPECT_TRUE( !omo );
- EXPECT_TRUE( !ondcm );
-}
-
-TEST(OptionalTest, CanCopyConstructFromEmptyOptional)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from empty optional (2)");
- optional<int> a;
-
- optional<int> b( a ); //NOLINT(performance-unnecessary-copy-initialization)
-
- EXPECT_TRUE( !b );
-}
-
-TEST(OptionalTest, CanMoveConstructFromEmptyOptional)
-{
- SCOPED_TRACE("optional: Allows to move-construct from empty optional (C++11, 3)");
-#if optional_CPP11_OR_GREATER
- optional<int> a;
-
- optional<int> b( std::move( a ) );
-
- EXPECT_TRUE( !b );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyConstructFromEmptyOptionalWithExplicitConversion)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from empty optional, explicit converting (C++11, 4a)");
-#if optional_CPP11_OR_GREATER
- optional<int> a;
-
- optional<Explicit> b{ a };
-
- EXPECT_TRUE( !b );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyConstructFromEmptyOptionalNonExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from empty optional, non-explicit converting (4b)");
- optional<int> a;
-
- optional<Implicit> b( a );
-
- EXPECT_TRUE( !b );
-}
-
-TEST(OptionalTest, CanMoveConstructFromEmptyOptionalExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from empty optional, explicit converting (C++11, 5a)");
-#if optional_CPP11_OR_GREATER
- optional<int> a;
-
- optional<Explicit> b{ std::move( a ) };
-
- EXPECT_TRUE( !b );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveConstructFromEmptyOptionalNonExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from empty optional, non-explicit converting (C++11, 5a)");
-#if optional_CPP11_OR_GREATER
- optional<int> a;
-
- optional<Implicit> b( std::move( a ) );
-
- EXPECT_TRUE( !b );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyConstructFromNonEmptyOptional)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from non-empty optional (2)");
- optional<int> a( 7 );
-
- optional<int> b( a );
-
- EXPECT_TRUE( b );
- EXPECT_EQ ( *b, 7 );
-}
-
-TEST(OptionalTest, CanCopyConstructFromNonEmptyOptionalExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from non-empty optional, explicit converting (C++11, 4a)");
-#if optional_CPP11_OR_GREATER
- optional<int> a( 7 );
-
- optional<Explicit> b{ a };
-
- EXPECT_TRUE( b );
- EXPECT_EQ( *b, Explicit{7} );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyConstructFromNonEmptyOptionalNonExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from non-empty optional, non-explicit converting (4b)");
- optional<int> a( 7 );
-
- optional<Implicit> b( a );
-
- EXPECT_TRUE( b );
- EXPECT_EQ( *b, Implicit(7) );
-}
-
-TEST(OptionalTest, CanMoveConstructFromNonEmptyOptional)
-{
- SCOPED_TRACE("optional: Allows to move-construct from non-empty optional (C++11, 3)");
-#if optional_CPP11_OR_GREATER
- optional<int> a( 7 );
-
- optional<int> b( std::move( a ) );
-
- EXPECT_TRUE( b );
- EXPECT_EQ( *b, 7 );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveConstructFromNonEmptyOptionalExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from non-empty optional, explicit converting (C++11, 5a)");
-#if optional_CPP11_OR_GREATER
- optional<int> a( 7 );
-
- optional<Explicit> b{ std::move( a ) };
-
- EXPECT_TRUE( b );
- EXPECT_EQ( *b, Explicit{7} );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveConstructFromNonEmptyOptionalNonExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from non-empty optional, non-explicit converting (C++11, 5b)");
-#if optional_CPP11_OR_GREATER
- optional<int> a( 7 );
-
- optional<Implicit> b( std::move( a ) );
-
- EXPECT_TRUE( b );
- EXPECT_EQ( *b, Implicit(7) );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-namespace {
-
-#if optional_CPP11_OR_GREATER
- void use_optional( nonstd::optional<Implicit> ) {} //NOLINT(readability-named-parameter,performance-unnecessary-value-param)
-#else
- template< typename T >
- void use_optional( T ) {}
-#endif
-
-}
-
-TEST(OptionalTest, CanCopyConstructFromLiteral)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from literal value (8)");
- use_optional( 7 );
- optional<int> a = 7;
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, 7 );
-}
-
-TEST(OptionalTest, CanCopyConstructFromLiteralConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from literal value, converting (8)");
- use_optional( '7' );
- optional<int> a = '7';
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, '7' );
-}
-
-TEST(OptionalTest, CanCopyConstructFromValue)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from value (8)");
- const int i = 7;
-
- use_optional( i );
- optional<int> a( i );
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, 7 );
-}
-
-TEST(OptionalTest, CanCopyConstructFromValueConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-construct from value, converting (8)");
- const char c = '7';
-
- use_optional( c );
- optional<int> a( c );
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, '7' );
-}
-
-TEST(OptionalTest, CanMoveConstructFromValue)
-{
- SCOPED_TRACE("optional: Allows to move-construct from value (C++11, 8b)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
-
- optional<S> a( std::move( s ) );
-
- EXPECT_EQ( a->value, 7 );
- EXPECT_EQ( a->state, move_constructed );
- EXPECT_EQ( s.state, moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveConstructFromValueExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from value, explicit converting (C++11, 8a)");
-#if optional_CPP11_OR_GREATER
- int seven = 7;
-
- optional<Explicit> a{ std::move( seven ) }; //NOLINT(performance-move-const-arg)
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, Explicit{7} );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveConstructFromValueNonExplicitConverting)
-{
- SCOPED_TRACE("optional: Allows to move-construct from value, non-explicit converting (C++11, 8b)");
-#if optional_CPP11_OR_GREATER
- int seven = 7;
- optional<Implicit> a( std::move( seven ) ); //NOLINT(performance-move-const-arg)
-
- EXPECT_TRUE( a );
- EXPECT_EQ( *a, Implicit(7) );
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanInPlaceConstructFromLiteral)
-{
- SCOPED_TRACE("optional: Allows to in-place construct from literal value (C++11, 6)");
-#if optional_CPP11_OR_GREATER
- using pair_t = std::pair<char, int>;
-
- optional<pair_t> a( in_place, 'a', 7 );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second, 7 );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanInPlaceCopyConstructFromValue)
-{
- SCOPED_TRACE("optional: Allows to in-place copy-construct from value (C++11, 6)");
-#if optional_CPP11_OR_GREATER
- char c = 'a'; S s( 7 );
- using pair_t = std::pair<char, S>;
-
- optional<pair_t> a( in_place, c, s );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value, 7 );
-#if optional_USES_STD_OPTIONAL
- EXPECT_EQ( a->second.state, copy_constructed );
-#else
- EXPECT_EQ( a->second.state, move_constructed );
-#endif
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanInPlaceMoveConstructFromValue)
-{
- SCOPED_TRACE("optional: Allows to in-place move-construct from value (C++11, 6)");
-#if optional_CPP11_OR_GREATER
- char c = 'a'; S s( 7 );
- using pair_t = std::pair<char, S>;
-
- optional<pair_t> a( in_place, c, std::move( s ) );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value, 7 );
- EXPECT_EQ( a->second.state, move_constructed );
- EXPECT_EQ( s.state, moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanInPlaceCopyConstructFromInitializerList)
-{
- SCOPED_TRACE("optional: Allows to in-place copy-construct from initializer-list (C++11, 7)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- optional<InitList> a( in_place, { 7, 8, 9, }, 'a', s );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a');
- EXPECT_EQ( a->s.value, 7 );
-#if optional_USES_STD_OPTIONAL
- EXPECT_EQ( a->s.state , copy_constructed );
-#else
- EXPECT_EQ( a->s.state , move_constructed );
-#endif
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanInPlaceMoveConstructFromInitializerList)
-{
- SCOPED_TRACE("optional: Allows to in-place move-construct from initializer-list (C++11, 7)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- optional<InitList> a( in_place, { 7, 8, 9, }, 'a', std::move( s ) );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a' );
- EXPECT_EQ( a->s.value , 7 );
- EXPECT_EQ( a->s.state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-// assignment:
-
-TEST(OptionalTest, CanAssignNulloptToDisengage)
-{
- SCOPED_TRACE("optional: Allows to assign nullopt to disengage (1)");
- optional<int> a( 7 );
-
- a = nullopt;
-
- EXPECT_TRUE( !a );
-}
-
-TEST(OptionalTest, CanCopyAssignBetweenEngagedAndDisengagedOptionals)
-{
- SCOPED_TRACE("optional: Allows to copy-assign from/to engaged and disengaged optionals (2)");
- optional<int> d1;
- optional<int> d2;
- optional<int> e1( 123 );
- optional<int> e2( 987 );
-
- {
- SCOPED_TRACE("a disengaged optional assigned nullopt remains empty");
- d1 = nullopt;
- EXPECT_TRUE( !d1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned an engaged optional obtains its value");
- d1 = e1;
- EXPECT_TRUE( d1 );
- EXPECT_EQ( *d1 , 123 );
- }
- {
- SCOPED_TRACE("an engaged optional assigned an engaged optional obtains its value");
- e1 = e2;
- EXPECT_TRUE( e1 );
- EXPECT_EQ( *e1 , 987 );
- }
- {
- SCOPED_TRACE("an engaged optional assigned nullopt becomes empty");
- e1 = nullopt;
- EXPECT_TRUE( !e1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned a disengaged optional remains empty");
- d1 = d2;
- EXPECT_TRUE( !d1 );
- }
-}
-
-TEST(MakeOptionalTest, CanMoveAssignBetweenEngagedAndDisengagedOptionals)
-{
- SCOPED_TRACE("optional: Allows to move-assign from/to engaged and disengaged optionals (C++11, 3)");
-#if optional_CPP11_OR_GREATER
- optional<int> d1;
- optional<int> d2;
- optional<int> e1( 123 );
- optional<int> e2( 987 );
-
- {
- SCOPED_TRACE("a disengaged optional assigned nullopt remains empty");
- d1 = std::move( nullopt ); //NOLINT(performance-move-const-arg)
- EXPECT_TRUE( !d1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned an engaged optional obtains its value");
- d1 = std::move( e1);
- EXPECT_TRUE( d1 );
- EXPECT_EQ( *d1 , 123 );
- }
- {
- SCOPED_TRACE("an engaged optional assigned an engaged optional obtains its value");
- e1 = std::move( e2 );
- EXPECT_TRUE( e1 );
- EXPECT_EQ( *e1 , 987 );
- }
- {
- SCOPED_TRACE("an engaged optional assigned nullopt becomes empty");
- e1 = std::move( nullopt ); //NOLINT(performance-move-const-arg)
- EXPECT_TRUE( !e1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned a disengaged optional remains empty");
- d1 = std::move( d2);
- EXPECT_TRUE( !d1 );
- }
-#else
- EXPECT_TRUE( !!"optional: move-assignment is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyAssignBetweenEngagedAndDisengagedOptionalsConverting)
-{
- SCOPED_TRACE("optional: Allows to copy-assign from/to engaged and disengaged optionals, converting, (5)");
- optional<int> d1;
- optional<char> d2;
- optional<int> e1( 123 );
- optional<char> e2( '7' );
-
- {
- SCOPED_TRACE("a disengaged optional assigned an engaged optional obtains its value, converting");
- d1 = e2;
- EXPECT_TRUE( d1 );
- EXPECT_EQ( *d1 , '7' );
- }
- {
- SCOPED_TRACE("an engaged optional assigned an engaged optional obtains its value, converting");
- e1 = e2;
- EXPECT_TRUE( e1 );
- EXPECT_EQ( *e1 , '7' );
- }
- {
- SCOPED_TRACE("an engaged optional assigned a disengaged optional becomes empty, converting");
- e1 = d2;
- EXPECT_TRUE( !e1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned a disengaged optional remains empty, converting");
- d1 = d2;
- EXPECT_TRUE( !d1 );
- }
-}
-
-TEST(OptionalTest, CanMoveAssignBetweenEngagedAndDisengagedOptionalsConverting)
-{
- SCOPED_TRACE("optional: Allows to move-assign from/to engaged and disengaged optionals, converting (C++11, 6)");
-#if optional_CPP11_OR_GREATER
- optional<int> d1;
- optional<char> d2;
- optional<int> e1( 123 );
- optional<char> e2( '7' );
-
- {
- SCOPED_TRACE("a disengaged optional assigned an engaged optional obtains its value, converting");
- d1 = std::move( e2 );
- EXPECT_TRUE( d1 );
- EXPECT_EQ( *d1 , '7' );
- }
- {
- SCOPED_TRACE("an engaged optional assigned an engaged optional obtains its value, converting");
- e1 = std::move( e2 ); //NOLINT(bugprone-use-after-move)
- EXPECT_TRUE( e1 );
- EXPECT_EQ( *e1 , '7' );
- }
- {
- SCOPED_TRACE("an engaged optional assigned a disengaged optional becomes empty, converting");
- e1 = std::move( d2 );
- EXPECT_TRUE( !e1 );
- }
- {
- SCOPED_TRACE("a disengaged optional assigned a disengaged optional remains empty, converting");
- d1 = std::move( d2 ); //NOLINT(bugprone-use-after-move)
- EXPECT_TRUE( !d1 );
- }
-#else
- EXPECT_TRUE( !!"optional: move-assignment is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyAssignFromLiteral)
-{
- SCOPED_TRACE("optional: Allows to copy-assign from literal value (4)");
- optional<int> a;
-
- a = 7;
-
- EXPECT_EQ( *a , 7 );
-}
-
-TEST(OptionalTest, CanCopyAssignFromValue)
-{
- SCOPED_TRACE("optional: Allows to copy-assign from value (4)");
- const int i = 7;
- optional<int> a;
-
- a = i;
-
- EXPECT_EQ( *a , i );
-}
-
-TEST(OptionalTest, CanMoveAssignFromValue)
-{
- SCOPED_TRACE("optional: Allows to move-assign from value (C++11, 4)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- optional<S> a;
-
- a = std::move( s );
-
- EXPECT_EQ( a->value , 7 );
- EXPECT_EQ( a->state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: move-assign is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyEmplaceFromArguments)
-{
- SCOPED_TRACE("optional: Allows to copy-emplace content from arguments (C++11, 7)");
-#if optional_CPP11_OR_GREATER
- using pair_t = std::pair<char, S>;
- S s( 7 );
- optional<pair_t> a;
-
- a.emplace( 'a', s );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value , 7 );
- EXPECT_EQ( a->second.state , copy_constructed );
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveEmplaceFromArguments)
-{
- SCOPED_TRACE("optional: Allows to move-emplace content from arguments (C++11, 7)");
-#if optional_CPP11_OR_GREATER
- using pair_t = std::pair<char, S>;
- S s( 7 );
- optional<pair_t> a;
-
- a.emplace( 'a', std::move( s ) );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value , 7 );
- EXPECT_EQ( a->second.state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanCopyEmplaceFromInitializerListAndArguments)
-{
- SCOPED_TRACE("optional: Allows to copy-emplace content from intializer-list and arguments (C++11, 8)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- optional<InitList> a;
-
- a.emplace( { 7, 8, 9, }, 'a', s );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a' );
- EXPECT_EQ( a->s.value , 7 );
- EXPECT_EQ( a->s.state , copy_constructed );
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanMoveEmplaceFromInitializerListAndArguments)
-{
- SCOPED_TRACE("optional: Allows to move-emplace content from intializer-list and arguments (C++11, 8)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- optional<InitList> a;
-
- a.emplace( { 7, 8, 9, }, 'a', std::move( s ) );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a' );
- EXPECT_EQ( a->s.value , 7 );
- EXPECT_EQ( a->s.state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-// swap:
-
-class OptionalMemberSwapTest : public ::testing::Test
-{
- public:
- optional<int> d1;
- optional<int> d2;
- optional<int> e1{ 42 };
- optional<int> e2{ 7 };
-};
-
-TEST_F(OptionalMemberSwapTest, CanSwapDisengagedWithDisengaged)
- {
- SCOPED_TRACE("swap disengaged with disengaged optional");
- d1.swap( d2 );
- EXPECT_TRUE( !d1 );
- }
-
-TEST_F(OptionalMemberSwapTest, CanSwapEngagedWithDisengaged)
- {
- SCOPED_TRACE("swap engaged with engaged optional");
- e1.swap( e2 );
- EXPECT_TRUE( e1 );
- EXPECT_TRUE( e2 );
- EXPECT_EQ( *e1 , 7 );
- EXPECT_EQ( *e2 , 42 );
- }
-TEST_F(OptionalMemberSwapTest, CanSwapDisengagedWithEngaged)
- {
- SCOPED_TRACE("swap disengaged with engaged optional");
- d1.swap( e1 );
- EXPECT_TRUE( d1 );
- EXPECT_TRUE( !e1 );
- EXPECT_EQ( *d1 , 42 );
- }
-TEST_F(OptionalMemberSwapTest, CanSwapEngagedWithEngaged)
- {
- SCOPED_TRACE("swap engaged with disengaged optional");
- e1.swap( d1 );
- EXPECT_TRUE( d1 );
- EXPECT_TRUE( !e1 );
- EXPECT_EQ( *d1 , 42 );
- }
-
-// observers:
-
-class OptionalImplicitValueTest : public ::testing::Test
-{
- public:
- optional<Implicit> e{ Implicit( 42 ) };
- optional<Implicit> const ce{ Implicit( 42 ) };
-};
-
-TEST_F(OptionalImplicitValueTest, CanObtainValueConst)
- {
- SCOPED_TRACE("operator->() yields pointer to value (const)");
- EXPECT_EQ( ce->x , 42 );
- }
-TEST_F(OptionalImplicitValueTest, CanObtainValueNonConst)
- {
- SCOPED_TRACE("operator->() yields pointer to value (non-const)");
- e->x = 7;
- EXPECT_EQ( e->x , 7 );
- }
-
-TEST_F(OptionalImplicitValueTest, CanObtainMovedFromValueConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("operator->() yields pointer to value (const)");
- EXPECT_EQ( std::move( ce )->x , 42 ); //NOLINT(performance-move-const-arg)
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-TEST_F(OptionalImplicitValueTest, CanObtainMovedFromValueNonConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("operator->() yields pointer to value (non-const)");
- e->x = 7;
- EXPECT_EQ( std::move( e )->x , 7 );
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-
-class OptionalIntValueTest : public ::testing::Test
-{
- public:
- optional<int> a;
- optional<int> b{ 7 };
- optional<int> d;
- optional<int> const cd;
- optional<int> e{ 42 };
- optional<int> const ce{ 42 };
- optional<int> d1;
- optional<int> d2;
- optional<int> e1{ 42 };
- optional<int> e2{ 7 };
-};
-
-TEST_F(OptionalIntValueTest, CanObtainValueFromDereferenceOperatorConst)
- {
- SCOPED_TRACE("operator*() yields value (const)");
- EXPECT_EQ( *ce , 42 );
- }
-TEST_F(OptionalIntValueTest, CanObtainValueFromDereferenceOperatorNonConst)
- {
- SCOPED_TRACE("operator*() yields value (non-const)");
- *e = 7;
- EXPECT_EQ( *e , 7 );
- }
-
-TEST_F(OptionalIntValueTest, CanObtainMovedValueFromDereferenceOperatorConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("operator*() yields value (const)");
- EXPECT_EQ( *(std::move( ce )) , 42 ); //NOLINT(performance-move-const-arg)
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-TEST_F(OptionalIntValueTest, CanObtainMovedValueFromDereferenceOperatorNonConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("operator*() yields value (non-const)");
- *e = 7;
- EXPECT_EQ( *(std::move( e )) , 7 );
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-
-TEST_F(OptionalIntValueTest, CanObtainHasValueViaOperatorBool)
-{
- SCOPED_TRACE("optional: Allows to obtain has_value() via operator bool()");
-
- EXPECT_FALSE( a );
- EXPECT_TRUE( b );
-}
-
-TEST_F(OptionalIntValueTest, CanObtainValueViaValueMethodConst)
- {
- SCOPED_TRACE("value() yields value (const)");
- EXPECT_EQ( opt_value( ce ) , 42 );
- }
-TEST_F(OptionalIntValueTest, CanObtainValueViaValueMethodNonConst)
- {
- SCOPED_TRACE("value() yields value (non-const)");
- EXPECT_EQ( opt_value( e ) , 42 );
- }
-
-TEST_F(OptionalIntValueTest, CanObtainMovedValueViaValueMethodConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("value() yields value (const)");
- EXPECT_EQ( opt_value( std::move( ce ) ) , 42 ); //NOLINT(performance-move-const-arg)
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-TEST_F(OptionalIntValueTest, CanObtainMovedValueViaValueMethodNonConst)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("value() yields value (non-const)");
- EXPECT_EQ( opt_value( std::move( e ) ) , 42 );
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-
-TEST_F(OptionalIntValueTest, CanObtainValueFromNonEmptyOptionalViaValueOrMethod)
- {
- SCOPED_TRACE("value_or( 7 ) yields value for non-empty optional");
- EXPECT_EQ( e.value_or( 7 ) , 42 );
- }
-TEST_F(OptionalIntValueTest, CanObtainDefaultFromEmptyOptionalViaValueOrMethod)
- {
- SCOPED_TRACE("value_or( 7 ) yields default for empty optional");
- EXPECT_EQ( d.value_or( 7 ) , 7 );
- }
-
-TEST_F(OptionalIntValueTest, CanObtainMovedFromValueForLValuesViaValueOrMethod)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("for l-values");
- EXPECT_EQ( d.value_or( 7 ) , 7 );
- EXPECT_EQ( e.value_or( 7 ) , 42 );
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-TEST_F(OptionalIntValueTest, CanObtainMovedFromValueForRValuesViaValueOrMethod)
- {
-#if optional_CPP11_OR_GREATER
- SCOPED_TRACE("for r-values");
- EXPECT_EQ( std::move( d ).value_or( 7 ) , 7 );
- EXPECT_EQ( std::move( e ).value_or( 7 ) , 42 );
-#else
- EXPECT_TRUE( !!"optional: move-semantics are not available (no C++11)" );
-#endif
- }
-
-TEST_F(OptionalIntValueTest, ThrowsBadOptionalAccessAtDisengagedAccessForLValues)
-{
- SCOPED_TRACE("optional: Throws bad_optional_access at disengaged access");
-#if optional_USES_STD_OPTIONAL && defined(__APPLE__)
- EXPECT_TRUE( true );
-#else
-
- {
- SCOPED_TRACE("for l-values");
- EXPECT_THROW( d.value(), bad_optional_access );
- EXPECT_THROW( cd.value(), bad_optional_access );
- }
-#endif
-}
-TEST_F(OptionalIntValueTest, ThrowsBadOptionalAccessAtDisengagedAccessForRValues)
-{
- SCOPED_TRACE("optional: Throws bad_optional_access at disengaged access");
-#if optional_USES_STD_OPTIONAL && defined(__APPLE__)
- EXPECT_TRUE( true );
-#else
-
-# if optional_CPP11_OR_GREATER
- {
- SCOPED_TRACE("for r-values");
- EXPECT_THROW( std::move( d ).value(), bad_optional_access );
- EXPECT_THROW( std::move( cd ).value(), bad_optional_access ); //NOLINT(performance-move-const-arg)
- }
-# endif
-#endif
-}
-
-TEST_F(OptionalIntValueTest, ThrowsBadOptionalAccessWithNonEmptyWhatMethod)
-{
- SCOPED_TRACE("optional: Throws bad_optional_access with non-empty what()");
- try
- {
- (void) d.value();
- }
- catch( bad_optional_access const & e )
- {
- EXPECT_TRUE( ! std::string( e.what() ).empty() );
- }
-}
-
-// modifiers:
-
-TEST(OptionalTest, CanResetContent)
-{
- SCOPED_TRACE("optional: Allows to reset content");
- optional<int> a = 7;
-
- a.reset();
-
- EXPECT_FALSE( a.has_value() );
-}
-
-//
-// optional non-member functions:
-//
-
-TEST_F(OptionalIntValueTest, CanNonMemberSwapDisengagnedWithDisengaged)
- {
- SCOPED_TRACE("swap disengaged with disengaged optional");
- swap( d1, d2 );
- EXPECT_TRUE( !d1 );
- }
-TEST_F(OptionalIntValueTest, CanNonMemberSwapEngagnedWithEngaged)
- {
- SCOPED_TRACE("swap engaged with engaged optional");
- swap( e1, e2 );
- EXPECT_TRUE( e1 );
- EXPECT_TRUE( e2 );
- EXPECT_EQ( *e1 , 7 );
- EXPECT_EQ( *e2 , 42 );
- }
-TEST_F(OptionalIntValueTest, CanNonMemberSwapDisengagnedWithEngaged)
- {
- SCOPED_TRACE("swap disengaged with engaged optional");
- swap( d1, e1 );
- EXPECT_TRUE( d1 );
- EXPECT_TRUE( !e1 );
- EXPECT_EQ( *d1 , 42 );
- }
-TEST_F(OptionalIntValueTest, CanNonMemberSwapEngagnedWithDisengaged)
- {
- SCOPED_TRACE("swap engaged with disengaged optional");
- swap( e1, d1 );
- EXPECT_TRUE( d1 );
- EXPECT_TRUE( !e1 );
- EXPECT_EQ( *d1 , 42 );
- }
-
-template< typename R, typename S, typename T >
-void relop()
-{
- optional<R> d;
- optional<S> e1( 6 );
- optional<T> e2( 7 );
-
- { SCOPED_TRACE( "engaged == engaged" ); EXPECT_TRUE( e1 == e1 ); }
- { SCOPED_TRACE( "engaged == disengaged" ); EXPECT_TRUE( !(e1 == d ) ); }
- { SCOPED_TRACE( "disengaged == engaged" ); EXPECT_TRUE( !(d == e1) ); }
-
- { SCOPED_TRACE( "engaged != engaged" ); EXPECT_TRUE( e1 != e2 ); }
- { SCOPED_TRACE( "engaged != disengaged" ); EXPECT_TRUE( e1 != d ); }
- { SCOPED_TRACE( "disengaged != engaged" ); EXPECT_TRUE( d != e2 ); }
-
- { SCOPED_TRACE( "engaged < engaged" ); EXPECT_TRUE( e1 < e2 ); }
- { SCOPED_TRACE( "engaged < disengaged" ); EXPECT_TRUE( !(e1 < d ) ); }
- { SCOPED_TRACE( "disengaged < engaged" ); EXPECT_TRUE( d < e2 ); }
-
- { SCOPED_TRACE( "engaged <= engaged" ); EXPECT_TRUE( e1 <= e1 ); }
- { SCOPED_TRACE( "engaged <= engaged" ); EXPECT_TRUE( e1 <= e2 ); }
- { SCOPED_TRACE( "engaged <= disengaged" ); EXPECT_TRUE( !(e1 <= d ) ); }
- { SCOPED_TRACE( "disengaged <= engaged" ); EXPECT_TRUE( d <= e2 ); }
-
- { SCOPED_TRACE( "engaged > engaged" ); EXPECT_TRUE( e2 > e1 ); }
- { SCOPED_TRACE( "engaged > disengaged" ); EXPECT_TRUE( e2 > d ); }
- { SCOPED_TRACE( "disengaged > engaged" ); EXPECT_TRUE( !(d > e1) ); }
-
- { SCOPED_TRACE( "engaged >= engaged" ); EXPECT_TRUE( e1 >= e1 ); }
- { SCOPED_TRACE( "engaged >= engaged" ); EXPECT_TRUE( e2 >= e1 ); }
- { SCOPED_TRACE( "engaged >= disengaged" ); EXPECT_TRUE( e2 >= d ); }
- { SCOPED_TRACE( "disengaged >= engaged" ); EXPECT_TRUE( !(d >= e1) ); }
-
- { SCOPED_TRACE( "disengaged == nullopt" ); EXPECT_TRUE( (d == nullopt) ); }
- { SCOPED_TRACE( "nullopt == disengaged" ); EXPECT_TRUE( (nullopt == d ) ); }
- { SCOPED_TRACE( "engaged == nullopt" ); EXPECT_TRUE( (e1 != nullopt) ); }
- { SCOPED_TRACE( "nullopt == engaged" ); EXPECT_TRUE( (nullopt != e1 ) ); }
- { SCOPED_TRACE( "disengaged == nullopt" ); EXPECT_TRUE( !(d < nullopt) ); }
- { SCOPED_TRACE( "nullopt == disengaged" ); EXPECT_TRUE( !(nullopt < d ) ); }
- { SCOPED_TRACE( "disengaged == nullopt" ); EXPECT_TRUE( (d <= nullopt) ); }
- { SCOPED_TRACE( "nullopt == disengaged" ); EXPECT_TRUE( (nullopt <= d ) ); }
- { SCOPED_TRACE( "disengaged == nullopt" ); EXPECT_TRUE( !(d > nullopt) ); }
- { SCOPED_TRACE( "nullopt == disengaged" ); EXPECT_TRUE( !(nullopt > d ) ); }
- { SCOPED_TRACE( "disengaged == nullopt" ); EXPECT_TRUE( (d >= nullopt) ); }
- { SCOPED_TRACE( "nullopt == disengaged" ); EXPECT_TRUE( (nullopt >= d ) ); }
-
- { SCOPED_TRACE( "engaged == value" ); EXPECT_TRUE( e1 == 6 ); }
- { SCOPED_TRACE( "value == engaged" ); EXPECT_TRUE( 6 == e1 ); }
- { SCOPED_TRACE( "engaged != value" ); EXPECT_TRUE( e1 != 7 ); }
- { SCOPED_TRACE( "value != engaged" ); EXPECT_TRUE( 6 != e2 ); }
- { SCOPED_TRACE( "engaged < value" ); EXPECT_TRUE( e1 < 7 ); }
- { SCOPED_TRACE( "value < engaged" ); EXPECT_TRUE( 6 < e2 ); }
- { SCOPED_TRACE( "engaged <= value" ); EXPECT_TRUE( e1 <= 7 ); }
- { SCOPED_TRACE( "value <= engaged" ); EXPECT_TRUE( 6 <= e2 ); }
- { SCOPED_TRACE( "engaged > value" ); EXPECT_TRUE( e2 > 6 ); }
- { SCOPED_TRACE( "value > engaged" ); EXPECT_TRUE( 7 > e1 ); }
- { SCOPED_TRACE( "engaged >= value" ); EXPECT_TRUE( e2 >= 6 ); }
- { SCOPED_TRACE( "value >= engaged" ); EXPECT_TRUE( 7 >= e1 ); }
-}
-
-TEST(OptionalTest, ProvidesRelationalOperators)
-{
- SCOPED_TRACE("optional: Provides relational operators");
- relop<int, int, int>();
-}
-
-TEST(OptionalTest, ProvidesMixedTypeRelationalOperators)
-{
- SCOPED_TRACE("optional: Provides mixed-type relational operators");
- relop<char, int, long>();
-}
-
-TEST(MakeOptionalTest, CanCopyConstruct)
-{
- SCOPED_TRACE("make_optional: Allows to copy-construct optional");
- S s( 7 );
-
- EXPECT_EQ( make_optional( s )->value , 7 );
- EXPECT_NE( s.state , moved_from );
-}
-
-TEST(MakeOptionalTest, CanMoveConstruct)
-{
- SCOPED_TRACE("make_optional: Allows to move-construct optional (C++11)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
-
- EXPECT_EQ( make_optional( std::move( s ) )->value , 7 );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: move-construction is not available (no C++11)" );
-#endif
-}
-
-TEST(MakeOptionalTest, CanInPlaceCopyConstructFromArguments)
-{
- SCOPED_TRACE("make_optional: Allows to in-place copy-construct optional from arguments (C++11)");
-#if optional_CPP11_OR_GREATER
- using pair_t = std::pair<char, S>;
-
- S s( 7);
- auto a = make_optional<pair_t>( 'a', s );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value , 7 );
-#if optional_USES_STD_OPTIONAL
- EXPECT_EQ( a->second.state , copy_constructed );
-#else
- EXPECT_EQ( a->second.state , move_constructed );
-#endif
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(MakeOptionalTest, CanInPlaceMoveConstructFromArguments)
-{
- SCOPED_TRACE("make_optional: Allows to in-place move-construct optional from arguments (C++11)");
-#if optional_CPP11_OR_GREATER
- using pair_t = std::pair<char, S>;
-
- S s( 7 );
- auto a = make_optional<pair_t>( 'a', std::move( s ) );
-
- EXPECT_EQ( a->first , 'a' );
- EXPECT_EQ( a->second.value , 7 );
- EXPECT_EQ( a->second.state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(MakeOptionalTest, CanInPlaceCopyConstructFromInitializerListAndArguments)
-{
- SCOPED_TRACE("make_optional: Allows to in-place copy-construct optional from initializer-list and arguments (C++11)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- auto a = make_optional<InitList>( { 7, 8, 9, }, 'a', s );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a' );
- EXPECT_EQ( a->s.value , 7 );
-#if optional_USES_STD_OPTIONAL
- EXPECT_EQ( a->s.state , copy_constructed );
-#else
- EXPECT_EQ( a->s.state , move_constructed );
-#endif
- EXPECT_NE( s.state , moved_from );
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(MakeOptionalTest, CanInPlaceMoveConstructFromInitializerListAndArguments)
-{
- SCOPED_TRACE("make_optional: Allows to in-place move-construct optional from initializer-list and arguments (C++11)");
-#if optional_CPP11_OR_GREATER
- S s( 7 );
- auto a = make_optional<InitList>( { 7, 8, 9, }, 'a', std::move( s ) );
-
- EXPECT_EQ( a->vec[0] , 7 );
- EXPECT_EQ( a->vec[1] , 8 );
- EXPECT_EQ( a->vec[2] , 9 );
- EXPECT_EQ( a->c , 'a' );
- EXPECT_EQ( a->s.value , 7 );
- EXPECT_EQ( a->s.state , move_constructed );
- EXPECT_EQ( s.state , moved_from ); //NOLINT(bugprone-use-after-move)
-#else
- EXPECT_TRUE( !!"optional: in-place construction is not available (no C++11)" );
-#endif
-}
-
-TEST(OptionalTest, CanProduceHash)
-{
- SCOPED_TRACE("std::hash<>: Allows to obtain hash (C++11)");
-#if optional_CPP11_OR_GREATER
- const auto a = optional<int>( 7 );
- const auto b = optional<int>( 7 );
-
- EXPECT_EQ( std::hash<optional<int>>{}( a ) , std::hash<optional<int>>{}( b ) );
-#else
- EXPECT_GT( !!"std::hash<>: std::hash<, is not available (no C++11)" );
-#endif
-}
-
-
-//
-// Negative tests:
-//
-
-//
-// Tests that print information:
-//
-
-struct Struct{ Struct(){} };
-
-#if !defined(optional_FEATURE_MAX_ALIGN_HACK) || !optional_FEATURE_MAX_ALIGN_HACK
-
-#define optional_OUTPUT_ALIGNMENT_OF( type ) \
- "alignment_of<" #type ">: " << \
- alignment_of<type>::value << "\n" <<
-
-TEST(OptionalTest, ShowAlignmentDependingOnBaseType)
-{
- SCOPED_TRACE("alignment_of: Show alignment of various types");
-
-#if optional_CPP11_OR_GREATER
- using std::alignment_of;
-#else
- using ::nonstd::optional_lite::detail::alignment_of;
-#endif
-
- std::cout <<
- optional_OUTPUT_ALIGNMENT_OF( char )
- optional_OUTPUT_ALIGNMENT_OF( short )
- optional_OUTPUT_ALIGNMENT_OF( int )
- optional_OUTPUT_ALIGNMENT_OF( long )
- optional_OUTPUT_ALIGNMENT_OF( float )
- optional_OUTPUT_ALIGNMENT_OF( double )
- optional_OUTPUT_ALIGNMENT_OF( long double )
- optional_OUTPUT_ALIGNMENT_OF( Struct )
- "";
-}
-#undef optional_OUTPUT_ALIGNMENT_OF
-#endif
-
-#define optional_OUTPUT_SIZEOF( type ) \
- "sizeof( optional<" #type "> ): " << \
- sizeof( optional< type> ) << " (" << sizeof(type) << ")\n" <<
-
-TEST(OptionalTest, ShowSizeDependingOnBaseType)
-{
- std::cout <<
-#if !optional_USES_STD_OPTIONAL
- "sizeof( nonstd::optional_lite::detail::storage_t<char> ): " <<
- sizeof( nonstd::optional_lite::detail::storage_t<char> ) << "\n" <<
-#endif
- optional_OUTPUT_SIZEOF( char )
- optional_OUTPUT_SIZEOF( short )
- optional_OUTPUT_SIZEOF( int )
- optional_OUTPUT_SIZEOF( long )
- optional_OUTPUT_SIZEOF( float )
- optional_OUTPUT_SIZEOF( double )
- optional_OUTPUT_SIZEOF( long double )
- optional_OUTPUT_SIZEOF( Struct )
- "";
-}
-#undef optional_OUTPUT_SIZEOF
-
-// GMX modification to suppress Doxygen checking
-#endif // DOXYGEN
-
-} // namespace gmx
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-// Copyright 2017-2019 Martin Moene
-//
-// https://github.com/martinmoene/string-view-lite
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-/*! \internal \file
- * \brief Tests for C++14-compatible implementation of std::string_view.
- *
- * These tests are similer to those used in commit bf5824916b6895ccab0dbc2431520ee3b6d4f27f of
- * https://github.com/martinmoene/string_view-lite.git. The code has not
- * been linted with uncrustify so that any future updates to this
- * active repo can be incorporated easily, and //NOLINT comments added
- * to suppress clang-tidy warnings. The form of those
- * changes have been made to simplify the contents, while making it
- * easy to import any bug fixes that may appear in the source
- * repository.
- *
- * \todo Remove when requiring C++17, which has a standardized version
- * of std::string_view.
- *
- * \author Paul Bauer <paul.bauer.q@gmail.com>
- * \ingroup module_compat
- */
-#include "gmxpre.h"
-
-#include "gromacs/compat/string_view.h"
-
-#include <initializer_list>
-#include <iostream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-#include "gromacs/utility/strconvert.h"
-
-// GMX modification to suppress Doxygen checking
-#ifndef DOXYGEN
-
-namespace gmx
-{
-
-using namespace compat;
-
-namespace {
-
-template< class T >
-T * data( std::vector<T> & v )
-{
-#if nssv_CPP11_OR_GREATER
- return v.data();
-#else
- return &v[0];
-#endif
-}
-
-#define nssv_STD_SV_OR( expr ) ( nssv_USES_STD_STRING_VIEW || (expr) )
-
-typedef string_view::size_type size_type;
-
-// 24.4.2.1 Construction and assignment:
-
-TEST(StringViewTest, CanDefaultConstructEmptyView)
-{
- SCOPED_TRACE( "string_view: Allows to default construct an empty string_view" );
-
- string_view sv;
-
- // use parenthesis with data() to prevent lest from using sv.data() as C-string:
-
- EXPECT_TRUE( sv.size() == size_type( 0 ) );
- EXPECT_TRUE( (sv.data() == nssv_nullptr) );
-}
-
-TEST(StringViewTest, CanConstructFromPointerAndSize)
-{
- SCOPED_TRACE( "string_view: Allows to construct from pointer and size" );
-
- string_view sv( "hello world", 5 );
-
- EXPECT_TRUE( sv.size() == size_type( 5 ) );
- EXPECT_TRUE( *(sv.data() + 0) == 'h' );
- EXPECT_TRUE( *(sv.data() + 4) == 'o' );
-}
-
-TEST(StringViewTest, CanConstructFromCString)
-{
- SCOPED_TRACE( "string_view: Allows to construct from C-string" );
-
- string_view sv( "hello world" );
-
- EXPECT_TRUE( sv.size() == size_type( 11 ) );
- EXPECT_TRUE( *(sv.data() + 0) == 'h' );
- EXPECT_TRUE( *(sv.data() + 10) == 'd' );
-}
-
-TEST(StringViewTest, CanCopyConstructFromEmptyView)
-{
- SCOPED_TRACE( "string_view: Allows to copy-construct from empty string_view" );
-
- string_view sv1;
-
- string_view sv2( sv1 );
-
- // use parenthesis with data() to prevent lest from using sv.data() as C-string:
-
- EXPECT_TRUE( sv2.size() == size_type( 0 ) );
- EXPECT_TRUE( (sv2.data() == nssv_nullptr) );
-}
-
-TEST(StringViewTest, CanCopyConstructFromNonEmptyView)
-{
- SCOPED_TRACE( "string_view: Allows to copy-construct from non-empty string_view" );
-
- string_view sv1( "hello world", 5 );
-
- string_view sv2( sv1 );
-
- EXPECT_TRUE( sv2.size() == sv1.size() );
- EXPECT_TRUE( (sv2.data() == sv1.data()) );
- EXPECT_TRUE( *(sv2.data() + 0) == 'h' );
- EXPECT_TRUE( *(sv2.data() + 4) == 'o' );
-}
-
-// Assignment:
-
-TEST(StringViewTest, CanCopyAssingFromEmptyView)
-{
- SCOPED_TRACE( "string_view: Allows to copy-assign from empty string_view" );
-
- string_view sv1;
- string_view sv2;
-
- sv2 = sv1;
-
- // use parenthesis with data() to prevent lest from using sv.data() as C-string:
-
- EXPECT_TRUE( sv2.size() == size_type( 0 ) );
- EXPECT_TRUE( (sv2.data() == nssv_nullptr) );
-}
-
-TEST(StringViewTest, CanCopyAssingFromNonEmptyView)
-{
- SCOPED_TRACE( "string_view: Allows to copy-assign from non-empty string_view" );
-
- string_view sv1( "hello world", 5 );
- string_view sv2;
-
- sv2 = sv1;
-
- // use parenthesis with data() to prevent lest from using sv.data() as C-string:
-
- EXPECT_TRUE( sv2.size() == sv1.size() );
- EXPECT_TRUE( (sv2.data() == sv1.data()) );
- EXPECT_TRUE( *(sv2.data() + 0) == 'h' );
- EXPECT_TRUE( *(sv2.data() + 4) == 'o' );
-}
-
-// 24.4.2.2 Iterator support:
-
-TEST(StringViewTest, AllowForwardIteration)
-{
- SCOPED_TRACE( "string_view: Allows forward iteration" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( string_view::iterator pos = sv.begin(); pos != sv.end(); ++pos )
- {
- typedef std::iterator_traits< string_view::iterator >::difference_type difference_type;
-
- difference_type i = std::distance( sv.begin(), pos );
- EXPECT_TRUE( *pos == *(sv.data() + i) );
- }
-}
-
-TEST(StringViewTest, AllowConstForwardIteration)
-{
- SCOPED_TRACE( "string_view: Allows const forward iteration" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( string_view::const_iterator pos = sv.begin(); pos != sv.end(); ++pos )
- {
- typedef std::iterator_traits< string_view::const_iterator >::difference_type difference_type;
-
- difference_type i = std::distance( sv.cbegin(), pos );
- EXPECT_TRUE( *pos == *(sv.data() + i) );
- }
-}
-
-TEST(StringViewTest, AllowReverseIteration)
-{
- SCOPED_TRACE( "string_view: Allows reverse iteration" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( string_view::reverse_iterator pos = sv.rbegin(); pos != sv.rend(); ++pos )
- {
- typedef std::iterator_traits< string_view::reverse_iterator >::difference_type difference_type;
-
- difference_type dist = std::distance( sv.rbegin(), pos );
- EXPECT_TRUE( *pos == *(sv.data() + sv.size() - 1 - dist) );
- }
-}
-
-TEST(StringViewTest, AllowConstReverseIteration)
-{
- SCOPED_TRACE( "string_view: Allows const reverse iteration" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( string_view::const_reverse_iterator pos = sv.crbegin(); pos != sv.crend(); ++pos )
- {
- typedef std::iterator_traits< string_view::const_reverse_iterator >::difference_type difference_type;
-
- difference_type dist = std::distance( sv.crbegin(), pos );
- EXPECT_TRUE( *pos == *(sv.data() + sv.size() - 1 - dist) );
- }
-}
-
-// 24.4.2.3 Capacity:
-
-TEST(StringViewTest, CanObtainSizeFromViewViaSize)
-{
- SCOPED_TRACE( "string_view: Allows to obtain the size of the view via size()" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.size() == std::char_traits<char>::length(hello) );
-}
-
-TEST(StringViewTest, CanObtainSizeFromViewViaLength)
-{
- SCOPED_TRACE( "string_view: Allows to obtain the size of the view via length()" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.length() == std::char_traits<char>::length(hello) );
-}
-
-TEST(StringViewTest, CanObtainMaxSizeViaMaxSize)
-{
- SCOPED_TRACE( "string_view: Allows to obtain the maximum size a view can be via max_size()" );
-
- // "large"
- EXPECT_TRUE( string_view().max_size() >= (std::numeric_limits< string_view::size_type >::max)() / 10 );
-}
-
-TEST(StringViewTest, CanCheckForEmptyStringWithEmpty)
-{
- SCOPED_TRACE( "string_view: Allows to check for an empty string_view via empty()" );
-
- string_view sve;
- string_view svne("hello");
-
- EXPECT_TRUE( sve.size() == size_type( 0 ) );
- EXPECT_TRUE( sve.empty() );
- EXPECT_FALSE( svne.empty() );
-}
-
-// 24.4.2.4 Element access:
-
-TEST(StringViewTest, CanAccessElementViaArrayIndex)
-{
- SCOPED_TRACE( "string_view: Allows to observe an element via array indexing" );
-
- // Requires: index < sv.size()
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( size_type i = 0; i < sv.size(); ++i )
- {
- EXPECT_TRUE( sv[i] == hello[i] );
- }
-}
-
-TEST(StringViewTest, CanAccessElementViaAt)
-{
- SCOPED_TRACE( "string_view: Allows to observe an element via at()" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- for ( size_type i = 0; i < sv.size(); ++i )
- {
- EXPECT_TRUE( sv.at(i) == hello[i] );
- }
-}
-
-TEST(StringViewTest, ThrowsOnOutOfBoundsAccess)
-{
- SCOPED_TRACE( "string_view: Throws at observing an element via at() with an index of size() or larger" );
-
- string_view sv("hello");
-
- EXPECT_ANY_THROW( sv.at( sv.size() ) );
- EXPECT_NO_THROW( sv.at( sv.size() - 1 ) );
-}
-
-TEST(StringViewTest, CanAccessAllElementsViaData)
-{
- SCOPED_TRACE( "string_view: Allows to observe elements via data()" );
-
- char hello[] = "hello";
- string_view sv( hello );
-
- EXPECT_TRUE( *sv.data() == *sv.begin() );
-
- for ( size_type i = 0; i < sv.size(); ++i )
- {
- EXPECT_TRUE( sv.data()[i] == hello[i] );
- }
-}
-
-TEST(StringViewTest, DataFromEmptyStringIsNullptr)
-{
- SCOPED_TRACE( "string_view: Yields nullptr (or NULL) with data() for an empty string_view" );
-
- string_view sv;
-
- // use parenthesis with data() to prevent lest from using sv.data() as C-string:
-
- EXPECT_TRUE( (sv.data() == nssv_nullptr) );
-}
-
-// 24.4.2.5 Modifiers:
-
-TEST(StringViewTest, CanRemovePrefix)
-{
- SCOPED_TRACE( "string_view: Allows to remove a prefix of n elements" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- sv.remove_prefix( 6 );
-
- EXPECT_TRUE( sv.size() == size_type( 5 ) );
- EXPECT_TRUE( std::equal( sv.begin(), sv.end(), hello + 6) );
-}
-
-TEST(StringViewTest, CanRemoveSuffix)
-{
- SCOPED_TRACE( "string_view: Allows to remove a suffix of n elements" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- sv.remove_suffix( 6 );
-
- EXPECT_TRUE( sv.size() == size_type( 5 ) );
- EXPECT_TRUE( std::equal( sv.begin(), sv.end(), hello ) );
-}
-
-TEST(StringViewTest, CanSwapWithOtherView)
-{
- SCOPED_TRACE( "string_view: Allows to swap with other string_view" );
-
- char hello[] = "hello";
- char world[] = "world";
- string_view sv1( hello );
- string_view sv2( world );
-
- sv1.swap( sv2 );
-
- EXPECT_TRUE( std::equal( sv1.begin(), sv1.end(), world ) );
- EXPECT_TRUE( std::equal( sv2.begin(), sv2.end(), hello ) );
-}
-
-// 24.4.2.6 String operations:
-
-TEST(StringViewTest, CanCopySubstringWithCopy)
-{
- SCOPED_TRACE( "string_view: Allows to copy a substring of length n, starting at position pos (default: 0) via copy()" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- {
- std::vector<string_view::value_type> vec( sv.size() );
-
- sv.copy( data(vec), vec.size() );
-
- EXPECT_TRUE( std::equal( vec.begin(), vec.end(), hello ) );
- }{
- std::size_t offset = 3U; std::size_t length = 4U;
- std::vector<string_view::value_type> vec( length );
-
- sv.copy( data(vec), length, offset );
-
- EXPECT_TRUE( std::equal( vec.begin(), vec.end(), hello + offset ) );
- }
-}
-
-TEST(StringViewTest, ThrowsOnOutOfBoundsCopy)
-{
- SCOPED_TRACE( "string_view: Throws if requested position of copy() exceeds string_view's size()" );
-
- string_view sv("hello world");
- std::vector<string_view::value_type> vec( sv.size() );
-
- EXPECT_ANY_THROW( sv.copy( data(vec), sv.size() - 4, sv.size() + 1 ) );
- EXPECT_NO_THROW( sv.copy( data(vec), sv.size() - 4, sv.size() + 0 ) );
-}
-
-TEST(StringViewTest, CanObtainSubstringWithSubstr)
-{
- SCOPED_TRACE( "string_view: Allow to obtain a sub string, starting at position pos (default: 0) and of length n (default full), via substr()" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- {
-#if nssv_USES_STD_STRING_VIEW && defined(__GNUC__)
- EXPECT_TRUE( !!"std::string_view::substr(), with default pos, count is not available with GNU C" );
-#else
- EXPECT_TRUE( std::equal( sv.begin(), sv.end(), sv.substr().begin() ) );
-#endif
- }{
- string_view subv = sv.substr( 6 );
-
- EXPECT_TRUE( std::equal( subv.begin(), subv.end(), hello + 6 ) );
- }{
- string_view subv = sv.substr( 3, 4 );
-
- EXPECT_TRUE( std::equal( subv.begin(), subv.end(), hello + 3 ) );
- }
-}
-
-TEST(StringViewTest, ThrowsOnOutOfBoundsSubstr)
-{
- SCOPED_TRACE( "string_view: Throws if requested position of substr() exceeds string_view's size()" );
-
- string_view sv("hello world");
-
- EXPECT_ANY_THROW( sv.substr( sv.size() + 1 ) );
- EXPECT_NO_THROW( sv.substr( sv.size() + 0 ) );
-}
-
-TEST(StringViewTest, CanLexicallyCompareViewWithCompare)
-{
- SCOPED_TRACE( "string_view: Allows to lexically compare to another string_view via compare(), (1)" );
-
- char hello[] = "hello";
- char world[] = "world";
-
- EXPECT_TRUE( string_view( hello ).compare( string_view( hello ) ) == 0 );
- EXPECT_TRUE( string_view( hello ).compare( string_view( world ) ) < 0 );
- EXPECT_TRUE( string_view( world ).compare( string_view( hello ) ) > 0 );
-
- char hello_sp[] = "hello ";
-
- EXPECT_TRUE( string_view( hello ).compare( string_view( hello_sp ) ) < 0 );
- EXPECT_TRUE( string_view( hello_sp ).compare( string_view( hello ) ) > 0 );
-}
-
-TEST(StringViewTest, CanCompareEmptyViewsWIthCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare empty string_views as equal via compare(), (1)" );
-
- EXPECT_TRUE( string_view().compare( string_view() ) == 0 );
-}
-
-TEST(StringViewTest, CanCompareSubStringWithViewViaCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare a sub string to another string_view via compare(), (2)" );
-
- string_view sv1("hello world");
- string_view sv2("world");
-
- EXPECT_TRUE( sv1.compare ( 0, sv1.length(), sv1 ) == 0 );
- EXPECT_TRUE( sv1.compare ( 6, 5, sv2 ) == 0 );
- EXPECT_TRUE( sv1.compare ( 0, 5, sv2 ) < 0 );
- EXPECT_TRUE( sv2.compare ( 0, 5, sv1 ) > 0 );
-}
-
-TEST(StringViewTest, CanCompareSubStringWithSubStringViewViaCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare a sub string to another string_view sub string via compare(), (3)" );
-
- string_view sv1("hello world");
-
- EXPECT_TRUE( sv1.compare ( 0, sv1.length(), sv1 ) == 0 );
- EXPECT_TRUE( sv1.compare ( 6, 5, sv1, 6, 5 ) == 0 );
- EXPECT_TRUE( sv1.compare ( 0, 5, sv1, 6, 5 ) < 0 );
- EXPECT_TRUE( sv1.compare ( 6, 5, sv1, 0, 5 ) > 0 );
-}
-
-TEST(StringViewTest, CanCompareToCStringViaCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare to a C-string via compare(), (4)" );
-
- char hello[] = "hello";
- char world[] = "world";
-
- EXPECT_TRUE( string_view( hello ).compare( hello ) == 0 );
- EXPECT_TRUE( string_view( hello ).compare( world ) < 0 );
- EXPECT_TRUE( string_view( world ).compare( hello ) > 0 );
-}
-
-TEST(StringViewTest, CanCompareSubStringToCStringViaCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare a sub string to a C-string via compare(), (5)" );
-
- char hello[] = "hello world";
- char world[] = "world";
-
- EXPECT_TRUE( string_view( hello ).compare( 6, 5, world ) == 0 );
- EXPECT_TRUE( string_view( hello ).compare( world ) < 0 );
- EXPECT_TRUE( string_view( world ).compare( hello ) > 0 );
-}
-
-TEST(StringViewTest, CanCompareSubStringToCStringPrefixViaCompare)
-{
- SCOPED_TRACE( "string_view: Allows to compare a sub string to a C-string prefix via compare(), (6)" );
-
- char hello[] = "hello world";
- char world[] = "world";
-
- EXPECT_TRUE( string_view( hello ).compare( 6, 5, world, 5 ) == 0 );
- EXPECT_TRUE( string_view( hello ).compare( 0, 5, world, 5 ) < 0 );
- EXPECT_TRUE( string_view( hello ).compare( 6, 5, hello, 5 ) > 0 );
-}
-
-// 24.4.2.7 Searching:
-
-#if nssv_HAVE_STARTS_WITH
-
-TEST(StringViewTest, CanCheckForPrefixViewViaStartsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a prefix string_view via starts_with(), (1)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).starts_with( string_view( hello ) ) );
- EXPECT_TRUE( string_view( hello ).starts_with( string_view("hello") ) );
- EXPECT_FALSE( string_view( hello ).starts_with( string_view("world") ) );
-}
-
-TEST(StringViewTest, CanCheckForPrefixCharacterViaStartsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a prefix character via starts_with(), (2)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).starts_with( 'h' ) );
- EXPECT_FALSE( string_view( hello ).starts_with( 'e' ) );
-}
-
-TEST(StringViewTest, CanCheckForPrefixCStringViaStartsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a prefix C-string via starts_with(), (3)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).starts_with( hello ) );
- EXPECT_TRUE( string_view( hello ).starts_with("hello") );
- EXPECT_FALSE( string_view( hello ).starts_with("world") );
-}
-
-#endif // nssv_HAVE_STARTS_WITH
-
-#if nssv_HAVE_ENDS_WITH
-
-TEST(StringViewTest, CanCheckForSuffixViewViaEndsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a suffix string_view via ends_with(), (1)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).ends_with( string_view( hello ) ) );
- EXPECT_TRUE( string_view( hello ).ends_with( string_view("world") ) );
- EXPECT_FALSE( string_view( hello ).ends_with( string_view("hello") ) );
-}
-
-TEST(StringViewTest, CanCheckForSuffixCharacterViaEndsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a suffix character via ends_with(), (2)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).ends_with( 'd' ) );
- EXPECT_FALSE( string_view( hello ).ends_with( 'l' ) );
-}
-
-TEST(StringViewTest, CanCheckForSuffixCStringViaEndsWith)
-{
- SCOPED_TRACE( "string_view: Allows to check for a suffix C-string via ends_with(), (3)" );
-
- char hello[] = "hello world";
-
- EXPECT_TRUE( string_view( hello ).ends_with( hello ) );
- EXPECT_TRUE( string_view( hello ).ends_with("world") );
- EXPECT_FALSE( string_view( hello ).ends_with("hello") );
-}
-
-#endif // nssv_HAVE_ENDS_WITH
-
-TEST(StringViewTest, CanSearchForViewSubstrViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search for a string_view substring, starting at position pos (default: 0) via find(), (1)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find( sv ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find( sv, 1 ) == string_view::npos );
- EXPECT_TRUE( sv.find( string_view("world" ) ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find( string_view("world" ), 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find( string_view("world" ), 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForCharacterViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search for a character, starting at position pos (default: 0) via find(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find('h' ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find('h', 1 ) == string_view::npos );
- EXPECT_TRUE( sv.find('w' ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find('w', 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find('w', 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForCStringSubstringViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search for a C-string substring, starting at position pos and of length n via find(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find( hello , 0, sv.size() ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find( hello , 1, sv.size() ) == string_view::npos );
- EXPECT_TRUE( sv.find("world", 0, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find("world", 6, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find("world", 7, 4 ) == string_view::npos );
- EXPECT_TRUE( sv.find("world", 3, 0 ) == size_type( 3 ) );
-}
-
-TEST(StringViewTest, CanSearchForCStringSubstringViaFindWithDefaultPos)
-{
- SCOPED_TRACE( "string_view: Allows to search for a C-string substring, starting at position pos (default: 0) via find(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find( hello ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find( hello , 1 ) == string_view::npos );
- EXPECT_TRUE( sv.find("world" ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find("world", 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find("world", 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForViewSubstrViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for a string_view substring, starting at position pos (default: npos) via rfind(), (1)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.rfind( sv ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind( sv, 3 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind( string_view( ) ) == size_type(11 ) );
- EXPECT_TRUE( sv.rfind( string_view("world" ) ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind( string_view("world" ), 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind( string_view("world" ), 5 ) == string_view::npos );
- EXPECT_TRUE( sv.rfind( string_view("hello world, a longer text" ) ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForCharacterViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for a character, starting at position pos (default: npos) via rfind(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.rfind('h' ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind('e' ) == size_type( 1 ) );
- EXPECT_TRUE( sv.rfind('e', 0 ) == string_view::npos );
- EXPECT_TRUE( sv.rfind('w' ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind('w', 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind('w', 5 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForCStringSubstringViaFind)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for a C-string substring, starting at position pos and of length n via rfind(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.rfind( hello ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind( hello , 0, 5 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind( hello , 1, 5 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind("world", 10, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind("world", 6, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind("world", 5, 5 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForCStringSubstringViaFindWithDefaultPos)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for a C-string substring, starting at position pos (default: 0) via rfind(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.rfind( hello ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind( hello , 3 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.rfind("world" ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind("world", 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.rfind("world", 5 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstOccurenceOfAnyCharacterInView)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first occurrence of any of the characters specified in a string view, starting at position pos (default: 0) via find_first_of(), (1)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_of( sv ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_first_of( sv, 3 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_first_of( string_view("xwo" ) ) == size_type( 4 ) );
- EXPECT_TRUE( sv.find_first_of( string_view("wdx" ), 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of( string_view("wxy" ), 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstOccurenceOfCharacter)
-{
- SCOPED_TRACE( "string_view: Allows to search for a character, starting at position pos (default: 0) via find_first_of(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_of('h' ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_first_of('h', 1 ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_of('w' ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of('w', 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of('w', 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstOccurenceOfCharactersInCStringInLenght)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first occurrence of any of the characters specified in a C-string, starting at position pos and of length n via find_first_of(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_of( hello , 0, sv.size() ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_first_of( hello , 1, sv.size() ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 0, 3 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 6, 3 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 7, 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_of( "xyw", 0, 2 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstOccurenceOfCharactersInCString)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first occurrence of any of the characters specified in a C-string, starting at position pos via find_first_of(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_of( hello , 0 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_first_of( hello , 1 ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 0 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_of( "xwy", 7 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForLastOccurenceOfAnyCharacterInView)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the last occurrence of any of the characters specified in a string view, starting at position pos (default: npos) via find_last_of(), (1)" );
-
- char hello[] = "hello world";
- char empty[] = "";
- string_view sv( hello );
- string_view sve( empty );
-
- EXPECT_TRUE( sv.find_last_of( sv ) == size_type( 10 ) );
- EXPECT_TRUE( sv.find_last_of( sv, 3 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_of( string_view("xwo" ) ) == size_type( 7 ) );
- EXPECT_TRUE( sv.find_last_of( string_view("wdx" ), 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of( string_view("wxy" ), 7 ) == size_type( 6 ) );
-
- EXPECT_TRUE( sve.find_last_of( string_view("x") ) == string_view::npos ); // issue 20 (endless loop)
-}
-
-TEST(StringViewTest, CanBackwardsSearchForLastOccurenceOfCharacter)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for a character, starting at position pos (default: 0) via find_last_of(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_of('h' ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_last_of('l', 1 ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_of('w' ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of('w', 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of('w', 5 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForLastOccurenceOfCharactersInCStringInLenght)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first occurrence of any of the characters specified in a C-string, starting at position pos and of length n via find_last_of(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_of( hello , 0, sv.size() ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_last_of( hello , 1, sv.size() ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_last_of("xwy", 10, 3 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of("xwy", 6, 3 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of("xwy", 5, 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_of("xyw", 10, 2 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForLastOccurenceOfCharactersInCString)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first occurrence of any of the characters specified in a C-string, starting at position pos via find_last_of(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_of( hello , 0 ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_last_of( hello , 1 ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_last_of( "xwy", 10 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of( "xwy", 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_last_of( "xwy", 5 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstNotFoundCharacter)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first character not specified in a string view, starting at position pos (default: 0) via find_first_not_of(), (1)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_not_of( sv ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( sv, 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( string_view("helo " ) ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( string_view("helo " ), 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( string_view("helo " ), 7 ) == size_type( 8 ) );
- EXPECT_TRUE( sv.find_first_not_of( string_view("helo wr" ) ) == size_type( 10 ) );
-}
-
-TEST(StringViewTest, CanSearchForFirstNonMatchingCharacter)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first character not equal to the specified character, starting at position pos (default: 0) via find_first_not_of(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_not_of('h' ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_first_not_of('h', 1 ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_first_not_of('w' ) == size_type( 0 ) );
- EXPECT_TRUE( sv.find_first_not_of('w', 6 ) == size_type( 7 ) );
- EXPECT_TRUE( sv.find_first_not_of('d', 10 ) == string_view::npos );
-}
-
-TEST(StringViewTest, CanSearchForFirstNonEqualToAnyCharacterInCStringInLength)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first character not equal to any of the characters specified in a C-string, starting at position pos and of length n via find_first_not_of(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_not_of( hello, 0, sv.size() ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( hello, 3, sv.size() ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 0, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 6, 5 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 7, 5 ) == size_type( 8 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo wr", 0, 7 ) == size_type( 10 ) );
- EXPECT_TRUE( sv.find_first_not_of( "he" , 0, 1 ) == size_type( 1 ) );
-}
-
-TEST(StringViewTest, CanSearchForFirstNonEqualToAnyCharacterInCString)
-{
- SCOPED_TRACE( "string_view: Allows to search for the first character not equal to any of the characters specified in a C-string, starting at position pos via find_first_not_of(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_first_not_of( hello , 0 ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( hello , 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 0 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 6 ) == size_type( 6 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo " , 7 ) == size_type( 8 ) );
- EXPECT_TRUE( sv.find_first_not_of( "helo wr", 0 ) == size_type( 10 ) );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForForstNonFoundCharacterInView)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first character not specified in a string view, starting at position pos (default: npos) via find_last_not_of(), (1)" );
-
- char hello[] = "hello world";
- char empty[] = "";
- string_view sv( hello );
- string_view sve( empty );
-
- EXPECT_TRUE( sv.find_last_not_of( sv ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( sv, 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( string_view("world " ) ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_last_not_of( string_view("heo " ), 4 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( string_view("heo " ), 3 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( string_view("heo " ), 2 ) == size_type( 2 ) );
- EXPECT_TRUE( sv.find_last_not_of( string_view("x" ) ) == size_type( 10 ) );
-
- EXPECT_TRUE( sve.find_last_not_of( string_view("x") ) == string_view::npos ); // issue 20 (endless loop)
-}
-
-TEST(StringViewTest, CanBackwardsSearchForFirstNonMatchingCharacter)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first character not equal to the specified character, starting at position pos (default: npos) via find_last_not_of(), (2)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_not_of('d' ) == size_type( 9 ) );
- EXPECT_TRUE( sv.find_last_not_of('d', 10 ) == size_type( 9 ) );
- EXPECT_TRUE( sv.find_last_not_of('d', 9 ) == size_type( 9 ) );
- EXPECT_TRUE( sv.find_last_not_of('d', 8 ) == size_type( 8 ) );
- EXPECT_TRUE( sv.find_last_not_of('d', 0 ) == size_type( 0 ) );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForFirstNonEqualToAnyCharacterInCStringInLength)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first character not equal to any of the characters specified in a C-string, starting at position pos and of length n via find_last_not_of(), (3)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_not_of( hello, 0, sv.size() ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( hello, 3, sv.size() ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( "world ", 10, 6 ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 4, 4 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 3, 4 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 2, 4 ) == size_type( 2 ) );
- EXPECT_TRUE( sv.find_last_not_of( "x" ) == size_type( 10 ) );
-}
-
-TEST(StringViewTest, CanBackwardsSearchForFirstNonEqualToAnyCharacterInCString)
-{
- SCOPED_TRACE( "string_view: Allows to search backwards for the first character not equal to any of the characters specified in a C-string, starting at position pos via find_last_not_of(), (4)" );
-
- char hello[] = "hello world";
- string_view sv( hello );
-
- EXPECT_TRUE( sv.find_last_not_of( hello , 0 ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( hello , 3 ) == string_view::npos );
- EXPECT_TRUE( sv.find_last_not_of( "world ", 10 ) == size_type( 1 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 4 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 3 ) == size_type( 3 ) );
- EXPECT_TRUE( sv.find_last_not_of( "heo " , 2 ) == size_type( 2 ) );
- EXPECT_TRUE( sv.find_last_not_of( "x" ) == size_type( 10 ) );
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteralSV)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view, wstring_view, u16string_view, u32string_view via literal \"sv\"" );
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_STD_DEFINED_LITERALS )
- using namespace nonstd::literals::string_view_literals;
-
- string_view sv1 = "abc"sv;
- wstring_view sv2 = L"abc"sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 3 ) );
-
-#if nssv_HAVE_WCHAR16_T
- u16string_view sv3 = u"abc"sv;
- EXPECT_TRUE( sv3.size() == size_type( 3 ) );
-#endif
-#if nssv_HAVE_WCHAR32_T
- u32string_view sv4 = U"abc"sv;
- EXPECT_TRUE( sv4.size() == size_type( 3 ) );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (nssv_CONFIG_STD_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteralSVInLiteralsStringViewLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"sv\", using namespace gmx::compat::literals::string_view_literals" );
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_STD_DEFINED_LITERALS )
- using namespace gmx::compat::literals::string_view_literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (nssv_CONFIG_STD_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteralSVInStringViewLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"sv\", using namespace gmx::compat::string_view_literals" );
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_STD_DEFINED_LITERALS )
-#if nssv_STD_SV_OR( nssv_HAVE_INLINE_NAMESPACE )
- using namespace gmx::compat::string_view_literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Inline namespaces for literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (nssv_CONFIG_STD_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteralSVInLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"sv\", using namespace gmx::compat::literals" );
-
-#if nssv_CONFIG_STD_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_STD_DEFINED_LITERALS )
-#if nssv_STD_SV_OR( nssv_HAVE_INLINE_NAMESPACE )
- using namespace gmx::compat::literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Inline namespaces for literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator 'sv' for string_view not available (nssv_CONFIG_STD_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteral_SV)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view, wstring_view, u16string_view, u32string_view via literal \"_sv\"" );
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_USER_DEFINED_LITERALS )
- using namespace gmx::compat::literals::string_view_literals;
-
- string_view sv1 = "abc"_sv;
- wstring_view sv2 = L"abc"_sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 3 ) );
-
-#if nssv_HAVE_WCHAR16_T
- u16string_view sv3 = u"abc"_sv;
- EXPECT_TRUE( sv3.size() == size_type( 3 ) );
-#endif
-#if nssv_HAVE_WCHAR32_T
- u32string_view sv4 = U"abc"_sv;
- EXPECT_TRUE( sv4.size() == size_type( 3 ) );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (nssv_CONFIG_USR_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteral_SVInLiteralsStringViewLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"_sv\", using namespace gmx::compat::literals::string_view_literals" );
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_USER_DEFINED_LITERALS )
- using namespace gmx::compat::literals::string_view_literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"_sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (nssv_CONFIG_USR_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteral_SVInStringViewLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"_sv\", using namespace gmx::compat::string_view_literals" );
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_USER_DEFINED_LITERALS )
-#if nssv_STD_SV_OR( nssv_HAVE_INLINE_NAMESPACE )
- using namespace gmx::compat::string_view_literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"_sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Inline namespaces for literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (nssv_CONFIG_USR_SV_OPERATOR=0)." );
-#endif
-}
-
-TEST(StringViewTest, CanCreateViewWithLiteral_SVInLiteralsNamespace)
-{
- SCOPED_TRACE( "string_view: Allows to create a string_view via literal \"_sv\", using namespace gmx::compat::literals" );
-
-#if nssv_CONFIG_USR_SV_OPERATOR
-#if nssv_STD_SV_OR( nssv_HAVE_USER_DEFINED_LITERALS )
-#if nssv_STD_SV_OR( nssv_HAVE_INLINE_NAMESPACE )
- using namespace gmx::compat::literals;
-
- string_view sv1 = "abc\0\0def";
- string_view sv2 = "abc\0\0def"_sv;
-
- EXPECT_TRUE( sv1.size() == size_type( 3 ) );
- EXPECT_TRUE( sv2.size() == size_type( 8 ) );
-#else
- EXPECT_TRUE( !!"Inline namespaces for literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Literal operator '_sv' for string_view not available (nssv_CONFIG_USR_SV_OPERATOR=0)." );
-#endif
-}
-
-// 24.4.3 Non-member comparison functions:
-
-TEST(StringViewTest, CanCompareToViews)
-{
- SCOPED_TRACE( "string_view: Allows to compare a string_view with another string_view" );
-
- char s[] = "hello";
- char t[] = "world";
- string_view sv( s );
- string_view tv( t );
-
- EXPECT_TRUE( sv.length() == size_type( 5 ) );
- EXPECT_TRUE( tv.length() == size_type( 5 ) );
-
- EXPECT_TRUE( sv == sv );
- EXPECT_TRUE( sv != tv );
- EXPECT_TRUE( sv <= sv );
- EXPECT_TRUE( sv <= tv );
- EXPECT_TRUE( sv < tv );
- EXPECT_TRUE( tv >= tv );
- EXPECT_TRUE( tv >= sv );
- EXPECT_TRUE( tv > sv );
-}
-
-TEST(StringViewTest, CanCompareViewToImplicitlyConvertedView)
-{
- SCOPED_TRACE( "string_view: Allows to compare a string_view with an object with implicit conversion to string_view" );
-
-#if nssv_CPP11_OR_GREATER
-#if defined(_MSC_VER) && _MSC_VER != 1900
- char s[] = "hello";
- string_view sv( s );
-
- EXPECT_TRUE( sv == "hello" );
- EXPECT_TRUE( "hello" == sv );
-
- EXPECT_TRUE( sv != "world" );
- EXPECT_TRUE( "world" != sv );
-
- EXPECT_TRUE( sv <= "hello" );
- EXPECT_TRUE( "hello" <= sv );
- EXPECT_TRUE( sv <= "world" );
- EXPECT_TRUE( "aloha" <= sv );
-
- EXPECT_TRUE( sv < "world" );
- EXPECT_TRUE( "aloha" < sv );
-
- EXPECT_TRUE( sv >= "hello" );
- EXPECT_TRUE( "hello" >= sv );
- EXPECT_TRUE( sv >= "aloha" );
- EXPECT_TRUE( "world" >= sv );
-
- EXPECT_TRUE( sv > "aloha" );
- EXPECT_TRUE( "world" > sv );
-#else
- EXPECT_TRUE( !!"Comparison for types with implicit conversion to string_view not available (insufficient C++11 support of MSVC)." );
-#endif
-#else
- EXPECT_TRUE( !!"Comparison for types with implicit conversion to string_view not available (no C++11)." );
-#endif
-}
-
-TEST(StringViewTest, EmptyViewsCompareAsEqual)
-{
- SCOPED_TRACE( "string_view: Allows to compare empty string_view-s as equal" );
-
- string_view a, b;
-
- EXPECT_TRUE( a == b );
-}
-
-// 24.4.4 Inserters and extractors:
-
-TEST(StringViewTest, CanPrintViewToPutputStream)
-{
- SCOPED_TRACE ( "operator<<: Allows printing a string_view to an output stream" );
-
- std::ostringstream oss;
- char s[] = "hello";
- string_view sv( s );
-
- oss << sv << '\n'
- << std::right << std::setw(10) << sv << '\n'
- << sv << '\n'
- << std::setfill('.') << std::left << std::setw(10) << sv;
-
- EXPECT_TRUE( oss.str() == "hello\n hello\nhello\nhello....." );
-}
-
-// 24.4.5 Hash support (C++11):
-
-TEST(StringViewTest, HashOfViewIsEqualToHashOfString)
-{
- SCOPED_TRACE ( "std::hash<>: Hash value of string_view equals hash value of corresponding string object" );
-
-#if nssv_HAVE_STD_HASH
- EXPECT_TRUE( std::hash<string_view>()( "Hello, world!" ) == std::hash<std::string>()( "Hello, world!" ) );
-#else
- EXPECT_TRUE( !!"std::hash is not available (no C++11)" );
-#endif
-}
-
-TEST(StringViewTest, HashOfWStringViewIsEqualToHashOfString)
-{
- SCOPED_TRACE ( "std::hash<>: Hash value of wstring_view equals hash value of corresponding string object" );
-
-#if nssv_HAVE_STD_HASH
- EXPECT_TRUE( std::hash<wstring_view>()( L"Hello, world!" ) == std::hash<std::wstring>()( L"Hello, world!" ) );
-#else
- EXPECT_TRUE( !!"std::hash is not available (no C++11)" );
-#endif
-}
-
-TEST(StringViewTest, HashOfU16StringViewIsEqualToHashOfString)
-{
- SCOPED_TRACE ( "std::hash<>: Hash value of u16string_view equals hash value of corresponding string object" );
-
-#if nssv_HAVE_STD_HASH
-#if nssv_HAVE_WCHAR16_T
-#if nssv_HAVE_UNICODE_LITERALS
- EXPECT_TRUE( std::hash<u16string_view>()( u"Hello, world!" ) == std::hash<std::u16string>()( u"Hello, world!" ) );
-#else
- EXPECT_TRUE( !!"Unicode literal u\"...\" is not available (no C++11)" );
-#endif
-#else
- EXPECT_TRUE( !!"std::u16string is not available (no C++11)" );
-#endif
-#else
- EXPECT_TRUE( !!"std::hash is not available (no C++11)" );
-#endif
-}
-
-TEST(StringViewTest, HashOfU32StringViewIsEqualToHashOfString)
-{
- SCOPED_TRACE ( "std::hash<>: Hash value of u32string_view equals hash value of corresponding string object" );
-
-#if nssv_HAVE_STD_HASH
-#if nssv_HAVE_WCHAR16_T
-#if nssv_HAVE_UNICODE_LITERALS
- EXPECT_TRUE( std::hash<u32string_view>()( U"Hello, world!" ) == std::hash<std::u32string>()( U"Hello, world!" ) );
-#else
- EXPECT_TRUE( !!"Unicode literal U\"...\" is not available (no C++11)" );
-#endif
-#else
- EXPECT_TRUE( !!"std::u32string is not available (no C++11)" );
-#endif
-#else
- EXPECT_TRUE( !!"std::hash is not available (no C++11)" );
-#endif
-}
-
-// nonstd extension: conversions from and to std::basic_string
-
-TEST(StringViewExtensionTest, CanConstructViewFromString)
-{
- SCOPED_TRACE( "string_view: construct from std::string " "[extension]" );
-
-#if nssv_USES_STD_STRING_VIEW
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_USES_STD_STRING_VIEW=1)." );
-#elif nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
- char hello[] = "hello world";
- std::string s = hello;
-
- string_view sv( hello );
-
- EXPECT_TRUE( sv.size() == s.size() );
- EXPECT_TRUE( sv.compare( s ) == 0 );
-#else
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS=0)." );
-#endif
-}
-
-TEST(StringViewExtensionTest, CanConvertViewToStringViaExplicitOperator)
-{
- SCOPED_TRACE( "string_view: convert to std::string via explicit operator " "[extension]" );
-
-#if nssv_USES_STD_STRING_VIEW
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_USES_STD_STRING_VIEW=1)." );
-#elif nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
-#if nssv_HAVE_EXPLICIT_CONVERSION
- char hello[] = "hello world";
- string_view sv( hello );
-
- std::string s( sv );
-// std::string t{ sv };
-
- EXPECT_TRUE( sv.size() == s.size() );
- EXPECT_TRUE( sv.compare( s ) == 0 );
-#else
- EXPECT_TRUE( !!"explicit conversion is not available (no C++11)." );
-#endif
-#else
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS=0)." );
-#endif
-}
-
-TEST(StringViewExtensionTest, CanConvertViewToStringViaToString)
-{
- SCOPED_TRACE( "string_view: convert to std::string via to_string() " "[extension]" );
-
-#if nssv_USES_STD_STRING_VIEW
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_USES_STD_STRING_VIEW=1)." );
-#elif nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
- char hello[] = "hello world";
- string_view sv( hello );
-
- std::string s1 = sv.to_string();
-
- EXPECT_TRUE( sv.size() == s1.size() );
- EXPECT_TRUE( sv.compare( s1 ) == 0 );
-
- std::string s2 = sv.to_string( std::string::allocator_type() );
-
- EXPECT_TRUE( sv.size() == s2.size() );
- EXPECT_TRUE( sv.compare( s2 ) == 0 );
-#else
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS=0)." );
-#endif
-}
-
-TEST(StringViewExtensionTest, CanConvertViewToStringViaToStringFreeFunction)
-{
- SCOPED_TRACE( "to_string(): convert to std::string via to_string() " "[extension]" );
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
- char hello[] = "hello world";
- string_view sv( hello );
-
- std::string s1 = to_string( sv );
-
- EXPECT_TRUE( sv.size() == s1.size() );
- EXPECT_TRUE( sv.compare( s1 ) == 0 );
-
- std::string s2 = to_string( sv, std::string::allocator_type() );
-
- EXPECT_TRUE( sv.size() == s2.size() );
- EXPECT_TRUE( sv.compare( s2 ) == 0 );
-
-#else
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS=0)." );
-#endif
-}
-
-TEST(StringViewExtensionTest, CanConvertViewToStringViewViaToStringView)
-{
- SCOPED_TRACE( "to_string_view(): convert from std::string via to_string_view() " "[extension]" );
-
-#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
- char hello[] = "hello world";
- std::string s = hello;
-
- string_view sv = to_string_view( s );
-
- EXPECT_TRUE( sv.size() == s.size() );
- EXPECT_TRUE( sv.compare( s ) == 0 );
-#else
- EXPECT_TRUE( !!"Conversion to/from std::string is not available (nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS=0)." );
-#endif
-}
-
-} // anonymous namespace
-
-} // namespace gmx
-
-// GMX modification to suppress Doxygen checking
-#endif // DOXYGEN
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \ingroup module_coordinateio
*/
-
#include "gmxpre.h"
#include "coordinatefile.h"
#include <algorithm>
+#include "gromacs/options.h"
#include "gromacs/coordinateio/outputadapters.h"
#include "gromacs/coordinateio/requirements.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/math/vec.h"
+#include "gromacs/topology/mtop_util.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/utility/exceptions.h"
}
}
copy_mat(input.box, copy->box);
- copy->bPBC = input.bPBC;
- copy->ePBC = input.ePBC;
+ copy->bPBC = input.bPBC;
+ copy->pbcType = input.pbcType;
}
/*! \brief
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_COORDINATEIO_COORDINATEFILE_H
#define GMX_COORDINATEIO_COORDINATEFILE_H
-#include <algorithm>
+#include <string>
#include <utility>
#include "gromacs/coordinateio/ioutputadapter.h"
#include "gromacs/coordinateio/outputadaptercontainer.h"
-#include "gromacs/fileio/filetypes.h"
-#include "gromacs/fileio/trxio.h"
-#include "gromacs/selection/selection.h"
-#include "gromacs/topology/mtop_util.h"
-#include "gromacs/topology/topology.h"
+#include "gromacs/math/vectypes.h"
+#include "gromacs/topology/atoms.h"
+
+struct gmx_mtop_t;
+struct t_trxstatus;
namespace gmx
{
+class Selection;
class TrajectoryFrameWriter;
struct OutputRequirements;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
//! Enum class for setting basic flags in a t_trxframe
-enum class ChangeSettingType
+enum class ChangeSettingType : int
{
PreservedIfPresent,
Always,
- Never
+ Never,
+ Count
};
-//! Mapping for enums from \ref ChangeSettingType.
-const char* const cChangeSettingTypeEnum[] = { "preserved-if-present", "always", "never" };
//! Enum class for t_atoms settings
enum class ChangeAtomsType
PreservedIfPresent,
AlwaysFromStructure,
Never,
- Always
+ Always,
+ Count
};
-//! Mapping for enums from \ref ChangeAtomsType.
-const char* const cChangeAtomsTypeEnum[] = { "preserved-if-present", "always-from-structure",
- "never", "always" };
-
//! Enum class for setting fields new or not.
enum class ChangeFrameInfoType
{
PreservedIfPresent,
- Always
+ Always,
+ Count
};
-//! Mapping for enums from \ref ChangeFrameInfoType.
-const char* const cChangeFrameInfoTypeEnum[] = { "preserved-if-present", "always" };
//! Enum class for setting frame time from user input.
enum class ChangeFrameTimeType
PreservedIfPresent,
StartTime,
TimeStep,
- Both
+ Both,
+ Count
};
-//! Mapping for values from \ref ChangeFrameTimeType.
-const char* const cChangeFrameTimeTypeEnum[] = { "preserved-if-present", "starttime", "timestep",
- "both" };
-
-
} // namespace gmx
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-bool SetAtoms::haveFrameAtoms(const t_trxframe& input) const
+bool SetAtoms::haveFrameAtoms(const t_trxframe& input)
{
return input.bAtoms;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \param[in] input t_trxframe before we start modifying it.
*/
- bool haveFrameAtoms(const t_trxframe& input) const;
+ static bool haveFrameAtoms(const t_trxframe& input);
//! Test if the atoms data is available for writing.
bool haveAtoms(const t_trxframe& input) const
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/filenameoption.h"
#include "gromacs/options/ioptionscontainer.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
namespace gmx
{
+//! Mapping for enums from \ref ChangeSettingType.
+static const EnumerationArray<ChangeSettingType, const char*> c_changeSettingTypeNames = {
+ { "preserved-if-present", "always", "never" }
+};
+//! Mapping for enums from \ref ChangeAtomsType.
+static const EnumerationArray<ChangeAtomsType, const char*> c_changeAtomsTypeNames = {
+ { "preserved-if-present", "always-from-structure", "never", "always" }
+};
+/* Currently unused
+//! Mapping for enums from \ref ChangeFrameInfoType.
+static const EnumerationArray<ChangeFrameInfoType, const char*> c_changeFrameInfoTypeNames = { {
+"preserved-if-present", "always" } };
+//! Mapping for values from \ref ChangeFrameTimeType.
+static const EnumerationArray<ChangeFrameTimeType, const char*> c_changeFrameTimeTypeNames = { {
+"preserved-if-present", "starttime", "timestep", "both" } };
+*/
+
void OutputRequirementOptionDirector::initOptions(IOptionsContainer* options)
{
options->addOption(EnumOption<ChangeSettingType>("vel")
- .enumValue(cChangeSettingTypeEnum)
+ .enumValue(c_changeSettingTypeNames)
.store(&velocity_)
.description("Save velocities from frame if possible"));
options->addOption(EnumOption<ChangeSettingType>("force")
- .enumValue(cChangeSettingTypeEnum)
+ .enumValue(c_changeSettingTypeNames)
.store(&force_)
.description("Save forces from frame if possible"));
options->addOption(
- EnumOption<ChangeAtomsType>("atoms").enumValue(cChangeAtomsTypeEnum).store(&atoms_).description("Decide on providing new atom information from topology or using current frame atom information"));
+ EnumOption<ChangeAtomsType>("atoms").enumValue(c_changeAtomsTypeNames).store(&atoms_).description("Decide on providing new atom information from topology or using current frame atom information"));
options->addOption(IntegerOption("precision")
.store(&prec_)
.defaultValue(prec_)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-set(test_sources
- builder.cpp
- outputadaptercontainer.cpp
- outputadapters.cpp
- requirements.cpp
- setatoms.cpp
- setbothtime.cpp
- setstarttime.cpp
- settimestep.cpp
- testmodule.cpp
- )
-gmx_add_unit_test(CoordinateIOTests coordinateio-test ${test_sources})
+gmx_add_unit_test(CoordinateIOTests coordinateio-test
+ CPP_SOURCE_FILES
+ builder.cpp
+ outputadaptercontainer.cpp
+ outputadapters.cpp
+ requirements.cpp
+ setatoms.cpp
+ setbothtime.cpp
+ setstarttime.cpp
+ settimestep.cpp
+ testmodule.cpp
+ )
+
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] options Container for options.
* \param[in] type Need to know type of entries.
*/
- void setModuleFlag(const std::string& optionName, const std::string& optionValues, Options* options, TestEnums type)
+ static void setModuleFlag(const std::string& optionName,
+ const std::string& optionValues,
+ Options* options,
+ TestEnums type)
{
OptionsAssigner assigner(options);
assigner.start();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <utility>
#include "gromacs/coordinateio/outputadapters/setatoms.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/trajectoryanalysis/topologyinformation.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/coordinateio/outputadapters/setstarttime.h"
#include "gromacs/coordinateio/outputadapters/settimestep.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/coordinateio/tests/coordinate_test.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
#include "gromacs/coordinateio/outputadapters/setstarttime.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/coordinateio/tests/coordinate_test.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
#include "gromacs/coordinateio/outputadapters/settimestep.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/coordinateio/tests/coordinate_test.h"
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2016, by the GROMACS development team, led by
+# Copyright (c) 2014,2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(CorrelationsTest correlations-test
- autocorr.cpp
- manyautocorrelation.cpp
- correlationdataset.cpp
- expfit.cpp)
+ CPP_SOURCE_FILES
+ autocorr.cpp
+ correlationdataset.cpp
+ expfit.cpp
+ manyautocorrelation.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
checker_.checkReal(testResult, "Integral");
}
- int getDim(unsigned long type)
+ static int getDim(unsigned long type)
{
switch (type)
{
case eacNormal: return 1;
case eacVector: return 3;
- case eacCos: return 1;
- case eacRcross: return 3;
- case eacP0: return 3;
- case eacP1: return 3;
- case eacP2: return 3;
- case eacP3: return 3;
+ case eacCos:
+ return 1;
+ // Several intended fall-throughs follow
+ case eacRcross:
+ case eacP0:
+ case eacP1:
+ case eacP2:
+ case eacP3:
case eacP4: return 3;
case eacIden: return 1;
default: GMX_RELEASE_ASSERT(false, "Invalid auto correlation option"); return -1;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::ArrayRef<const gmx::RVec> xRef = constArrayRefFromArray(
x.data(), masterRankHasTheSystemState ? x.size() : dd.comm->atomRanges.numHomeAtoms());
- low_set_ddbox(dd.unitCellInfo.npbcdim, dd.unitCellInfo.numBoundedDimensions, &dd.nc, box,
- calculateUnboundedSize, xRef,
+ low_set_ddbox(dd.unitCellInfo.npbcdim, dd.unitCellInfo.numBoundedDimensions, &dd.numCells,
+ box, calculateUnboundedSize, xRef,
needToReduceCoordinateData ? &dd.mpi_comm_all : nullptr, ddbox);
}
{
if (MASTER(&cr))
{
- low_set_ddbox(ePBC2npbcdim(ir.ePBC), inputrec2nboundeddim(&ir), dd_nc, box, true, x, nullptr, ddbox);
+ low_set_ddbox(numPbcDimensions(ir.pbcType), inputrec2nboundeddim(&ir), dd_nc, box, true, x,
+ nullptr, ddbox);
}
- gmx_bcast(sizeof(gmx_ddbox_t), ddbox, &cr);
+ gmx_bcast(sizeof(gmx_ddbox_t), ddbox, cr.mpi_comm_mygroup);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_commrec* cr,
const DomdecOptions& options,
const MdrunOptions& mdrunOptions,
- bool prefer1DAnd1Pulse,
+ bool prefer1D,
const gmx_mtop_t& mtop,
const t_inputrec& ir,
const matrix box,
int sh;
comm = dd->comm;
- nc = dd->nc[ddpme->dim];
+ nc = dd->numCells[ddpme->dim];
ns = ddpme->nslab;
if (!ddpme->dim_match)
dim = dd->dim[d];
if (dim < ddbox->nboundeddim
&& ddbox->box_size[dim] * ddbox->skew_fac[dim]
- < dd->nc[dim] * dd->comm->cellsize_limit * DD_CELL_MARGIN)
+ < dd->numCells[dim] * dd->comm->cellsize_limit * DD_CELL_MARGIN)
{
gmx_fatal(
FARGS,
"The %c-size of the box (%f) times the triclinic skew factor (%f) is smaller "
"than the number of DD cells (%d) times the smallest allowed cell size (%f)\n",
- dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim], dd->nc[dim],
+ dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim], dd->numCells[dim],
dd->comm->cellsize_limit);
}
}
{
cellsize_min[d] = ddbox->box_size[d] * ddbox->skew_fac[d];
npulse[d] = 1;
- if (dd->nc[d] == 1 || comm->slb_frac[d] == nullptr)
+ if (dd->numCells[d] == 1 || comm->slb_frac[d] == nullptr)
{
/* Uniform grid */
- real cell_dx = ddbox->box_size[d] / dd->nc[d];
+ real cell_dx = ddbox->box_size[d] / dd->numCells[d];
switch (setmode)
{
case setcellsizeslbMASTER:
- for (int j = 0; j < dd->nc[d] + 1; j++)
+ for (int j = 0; j < dd->numCells[d] + 1; j++)
{
cell_x_master[d][j] = ddbox->box0[d] + j * cell_dx;
}
}
else
{
- cell_x_buffer.resize(dd->nc[d] + 1);
+ cell_x_buffer.resize(dd->numCells[d] + 1);
cell_x = cell_x_buffer;
}
cell_x[0] = ddbox->box0[d];
- for (int j = 0; j < dd->nc[d]; j++)
+ for (int j = 0; j < dd->numCells[d]; j++)
{
real cell_dx = ddbox->box_size[d] * comm->slb_frac[d][j];
cell_x[j + 1] = cell_x[j] + cell_dx;
real cellsize = cell_dx * ddbox->skew_fac[d];
- while (cellsize * npulse[d] < comm->systemInfo.cutoff && npulse[d] < dd->nc[d] - 1)
+ while (cellsize * npulse[d] < comm->systemInfo.cutoff && npulse[d] < dd->numCells[d] - 1)
{
npulse[d]++;
}
* some of its own home charge groups back over the periodic boundary.
* Double charge groups cause trouble with the global indices.
*/
- if (d < ddbox->npbcdim && dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
+ if (d < ddbox->npbcdim && dd->numCells[d] > 1 && npulse[d] >= dd->numCells[d])
{
char error_string[STRLEN];
"small for a cut-off of %f with %d domain decomposition cells, use 1 or more "
"than %d %s or increase the box size in this direction",
dim2char(d), ddbox->box_size[d], ddbox->skew_fac[d], comm->systemInfo.cutoff,
- dd->nc[d], dd->nc[d], dd->nnodes > dd->nc[d] ? "cells" : "ranks");
+ dd->numCells[d], dd->numCells[d], dd->nnodes > dd->numCells[d] ? "cells" : "ranks");
if (setmode == setcellsizeslbLOCAL)
{
comm = dd->comm;
- const int ncd = dd->nc[dim];
+ const int ncd = dd->numCells[dim];
const bool dimHasPbc = (dim < ddbox->npbcdim);
if (!rowMaster->isCellMin[i])
{
cell_size[i] *= fac;
- if (!dimHasPbc && (i == 0 || i == dd->nc[dim] - 1))
+ if (!dimHasPbc && (i == 0 || i == dd->numCells[dim] - 1))
{
cellsize_limit_f_i = 0;
}
/* Convert the maximum change from the input percentage to a fraction */
const real change_limit = comm->ddSettings.dlb_scale_lim * 0.01;
- const int ncd = dd->nc[dim];
+ const int ncd = dd->numCells[dim];
const bool bPBC = (dim < ddbox->npbcdim);
rowMaster->cellFrac[i], rowMaster->cellFrac[i + 1]);
}
- if ((bPBC || (i != 0 && i != dd->nc[dim] - 1))
+ if ((bPBC || (i != 0 && i != dd->numCells[dim] - 1))
&& rowMaster->cellFrac[i + 1] - rowMaster->cellFrac[i] < cellsize_limit_f / DD_CELL_MARGIN)
{
char buf[22];
comm.cellsizesWithDlb[d].fracLower = cellFracRow[dd->ci[dim]];
comm.cellsizesWithDlb[d].fracUpper = cellFracRow[dd->ci[dim] + 1];
/* The whole array was communicated, so set the buffer position */
- int pos = dd->nc[dim] + 1;
+ int pos = dd->numCells[dim] + 1;
for (int d1 = 0; d1 <= d; d1++)
{
if (d1 < d)
/* Set the dimensions for which no DD is used */
for (dim = 0; dim < DIM; dim++)
{
- if (dd->nc[dim] == 1)
+ if (dd->numCells[dim] == 1)
{
comm->cell_x0[dim] = 0;
comm->cell_x1[dim] = ddbox->box_size[dim];
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-static void dd_distribute_state(gmx_domdec_t* dd,
- const t_state* state,
- t_state* state_local,
- PaddedHostVector<gmx::RVec>* f)
+static void dd_distribute_state(gmx_domdec_t* dd, const t_state* state, t_state* state_local)
{
int nh = state_local->nhchainlength;
/* communicate df_history -- required for restarting from checkpoint */
dd_distribute_dfhist(dd, state_local->dfhist);
- dd_resize_state(state_local, f, dd->comm->atomRanges.numHomeAtoms());
+ state_change_natoms(state_local, dd->comm->atomRanges.numHomeAtoms());
if (state_local->flags & (1 << estX))
{
if (d < dd.unitCellInfo.npbcdim)
{
bool bScrew = (dd.unitCellInfo.haveScrewPBC && d == XX);
- if (ddbox.tric_dir[d] && dd.nc[d] > 1)
+ if (ddbox.tric_dir[d] && dd.numCells[d] > 1)
{
/* Use triclinic coordinates for this dimension */
for (int j = d + 1; j < DIM; j++)
}
/* This could be done more efficiently */
ind[d] = 0;
- while (ind[d] + 1 < dd.nc[d] && pos_d >= cellBoundaries[d][ind[d] + 1])
+ while (ind[d] + 1 < dd.numCells[d] && pos_d >= cellBoundaries[d][ind[d] + 1])
{
ind[d]++;
}
}
- return dd_index(dd.nc, ind);
+ return dd_index(dd.numCells, ind);
}
}
}
-void distributeState(const gmx::MDLogger& mdlog,
- gmx_domdec_t* dd,
- const gmx_mtop_t& mtop,
- t_state* state_global,
- const gmx_ddbox_t& ddbox,
- t_state* state_local,
- PaddedHostVector<gmx::RVec>* f)
+void distributeState(const gmx::MDLogger& mdlog,
+ gmx_domdec_t* dd,
+ const gmx_mtop_t& mtop,
+ t_state* state_global,
+ const gmx_ddbox_t& ddbox,
+ t_state* state_local)
{
rvec* xGlobal = (DDMASTER(dd) ? state_global->x.rvec_array() : nullptr);
distributeAtomGroups(mdlog, dd, mtop, DDMASTER(dd) ? state_global->box : nullptr, &ddbox, xGlobal);
- dd_distribute_state(dd, state_global, state_local, f);
+ dd_distribute_state(dd, state_global, state_local);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_DOMDEC_DOMDEC_DISTRIBUTE_H
#define GMX_DOMDEC_DOMDEC_DISTRIBUTE_H
-#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/utility/basedefinitions.h"
struct gmx_ddbox_t;
}
/*! \brief Distributes the state from the master rank to all DD ranks */
-void distributeState(const gmx::MDLogger& mdlog,
- gmx_domdec_t* dd,
- const gmx_mtop_t& mtop,
- t_state* state_global,
- const gmx_ddbox_t& ddbox,
- t_state* state_local,
- gmx::PaddedHostVector<gmx::RVec>* f);
+void distributeState(const gmx::MDLogger& mdlog,
+ gmx_domdec_t* dd,
+ const gmx_mtop_t& mtop,
+ t_state* state_global,
+ const gmx_ddbox_t& ddbox,
+ t_state* state_local);
#endif
#include "gromacs/domdec/partition.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/hardware/hw_info.h"
#include "gromacs/listed_forces/manage_threading.h"
{ 2, 5, 6 },
{ 3, 5, 7 } };
-
-/*
- #define dd_index(n,i) ((((i)[ZZ]*(n)[YY] + (i)[YY])*(n)[XX]) + (i)[XX])
-
- static void index2xyz(ivec nc,int ind,ivec xyz)
- {
- xyz[XX] = ind % nc[XX];
- xyz[YY] = (ind / nc[XX]) % nc[YY];
- xyz[ZZ] = ind / (nc[YY]*nc[XX]);
- }
- */
-
static void ddindex2xyz(const ivec nc, int ind, ivec xyz)
{
xyz[XX] = ind / (nc[YY] * nc[ZZ]);
int ddnodeid = -1;
const CartesianRankSetup& cartSetup = dd->comm->cartesianRankSetup;
- const int ddindex = dd_index(dd->nc, c);
+ const int ddindex = dd_index(dd->numCells, c);
if (cartSetup.bCartesianPP_PME)
{
ddnodeid = cartSetup.ddindex2ddnodeid[ddindex];
ivec coords;
int slab;
- dd = cr->dd;
- /*
- if (dd->comm->bCartesian) {
- gmx_ddindex2xyz(dd->nc,ddindex,coords);
- dd_coords2pmecoords(dd,coords,coords_pme);
- copy_ivec(dd->ntot,nc);
- nc[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
- coords_pme[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
-
- slab = (coords_pme[XX]*nc[YY] + coords_pme[YY])*nc[ZZ] + coords_pme[ZZ];
- } else {
- slab = (ddindex*cr->npmenodes + cr->npmenodes/2)/dd->nnodes;
- }
- */
+ dd = cr->dd;
coords[XX] = x;
coords[YY] = y;
coords[ZZ] = z;
- slab = ddindex2pmeindex(dd->comm->ddRankSetup, dd_index(dd->nc, coords));
+ slab = ddindex2pmeindex(dd->comm->ddRankSetup, dd_index(dd->numCells, coords));
return slab;
}
}
else
{
- int ddindex = dd_index(cr->dd->nc, coords);
+ int ddindex = dd_index(cr->dd->numCells, coords);
if (cartSetup.bCartesianPP)
{
nodeid = cartSetup.ddindex2simnodeid[ddindex];
ivec coords;
MPI_Cart_coords(cr->mpi_comm_mysim, cr->sim_nodeid, DIM, coords);
coords[cartSetup.cartpmedim]++;
- if (coords[cartSetup.cartpmedim] < dd->nc[cartSetup.cartpmedim])
+ if (coords[cartSetup.cartpmedim] < dd->numCells[cartSetup.cartpmedim])
{
int rank;
MPI_Cart_rank(cr->mpi_comm_mysim, coords, &rank);
comm = dd->comm;
- snew(*dim_f, dd->nc[dim] + 1);
+ snew(*dim_f, dd->numCells[dim] + 1);
(*dim_f)[0] = 0;
- for (i = 1; i < dd->nc[dim]; i++)
+ for (i = 1; i < dd->numCells[dim]; i++)
{
if (comm->slb_frac[dim])
{
}
else
{
- (*dim_f)[i] = static_cast<real>(i) / static_cast<real>(dd->nc[dim]);
+ (*dim_f)[i] = static_cast<real>(i) / static_cast<real>(dd->numCells[dim]);
}
}
- (*dim_f)[dd->nc[dim]] = 1;
+ (*dim_f)[dd->numCells[dim]] = 1;
}
static void init_ddpme(gmx_domdec_t* dd, gmx_ddpme_t* ddpme, int dimind)
snew(ddpme->pp_max, ddpme->nslab);
for (int slab = 0; slab < ddpme->nslab; slab++)
{
- ddpme->pp_min[slab] = dd->nc[dd->dim[dimind]] - 1;
+ ddpme->pp_min[slab] = dd->numCells[dd->dim[dimind]] - 1;
ddpme->pp_max[slab] = 0;
}
for (int i = 0; i < dd->nnodes; i++)
{
ivec xyz;
- ddindex2xyz(dd->nc, i, xyz);
+ ddindex2xyz(dd->numCells, i, xyz);
/* For y only use our y/z slab.
* This assumes that the PME x grid size matches the DD grid size.
*/
dim = dd->dim[dim_ind];
copy_ivec(loc, loc_c);
- for (i = 0; i < dd->nc[dim]; i++)
+ for (i = 0; i < dd->numCells[dim]; i++)
{
loc_c[dim] = i;
- rank = dd_index(dd->nc, loc_c);
+ rank = dd_index(dd->numCells, loc_c);
if (rank == dd->rank)
{
/* This process is part of the group */
RowMaster& rowMaster = *cellsizes.rowMaster;
rowMaster.cellFrac.resize(ddCellFractionBufferSize(dd, dim_ind));
- rowMaster.oldCellFrac.resize(dd->nc[dim] + 1);
- rowMaster.isCellMin.resize(dd->nc[dim]);
+ rowMaster.oldCellFrac.resize(dd->numCells[dim] + 1);
+ rowMaster.isCellMin.resize(dd->numCells[dim]);
if (dim_ind > 0)
{
- rowMaster.bounds.resize(dd->nc[dim]);
+ rowMaster.bounds.resize(dd->numCells[dim]);
}
- rowMaster.buf_ncd.resize(dd->nc[dim]);
+ rowMaster.buf_ncd.resize(dd->numCells[dim]);
}
else
{
}
if (dd->ci[dim] == dd->master_ci[dim])
{
- snew(dd->comm->load[dim_ind].load, dd->nc[dim] * DD_NLOAD_MAX);
+ snew(dd->comm->load[dim_ind].load, dd->numCells[dim] * DD_NLOAD_MAX);
}
}
}
if (dd->ndim > 1)
{
dim0 = dd->dim[0];
- for (i = 0; i < dd->nc[dim0]; i++)
+ for (i = 0; i < dd->numCells[dim0]; i++)
{
loc[dim0] = i;
make_load_communicator(dd, 1, loc);
if (dd->ndim > 2)
{
dim0 = dd->dim[0];
- for (i = 0; i < dd->nc[dim0]; i++)
+ for (i = 0; i < dd->numCells[dim0]; i++)
{
loc[dim0] = i;
dim1 = dd->dim[1];
- for (j = 0; j < dd->nc[dim1]; j++)
+ for (j = 0; j < dd->numCells[dim1]; j++)
{
loc[dim1] = j;
make_load_communicator(dd, 2, loc);
{
dim = dd->dim[d];
copy_ivec(dd->ci, tmp);
- tmp[dim] = (tmp[dim] + 1) % dd->nc[dim];
+ tmp[dim] = (tmp[dim] + 1) % dd->numCells[dim];
dd->neighbor[d][0] = ddcoord2ddnodeid(dd, tmp);
copy_ivec(dd->ci, tmp);
- tmp[dim] = (tmp[dim] - 1 + dd->nc[dim]) % dd->nc[dim];
+ tmp[dim] = (tmp[dim] - 1 + dd->numCells[dim]) % dd->numCells[dim];
dd->neighbor[d][1] = ddcoord2ddnodeid(dd, tmp);
if (debug)
{
s[d] = dd->ci[d] - zones->shift[i][d];
if (s[d] < 0)
{
- s[d] += dd->nc[d];
+ s[d] += dd->numCells[d];
}
- else if (s[d] >= dd->nc[d])
+ else if (s[d] >= dd->numCells[d])
{
- s[d] -= dd->nc[d];
+ s[d] -= dd->numCells[d];
}
}
}
std::min(ddNonbondedZonePairRanges[iZoneIndex][2], nzone));
for (dim = 0; dim < DIM; dim++)
{
- if (dd->nc[dim] == 1)
+ if (dd->numCells[dim] == 1)
{
/* All shifts should be allowed */
iZone.shift0[dim] = -1;
{
/* Set up cartesian communication for the particle-particle part */
GMX_LOG(mdlog.info)
- .appendTextFormatted("Will use a Cartesian communicator: %d x %d x %d", dd->nc[XX],
- dd->nc[YY], dd->nc[ZZ]);
+ .appendTextFormatted("Will use a Cartesian communicator: %d x %d x %d",
+ dd->numCells[XX], dd->numCells[YY], dd->numCells[ZZ]);
ivec periods;
for (int i = 0; i < DIM; i++)
periods[i] = TRUE;
}
MPI_Comm comm_cart;
- MPI_Cart_create(cr->mpi_comm_mygroup, DIM, dd->nc, periods, static_cast<int>(reorder), &comm_cart);
+ MPI_Cart_create(cr->mpi_comm_mygroup, DIM, dd->numCells, periods, static_cast<int>(reorder),
+ &comm_cart);
/* We overwrite the old communicator with the new cartesian one */
cr->mpi_comm_mygroup = comm_cart;
}
* and not the one after split, we need to make an index.
*/
cartSetup.ddindex2ddnodeid.resize(dd->nnodes);
- cartSetup.ddindex2ddnodeid[dd_index(dd->nc, dd->ci)] = dd->rank;
+ cartSetup.ddindex2ddnodeid[dd_index(dd->numCells, dd->ci)] = dd->rank;
gmx_sumi(dd->nnodes, cartSetup.ddindex2ddnodeid.data(), cr);
/* Get the rank of the DD master,
* above we made sure that the master node is a PP node.
std::vector<int> buf(dd->nnodes);
if (thisRankHasDuty(cr, DUTY_PP))
{
- buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
+ buf[dd_index(dd->numCells, dd->ci)] = cr->sim_nodeid;
}
/* Communicate the ddindex to simulation nodeid index */
MPI_Allreduce(buf.data(), cartSetup.ddindex2simnodeid.data(), dd->nnodes, MPI_INT, MPI_SUM,
{
if (cartSetup.ddindex2simnodeid[i] == 0)
{
- ddindex2xyz(dd->nc, i, dd->master_ci);
+ ddindex2xyz(dd->numCells, i, dd->master_ci);
MPI_Cart_rank(dd->mpi_comm_all, dd->master_ci, &dd->masterrank);
}
}
{
/* No Cartesian communicators */
/* We use the rank in dd->comm->all as DD index */
- ddindex2xyz(dd->nc, dd->rank, dd->ci);
+ ddindex2xyz(dd->numCells, dd->rank, dd->ci);
/* The simulation master nodeid is 0, so the DD master rank is also 0 */
dd->masterrank = 0;
clear_ivec(dd->master_ci);
std::vector<int> buf(dd->nnodes);
if (thisRankHasDuty(cr, DUTY_PP))
{
- buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
+ buf[dd_index(dd->numCells, dd->ci)] = cr->sim_nodeid;
}
/* Communicate the ddindex to simulation nodeid index */
MPI_Allreduce(buf.data(), cartSetup.ddindex2simnodeid.data(), dd->nnodes, MPI_INT, MPI_SUM,
/* We can not use DDMASTER(dd), because dd->masterrank is set later */
if (MASTER(cr))
{
- dd->ma = std::make_unique<AtomDistribution>(dd->nc, numAtomsInSystem, numAtomsInSystem);
+ dd->ma = std::make_unique<AtomDistribution>(dd->numCells, numAtomsInSystem, numAtomsInSystem);
}
}
static void check_dd_restrictions(const gmx_domdec_t* dd, const t_inputrec* ir, const gmx::MDLogger& mdlog)
{
- if (ir->ePBC == epbcSCREW && (dd->nc[XX] == 1 || dd->nc[YY] > 1 || dd->nc[ZZ] > 1))
+ if (ir->pbcType == PbcType::Screw
+ && (dd->numCells[XX] == 1 || dd->numCells[YY] > 1 || dd->numCells[ZZ] > 1))
{
gmx_fatal(FARGS, "With pbc=%s can only do domain decomposition in the x-direction",
- epbc_names[ir->ePBC]);
+ c_pbcTypeNames[ir->pbcType].c_str());
}
if (ir->nstlist == 0)
gmx_fatal(FARGS, "Domain decomposition does not work with nstlist=0");
}
- if (ir->comm_mode == ecmANGULAR && ir->ePBC != epbcNONE)
+ if (ir->comm_mode == ecmANGULAR && ir->pbcType != PbcType::No)
{
GMX_LOG(mdlog.warning)
.appendText(
}
UnitCellInfo::UnitCellInfo(const t_inputrec& ir) :
- npbcdim(ePBC2npbcdim(ir.ePBC)),
+ npbcdim(numPbcDimensions(ir.pbcType)),
numBoundedDimensions(inputrec2nboundeddim(&ir)),
ddBoxIsDynamic(numBoundedDimensions < DIM || inputrecDynamicBox(&ir)),
- haveScrewPBC(ir.ePBC == epbcSCREW)
+ haveScrewPBC(ir.pbcType == PbcType::Screw)
{
}
systemInfo.useUpdateGroups = false;
if (ir.cutoff_scheme == ecutsVERLET)
{
- real cutoffMargin = std::sqrt(max_cutoff2(ir.ePBC, box)) - ir.rlist;
+ real cutoffMargin = std::sqrt(max_cutoff2(ir.pbcType, box)) - ir.rlist;
setupUpdateGroups(mdlog, mtop, ir, cutoffMargin, &systemInfo);
}
dd_bonded_cg_distance(mdlog, &mtop, &ir, as_rvec_array(xGlobal.data()), box,
options.checkBondedInteractions, &r_2b, &r_mb);
}
- gmx_bcast(sizeof(r_2b), &r_2b, cr);
- gmx_bcast(sizeof(r_mb), &r_mb, cr);
+ gmx_bcast(sizeof(r_2b), &r_2b, cr->mpi_comm_mygroup);
+ gmx_bcast(sizeof(r_mb), &r_mb, cr->mpi_comm_mygroup);
/* We use an initial margin of 10% for the minimum cell size,
* except when we are just below the non-bonded cut-off.
}
/* Set the DD setup given by ddGridSetup */
- copy_ivec(ddGridSetup.numDomains, dd->nc);
+ copy_ivec(ddGridSetup.numDomains, dd->numCells);
dd->ndim = ddGridSetup.numDDDimensions;
copy_ivec(ddGridSetup.ddDimensions, dd->dim);
- dd->nnodes = dd->nc[XX] * dd->nc[YY] * dd->nc[ZZ];
+ dd->nnodes = dd->numCells[XX] * dd->numCells[YY] * dd->numCells[ZZ];
snew(comm->slb_frac, DIM);
if (isDlbDisabled(comm))
{
- comm->slb_frac[XX] = get_slb_frac(mdlog, "x", dd->nc[XX], options.cellSizeX);
- comm->slb_frac[YY] = get_slb_frac(mdlog, "y", dd->nc[YY], options.cellSizeY);
- comm->slb_frac[ZZ] = get_slb_frac(mdlog, "z", dd->nc[ZZ], options.cellSizeZ);
+ comm->slb_frac[XX] = get_slb_frac(mdlog, "x", dd->numCells[XX], options.cellSizeX);
+ comm->slb_frac[YY] = get_slb_frac(mdlog, "y", dd->numCells[YY], options.cellSizeY);
+ comm->slb_frac[ZZ] = get_slb_frac(mdlog, "z", dd->numCells[ZZ], options.cellSizeZ);
}
/* Set the multi-body cut-off and cellsize limit for DLB */
* the minimum and the maximum,
* since the extra communication cost is nearly zero.
*/
- real acs = average_cellsize_min(ddbox, dd->nc);
+ real acs = average_cellsize_min(ddbox, dd->numCells);
comm->cutoff_mbody = 0.5 * (systemInfo.minCutoffForMultiBody + acs);
if (!isDlbDisabled(comm))
{
}
}
-void dd_init_bondeds(FILE* fplog,
- gmx_domdec_t* dd,
- const gmx_mtop_t* mtop,
- const gmx_vsite_t* vsite,
- const t_inputrec* ir,
- gmx_bool bBCheck,
- cginfo_mb_t* cginfo_mb)
+void dd_init_bondeds(FILE* fplog,
+ gmx_domdec_t* dd,
+ const gmx_mtop_t& mtop,
+ const gmx_vsite_t* vsite,
+ const t_inputrec* ir,
+ gmx_bool bBCheck,
+ gmx::ArrayRef<cginfo_mb_t> cginfo_mb)
{
gmx_domdec_comm_t* comm;
- dd_make_reverse_top(fplog, dd, mtop, vsite, ir, bBCheck);
+ dd_make_reverse_top(fplog, dd, &mtop, vsite, ir, bBCheck);
comm = dd->comm;
log->writeString("The allowed shrink of domain decomposition cells is:");
for (d = 0; d < DIM; d++)
{
- if (dd->nc[d] > 1)
+ if (dd->numCells[d] > 1)
{
- if (d >= ddbox->npbcdim && dd->nc[d] == 2)
+ if (d >= ddbox->npbcdim && dd->numCells[d] == 2)
{
shrink = 0;
}
else
{
shrink = comm->cellsize_min_dlb[d]
- / (ddbox->box_size[d] * ddbox->skew_fac[d] / dd->nc[d]);
+ / (ddbox->box_size[d] * ddbox->skew_fac[d] / dd->numCells[d]);
}
log->writeStringFormatted(" %c %.2f", dim2char(d), shrink);
}
log->writeString("The initial domain decomposition cell size is:");
for (d = 0; d < DIM; d++)
{
- if (dd->nc[d] > 1)
+ if (dd->numCells[d] > 1)
{
log->writeStringFormatted(" %c %.2f nm", dim2char(d), dd->comm->cellsize_min[d]);
}
else
{
/* There is no cell size limit */
- npulse = std::max(dd->nc[XX] - 1, std::max(dd->nc[YY] - 1, dd->nc[ZZ] - 1));
+ npulse = std::max(dd->numCells[XX] - 1, std::max(dd->numCells[YY] - 1, dd->numCells[ZZ] - 1));
}
if (!bNoCutOff && npulse > 1)
dim = dd->dim[d];
npulse_d = static_cast<int>(
1
- + dd->nc[dim] * comm->systemInfo.cutoff
+ + dd->numCells[dim] * comm->systemInfo.cutoff
/ (ddbox->box_size[dim] * ddbox->skew_fac[dim] * dlb_scale));
npulse_d_max = std::max(npulse_d_max, npulse_d);
}
}
comm->maxpulse = 1;
- comm->bVacDLBNoLimit = (ir->ePBC == epbcNONE);
+ comm->bVacDLBNoLimit = (ir->pbcType == PbcType::No);
for (d = 0; d < dd->ndim; d++)
{
- if (comm->ddSettings.request1DAnd1Pulse)
- {
- comm->cd[d].np_dlb = 1;
- }
- else
- {
- comm->cd[d].np_dlb = std::min(npulse, dd->nc[dd->dim[d]] - 1);
- comm->maxpulse = std::max(comm->maxpulse, comm->cd[d].np_dlb);
- }
- if (comm->cd[d].np_dlb < dd->nc[dd->dim[d]] - 1)
+ comm->cd[d].np_dlb = std::min(npulse, dd->numCells[dd->dim[d]] - 1);
+ comm->maxpulse = std::max(comm->maxpulse, comm->cd[d].np_dlb);
+ if (comm->cd[d].np_dlb < dd->numCells[dd->dim[d]] - 1)
{
comm->bVacDLBNoLimit = FALSE;
}
return dd.comm->systemInfo.moleculesAreAlwaysWhole;
}
-gmx_bool dd_bonded_molpbc(const gmx_domdec_t* dd, int ePBC)
+gmx_bool dd_bonded_molpbc(const gmx_domdec_t* dd, PbcType pbcType)
{
/* If each molecule is a single charge group
* or we use domain decomposition for each periodic dimension,
* we do not need to take pbc into account for the bonded interactions.
*/
- return (ePBC != epbcNONE && dd->comm->systemInfo.haveInterDomainBondeds
- && !(dd->nc[XX] > 1 && dd->nc[YY] > 1 && (dd->nc[ZZ] > 1 || ePBC == epbcXY)));
+ return (pbcType != PbcType::No && dd->comm->systemInfo.haveInterDomainBondeds
+ && !(dd->numCells[XX] > 1 && dd->numCells[YY] > 1
+ && (dd->numCells[ZZ] > 1 || pbcType == PbcType::XY)));
}
/*! \brief Sets grid size limits and PP-PME setup, prints settings to log */
logSettings(mdlog, dd, mtop, ir, dlb_scale, ddbox);
real vol_frac;
- if (ir->ePBC == epbcNONE)
+ if (ir->pbcType == PbcType::No)
{
vol_frac = 1 - 1 / static_cast<double>(dd->nnodes);
}
else
{
- vol_frac = (1 + comm_box_frac(dd->nc, comm->systemInfo.cutoff, *ddbox))
+ vol_frac = (1 + comm_box_frac(dd->numCells, comm->systemInfo.cutoff, *ddbox))
/ static_cast<double>(dd->nnodes);
}
if (debug)
ddSettings.useSendRecv2 = (dd_getenv(mdlog, "GMX_DD_USE_SENDRECV2", 0) != 0);
ddSettings.dlb_scale_lim = dd_getenv(mdlog, "GMX_DLB_MAX_BOX_SCALING", 10);
- ddSettings.request1DAnd1Pulse = bool(dd_getenv(mdlog, "GMX_DD_1D_1PULSE", 0));
+ ddSettings.request1D = bool(dd_getenv(mdlog, "GMX_DD_1D", 0));
ddSettings.useDDOrderZYX = bool(dd_getenv(mdlog, "GMX_DD_ORDER_ZYX", 0));
ddSettings.useCartesianReorder = bool(dd_getenv(mdlog, "GMX_NO_CART_REORDER", 1));
ddSettings.eFlop = dd_getenv(mdlog, "GMX_DLB_BASED_ON_FLOPS", 0);
gmx_domdec_t::gmx_domdec_t(const t_inputrec& ir) : unitCellInfo(ir) {}
-/*! \brief Return whether the simulation described can run a 1D single-pulse DD.
+/*! \brief Return whether the simulation described can run a 1D DD.
*
- * The GPU halo exchange code requires a 1D single-pulse DD. Such a DD
+ * The GPU halo exchange code requires 1D DD. Such a DD
* generally requires a larger box than other possible decompositions
* with the same rank count, so the calling code might need to decide
* what is the most appropriate way to run the simulation based on
* exchange code path. The number of PME ranks, if any, should be set
* in \c options.numPmeRanks.
*/
-static bool canMake1DAnd1PulseDomainDecomposition(const DDSettings& ddSettingsOriginal,
- const t_commrec* cr,
- const int numRanksRequested,
- const DomdecOptions& options,
- const gmx_mtop_t& mtop,
- const t_inputrec& ir,
- const matrix box,
- gmx::ArrayRef<const gmx::RVec> xGlobal)
+static bool canMake1DDomainDecomposition(const DDSettings& ddSettingsOriginal,
+ const t_commrec* cr,
+ const int numRanksRequested,
+ const DomdecOptions& options,
+ const gmx_mtop_t& mtop,
+ const t_inputrec& ir,
+ const matrix box,
+ gmx::ArrayRef<const gmx::RVec> xGlobal)
{
// Ensure we don't write any output from this checking routine
gmx::MDLogger dummyLogger;
DDSystemInfo systemInfo = getSystemInfo(dummyLogger, cr, options, mtop, ir, box, xGlobal);
- DDSettings ddSettings = ddSettingsOriginal;
- ddSettings.request1DAnd1Pulse = true;
- const real gridSetupCellsizeLimit = getDDGridSetupCellSizeLimit(
- dummyLogger, ddSettings.request1DAnd1Pulse, !isDlbDisabled(ddSettings.initialDlbState),
- options.dlbScaling, ir, systemInfo.cellsizeLimit);
+ DDSettings ddSettings = ddSettingsOriginal;
+ ddSettings.request1D = true;
+ const real gridSetupCellsizeLimit =
+ getDDGridSetupCellSizeLimit(dummyLogger, !isDlbDisabled(ddSettings.initialDlbState),
+ options.dlbScaling, ir, systemInfo.cellsizeLimit);
gmx_ddbox_t ddbox = { 0 };
DDGridSetup ddGridSetup =
getDDGridSetup(dummyLogger, cr, numRanksRequested, options, ddSettings, systemInfo,
gridSetupCellsizeLimit, mtop, ir, box, xGlobal, &ddbox);
- const bool canMakeDDWith1DAnd1Pulse = (ddGridSetup.numDomains[XX] != 0);
+ const bool canMake1DDD = (ddGridSetup.numDomains[XX] != 0);
- return canMakeDDWith1DAnd1Pulse;
+ return canMake1DDD;
}
-bool is1DAnd1PulseDD(const gmx_domdec_t& dd)
+bool is1D(const gmx_domdec_t& dd)
{
- const int maxDimensionSize = std::max(dd.nc[XX], std::max(dd.nc[YY], dd.nc[ZZ]));
- const int productOfDimensionSizes = dd.nc[XX] * dd.nc[YY] * dd.nc[ZZ];
+ const int maxDimensionSize = std::max(dd.numCells[XX], std::max(dd.numCells[YY], dd.numCells[ZZ]));
+ const int productOfDimensionSizes = dd.numCells[XX] * dd.numCells[YY] * dd.numCells[ZZ];
const bool decompositionHasOneDimension = (maxDimensionSize == productOfDimensionSizes);
- const bool hasMax1Pulse =
- ((isDlbDisabled(dd.comm) && dd.comm->cellsize_limit >= dd.comm->systemInfo.cutoff)
- || (!isDlbDisabled(dd.comm) && dd.comm->maxpulse == 1));
-
- return decompositionHasOneDimension && hasMax1Pulse;
+ return decompositionHasOneDimension;
}
namespace gmx
t_commrec* cr,
const DomdecOptions& options,
const MdrunOptions& mdrunOptions,
- bool prefer1DAnd1Pulse,
+ bool prefer1D,
const gmx_mtop_t& mtop,
const t_inputrec& ir,
const matrix box,
t_commrec* cr,
const DomdecOptions& options,
const MdrunOptions& mdrunOptions,
- const bool prefer1DAnd1Pulse,
+ const bool prefer1D,
const gmx_mtop_t& mtop,
const t_inputrec& ir,
const matrix box,
ddSettings_ = getDDSettings(mdlog_, options_, mdrunOptions, ir_);
- if (prefer1DAnd1Pulse
- && canMake1DAnd1PulseDomainDecomposition(ddSettings_, cr_, cr_->nnodes, options_, mtop_,
- ir_, box, xGlobal))
+ if (prefer1D
+ && canMake1DDomainDecomposition(ddSettings_, cr_, cr_->nnodes, options_, mtop_, ir_, box, xGlobal))
{
- ddSettings_.request1DAnd1Pulse = true;
+ ddSettings_.request1D = true;
}
if (ddSettings_.eFlop > 1)
// DD grid setup uses a more different cell size limit for
// automated setup than the one in systemInfo_. The latter is used
// in set_dd_limits() to configure DLB, for example.
- const real gridSetupCellsizeLimit = getDDGridSetupCellSizeLimit(
- mdlog_, ddSettings_.request1DAnd1Pulse, !isDlbDisabled(ddSettings_.initialDlbState),
- options_.dlbScaling, ir_, systemInfo_.cellsizeLimit);
+ const real gridSetupCellsizeLimit =
+ getDDGridSetupCellSizeLimit(mdlog_, !isDlbDisabled(ddSettings_.initialDlbState),
+ options_.dlbScaling, ir_, systemInfo_.cellsizeLimit);
ddGridSetup_ = getDDGridSetup(mdlog_, cr_, numRanksRequested, options_, ddSettings_, systemInfo_,
gridSetupCellsizeLimit, mtop_, ir_, box, xGlobal, &ddbox_);
checkDDGridSetup(ddGridSetup_, cr_, options_, ddSettings_, systemInfo_, gridSetupCellsizeLimit, ddbox_);
t_commrec* cr,
const DomdecOptions& options,
const MdrunOptions& mdrunOptions,
- const bool prefer1DAnd1Pulse,
+ const bool prefer1D,
const gmx_mtop_t& mtop,
const t_inputrec& ir,
const matrix box,
ArrayRef<const RVec> xGlobal) :
- impl_(new Impl(mdlog, cr, options, mdrunOptions, prefer1DAnd1Pulse, mtop, ir, box, xGlobal))
+ impl_(new Impl(mdlog, cr, options, mdrunOptions, prefer1D, mtop, ir, box, xGlobal))
{
}
{
dim = dd->dim[d];
- inv_cell_size = DD_CELL_MARGIN * dd->nc[dim] / ddbox.box_size[dim];
+ inv_cell_size = DD_CELL_MARGIN * dd->numCells[dim] / ddbox.box_size[dim];
if (dd->unitCellInfo.ddBoxIsDynamic)
{
inv_cell_size *= DD_PRES_SCALE_MARGIN;
np = 1 + static_cast<int>(cutoffRequested * inv_cell_size * ddbox.skew_fac[dim]);
- if (dd->comm->ddSettings.request1DAnd1Pulse && np > 1)
- {
- return FALSE;
- }
-
if (!isDlbDisabled(dd->comm) && (dim < ddbox.npbcdim) && (dd->comm->cd[d].np_dlb > 0))
{
if (np > dd->comm->cd[d].np_dlb)
return bCutoffAllowed;
}
+
+void constructGpuHaloExchange(const gmx::MDLogger& mdlog,
+ const t_commrec& cr,
+ const gmx::DeviceStreamManager& deviceStreamManager)
+{
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedLocal),
+ "Local non-bonded stream should be valid when using"
+ "GPU halo exchange.");
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedNonLocal),
+ "Non-local non-bonded stream should be valid when using "
+ "GPU halo exchange.");
+ int gpuHaloExchangeSize = 0;
+ int pulseStart = 0;
+ if (cr.dd->gpuHaloExchange.empty())
+ {
+ GMX_LOG(mdlog.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "NOTE: Activating the 'GPU halo exchange' feature, enabled "
+ "by the "
+ "GMX_GPU_DD_COMMS environment variable.");
+ }
+ else
+ {
+ gpuHaloExchangeSize = static_cast<int>(cr.dd->gpuHaloExchange.size());
+ pulseStart = gpuHaloExchangeSize - 1;
+ }
+ if (cr.dd->comm->cd[0].numPulses() > gpuHaloExchangeSize)
+ {
+ for (int pulse = pulseStart; pulse < cr.dd->comm->cd[0].numPulses(); pulse++)
+ {
+ cr.dd->gpuHaloExchange.push_back(std::make_unique<gmx::GpuHaloExchange>(
+ cr.dd, cr.mpi_comm_mysim, deviceStreamManager.context(),
+ deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedLocal),
+ deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedNonLocal), pulse));
+ }
+ }
+}
+
+void reinitGpuHaloExchange(const t_commrec& cr,
+ const DeviceBuffer<gmx::RVec> d_coordinatesBuffer,
+ const DeviceBuffer<gmx::RVec> d_forcesBuffer)
+{
+ for (int pulse = 0; pulse < cr.dd->comm->cd[0].numPulses(); pulse++)
+ {
+ cr.dd->gpuHaloExchange[pulse]->reinitHalo(d_coordinatesBuffer, d_forcesBuffer);
+ }
+}
+
+void communicateGpuHaloCoordinates(const t_commrec& cr,
+ const matrix box,
+ GpuEventSynchronizer* coordinatesReadyOnDeviceEvent)
+{
+ for (int pulse = 0; pulse < cr.dd->comm->cd[0].numPulses(); pulse++)
+ {
+ cr.dd->gpuHaloExchange[pulse]->communicateHaloCoordinates(box, coordinatesReadyOnDeviceEvent);
+ }
+}
+
+void communicateGpuHaloForces(const t_commrec& cr, bool accumulateForces)
+{
+ for (int pulse = cr.dd->comm->cd[0].numPulses() - 1; pulse >= 0; pulse--)
+ {
+ cr.dd->gpuHaloExchange[pulse]->communicateHaloForces(accumulateForces);
+ }
+}
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2005 - 2014, The GROMACS development team.
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/math/vectypes.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
struct t_mdatoms;
struct t_nrnb;
struct gmx_wallcycle;
+enum class PbcType : int;
class t_state;
+class DeviceContext;
+class GpuEventSynchronizer;
namespace gmx
{
+class DeviceStreamManager;
class ForceWithShiftForces;
class MDLogger;
class RangePartitioning;
/*! \brief Return whether update groups are used */
bool ddUsesUpdateGroups(const gmx_domdec_t& dd);
-/*! \brief Return whether the DD has a single dimension with a single pulse
+/*! \brief Return whether the DD has a single dimension
*
- * The GPU halo exchange code requires a 1D single-pulse DD, and its
- * setup code can use the returned value to understand what it should
- * do. */
-bool is1DAnd1PulseDD(const gmx_domdec_t& dd);
+ * The GPU halo exchange code requires a 1D DD, and its setup code can
+ * use the returned value to understand what it should do.
+ */
+bool is1D(const gmx_domdec_t& dd);
/*! \brief Initialize data structures for bonded interactions */
-void dd_init_bondeds(FILE* fplog,
- gmx_domdec_t* dd,
- const gmx_mtop_t* mtop,
- const gmx_vsite_t* vsite,
- const t_inputrec* ir,
- gmx_bool bBCheck,
- cginfo_mb_t* cginfo_mb);
+void dd_init_bondeds(FILE* fplog,
+ gmx_domdec_t* dd,
+ const gmx_mtop_t& mtop,
+ const gmx_vsite_t* vsite,
+ const t_inputrec* ir,
+ gmx_bool bBCheck,
+ gmx::ArrayRef<cginfo_mb_t> cginfo_mb);
/*! \brief Returns whether molecules are always whole, i.e. not broken by PBC */
bool dd_moleculesAreAlwaysWhole(const gmx_domdec_t& dd);
/*! \brief Returns if we need to do pbc for calculating bonded interactions */
-gmx_bool dd_bonded_molpbc(const gmx_domdec_t* dd, int ePBC);
+gmx_bool dd_bonded_molpbc(const gmx_domdec_t* dd, PbcType pbcType);
/*! \brief Change the DD non-bonded communication cut-off.
*
void dd_clear_f_vsites(struct gmx_domdec_t* dd, rvec* f);
/*! \brief Move x0 and also x1 if x1!=NULL. bX1IsCoord tells if to do PBC on x1 */
-void dd_move_x_constraints(struct gmx_domdec_t* dd, const matrix box, rvec* x0, rvec* x1, gmx_bool bX1IsCoord);
+void dd_move_x_constraints(struct gmx_domdec_t* dd,
+ const matrix box,
+ gmx::ArrayRef<gmx::RVec> x0,
+ gmx::ArrayRef<gmx::RVec> x1,
+ gmx_bool bX1IsCoord);
/*! \brief Communicates the coordinates involved in virtual sites */
void dd_move_x_vsites(struct gmx_domdec_t* dd, const matrix box, rvec* x);
/* In domdec_top.c */
/*! \brief Print error output when interactions are missing */
-[[noreturn]] void dd_print_missing_interactions(const gmx::MDLogger& mdlog,
- t_commrec* cr,
- int local_count,
- const gmx_mtop_t* top_global,
- const gmx_localtop_t* top_local,
- const rvec* x,
- const matrix box);
+[[noreturn]] void dd_print_missing_interactions(const gmx::MDLogger& mdlog,
+ t_commrec* cr,
+ int local_count,
+ const gmx_mtop_t* top_global,
+ const gmx_localtop_t* top_local,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const matrix box);
/*! \brief Generate and store the reverse topology */
void dd_make_reverse_top(FILE* fplog,
/*! \brief Sort ltop->ilist when we are doing free energy. */
void dd_sort_local_top(gmx_domdec_t* dd, const t_mdatoms* mdatoms, gmx_localtop_t* ltop);
-/*! \brief Initialize local topology
- *
- * \param[in] top_global Reference to global topology.
- * \param[in,out] top Pointer to new local topology
- */
-void dd_init_local_top(const gmx_mtop_t& top_global, gmx_localtop_t* top);
-
/*! \brief Construct local state */
void dd_init_local_state(struct gmx_domdec_t* dd, const t_state* state_global, t_state* local_state);
*
* Also stores whether atoms are linked in \p cginfo_mb.
*/
-t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_mb);
+t_blocka* makeBondedLinks(const gmx_mtop_t& mtop, gmx::ArrayRef<cginfo_mb_t> cginfo_mb);
/*! \brief Calculate the maximum distance involved in 2-body and multi-body bonded interactions */
void dd_bonded_cg_distance(const gmx::MDLogger& mdlog,
real* r_2b,
real* r_mb);
+/*! \brief Construct the GPU halo exchange object(s).
+ *
+ * \param[in] mdlog The logger object.
+ * \param[in] cr The commrec object.
+ * \param[in] deviceStreamManager Manager of the GPU context and streams.
+ */
+void constructGpuHaloExchange(const gmx::MDLogger& mdlog,
+ const t_commrec& cr,
+ const gmx::DeviceStreamManager& deviceStreamManager);
+
+/*! \brief
+ * (Re-) Initialization for GPU halo exchange
+ * \param [in] cr The commrec object
+ * \param [in] d_coordinatesBuffer pointer to coordinates buffer in GPU memory
+ * \param [in] d_forcesBuffer pointer to forces buffer in GPU memory
+ */
+void reinitGpuHaloExchange(const t_commrec& cr,
+ DeviceBuffer<gmx::RVec> d_coordinatesBuffer,
+ DeviceBuffer<gmx::RVec> d_forcesBuffer);
+
+
+/*! \brief GPU halo exchange of coordinates buffer.
+ * \param [in] cr The commrec object
+ * \param [in] box Coordinate box (from which shifts will be constructed)
+ * \param [in] coordinatesReadyOnDeviceEvent event recorded when coordinates have been copied to device
+ */
+void communicateGpuHaloCoordinates(const t_commrec& cr,
+ const matrix box,
+ GpuEventSynchronizer* coordinatesReadyOnDeviceEvent);
+
+
+/*! \brief GPU halo exchange of force buffer.
+ * \param [in] cr The commrec object
+ * \param [in] accumulateForces True if forces should accumulate, otherwise they are set
+ */
+void communicateGpuHaloForces(const t_commrec& cr, bool accumulateForces);
+
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2006,2007,2008,2009,2010,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2006,2007,2008,2009,2010 by the GROMACS development team.
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
-#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/listoflists.h"
#include "domdec_internal.h"
#include "domdec_specatomcomm.h"
+using gmx::ListOfLists;
+
/*! \brief Struct used during constraint setup with domain decomposition */
struct gmx_domdec_constraints_t
{
std::unique_ptr<gmx::HashedMap<int>> ga2la; /**< Global to local communicated constraint atom only index */
/* Multi-threading stuff */
- int nthread; /**< Number of threads used for DD constraint setup */
- std::vector<t_ilist> ils; /**< Constraint ilist working arrays, size \p nthread */
+ int nthread; /**< Number of threads used for DD constraint setup */
+ std::vector<InteractionList> ils; /**< Constraint ilist working arrays, size \p nthread */
/* Buffers for requesting atoms */
std::vector<std::vector<int>> requestedGlobalAtomIndices; /**< Buffers for requesting global atom indices, one per thread */
//! @endcond
};
-void dd_move_x_constraints(gmx_domdec_t* dd, const matrix box, rvec* x0, rvec* x1, gmx_bool bX1IsCoord)
+void dd_move_x_constraints(gmx_domdec_t* dd,
+ const matrix box,
+ gmx::ArrayRef<gmx::RVec> x0,
+ gmx::ArrayRef<gmx::RVec> x1,
+ gmx_bool bX1IsCoord)
{
if (dd->constraint_comm)
{
- dd_move_x_specat(dd, dd->constraint_comm, box, x0, x1, bX1IsCoord);
+ dd_move_x_specat(dd, dd->constraint_comm, box, as_rvec_array(x0.data()),
+ as_rvec_array(x1.data()), bX1IsCoord);
ddReopenBalanceRegionCpu(dd);
}
int nrec,
gmx::ArrayRef<const int> ia1,
gmx::ArrayRef<const int> ia2,
- const t_blocka* at2con,
+ const ListOfLists<int>& at2con,
const gmx_ga2la_t& ga2la,
gmx_bool bHomeConnect,
gmx_domdec_constraints_t* dc,
gmx_domdec_specat_comm_t* dcc,
- t_ilist* il_local,
+ InteractionList* il_local,
std::vector<int>* ireq)
{
- int a1_gl, a2_gl, i, coni, b;
- const t_iatom* iap;
-
if (!dc->gc_req[con_offset + con])
{
/* Add this non-home constraint to the list */
dc->con_gl.push_back(con_offset + con);
dc->con_nlocat.push_back(bHomeConnect ? 1 : 0);
- dc->gc_req[con_offset + con] = true;
- if (il_local->nr + 3 > il_local->nalloc)
- {
- il_local->nalloc = over_alloc_dd(il_local->nr + 3);
- srenew(il_local->iatoms, il_local->nalloc);
- }
- iap = constr_iatomptr(ia1, ia2, con);
- il_local->iatoms[il_local->nr++] = iap[0];
- a1_gl = offset + iap[1];
- a2_gl = offset + iap[2];
+ dc->gc_req[con_offset + con] = true;
+ const int* iap = constr_iatomptr(ia1, ia2, con);
+ const int parameterType = iap[0];
+ const int a1_gl = offset + iap[1];
+ const int a2_gl = offset + iap[2];
+ std::array<int, 2> atoms;
/* The following indexing code can probably be optizimed */
if (const int* a_loc = ga2la.findHome(a1_gl))
{
- il_local->iatoms[il_local->nr++] = *a_loc;
+ atoms[0] = *a_loc;
}
else
{
/* We set this index later */
- il_local->iatoms[il_local->nr++] = -a1_gl - 1;
+ atoms[0] = -a1_gl - 1;
}
if (const int* a_loc = ga2la.findHome(a2_gl))
{
- il_local->iatoms[il_local->nr++] = *a_loc;
+ atoms[1] = *a_loc;
}
else
{
/* We set this index later */
- il_local->iatoms[il_local->nr++] = -a2_gl - 1;
+ atoms[1] = -a2_gl - 1;
}
+ il_local->push_back(parameterType, atoms);
dc->ncon++;
}
/* Check to not ask for the same atom more than once */
if (nrec > 0)
{
- for (i = at2con->index[a]; i < at2con->index[a + 1]; i++)
+ /* Loop over the constraint connected to atom a */
+ for (const int coni : at2con[a])
{
- coni = at2con->a[i];
if (coni != con)
{
/* Walk further */
- iap = constr_iatomptr(ia1, ia2, coni);
+ const int* iap = constr_iatomptr(ia1, ia2, coni);
+ int b;
if (a == iap[1])
{
b = iap[2];
gmx::ArrayRef<const std::vector<int>> at2settle_mt,
int cg_start,
int cg_end,
- t_ilist* ils_local,
+ InteractionList* ils_local,
std::vector<int>* ireq)
{
const gmx_ga2la_t& ga2la = *dd->ga2la;
if (bAssign)
{
- if (ils_local->nr + 1 + nral > ils_local->nalloc)
- {
- ils_local->nalloc = over_alloc_dd(ils_local->nr + 1 + nral);
- srenew(ils_local->iatoms, ils_local->nalloc);
- }
-
- ils_local->iatoms[ils_local->nr++] = ia1[settle * 4];
-
+ const int parameterType = ia1[settle * 4];
+ std::array<int, 3> atoms;
for (int sa = 0; sa < nral; sa++)
{
if (const int* a_loc = ga2la.findHome(a_gls[sa]))
{
- ils_local->iatoms[ils_local->nr++] = *a_loc;
+ atoms[sa] = *a_loc;
}
else
{
- ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1;
+ atoms[sa] = -a_gls[sa] - 1;
/* Add this non-home atom to the list */
ireq->push_back(a_gls[sa]);
/* A check on double atom requests is
*/
}
}
+ ils_local->push_back(parameterType, atoms);
}
}
}
}
/*! \brief Looks up constraint for the local atoms */
-static void atoms_to_constraints(gmx_domdec_t* dd,
- const gmx_mtop_t* mtop,
- const int* cginfo,
- gmx::ArrayRef<const t_blocka> at2con_mt,
- int nrec,
- t_ilist* ilc_local,
- std::vector<int>* ireq)
+static void atoms_to_constraints(gmx_domdec_t* dd,
+ const gmx_mtop_t* mtop,
+ const int* cginfo,
+ gmx::ArrayRef<const ListOfLists<int>> at2con_mt,
+ int nrec,
+ InteractionList* ilc_local,
+ std::vector<int>* ireq)
{
- const t_blocka* at2con;
- int b_lo, offset, b_mol, i, con, con_offset;
-
gmx_domdec_constraints_t* dc = dd->constraints;
gmx_domdec_specat_comm_t* dcc = dd->constraint_comm;
* This is only required for the global index to make sure
* that we use each constraint only once.
*/
- con_offset = dc->molb_con_offset[mb] + molnr * dc->molb_ncon_mol[mb];
+ const int con_offset = dc->molb_con_offset[mb] + molnr * dc->molb_ncon_mol[mb];
/* The global atom number offset for this molecule */
- offset = a_gl - a_mol;
- at2con = &at2con_mt[molb.type];
- for (i = at2con->index[a_mol]; i < at2con->index[a_mol + 1]; i++)
+ const int offset = a_gl - a_mol;
+ /* Loop over the constraints connected to atom a_mol in the molecule */
+ const auto& at2con = at2con_mt[molb.type];
+ for (const int con : at2con[a_mol])
{
- con = at2con->a[i];
const int* iap = constr_iatomptr(ia1, ia2, con);
+ int b_mol;
if (a_mol == iap[1])
{
b_mol = iap[2];
{
dc->con_gl.push_back(con_offset + con);
dc->con_nlocat.push_back(2);
- if (ilc_local->nr + 3 > ilc_local->nalloc)
- {
- ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3);
- srenew(ilc_local->iatoms, ilc_local->nalloc);
- }
- b_lo = *a_loc;
- ilc_local->iatoms[ilc_local->nr++] = iap[0];
- ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a : b_lo);
- ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a);
+ const int b_lo = *a_loc;
+ const int parameterType = iap[0];
+ std::array<int, 2> atoms;
+ atoms[0] = (a_gl == iap[1] ? a : b_lo);
+ atoms[1] = (a_gl == iap[1] ? b_lo : a);
+ ilc_local->push_back(parameterType, atoms);
dc->ncon++;
nhome++;
}
}
}
-int dd_make_local_constraints(gmx_domdec_t* dd,
- int at_start,
- const struct gmx_mtop_t* mtop,
- const int* cginfo,
- gmx::Constraints* constr,
- int nrec,
- t_ilist* il_local)
+int dd_make_local_constraints(gmx_domdec_t* dd,
+ int at_start,
+ const struct gmx_mtop_t* mtop,
+ const int* cginfo,
+ gmx::Constraints* constr,
+ int nrec,
+ gmx::ArrayRef<InteractionList> il_local)
{
- gmx_domdec_constraints_t* dc;
- t_ilist * ilc_local, *ils_local;
- std::vector<int>* ireq;
- gmx::ArrayRef<const t_blocka> at2con_mt;
- gmx::HashedMap<int>* ga2la_specat;
- int at_end, i, j;
- t_iatom* iap;
+ gmx_domdec_constraints_t* dc;
+ InteractionList * ilc_local, *ils_local;
+ gmx::HashedMap<int>* ga2la_specat;
+ int at_end, i, j;
// This code should not be called unless this condition is true,
// because that's the only time init_domdec_constraints is
ilc_local = &il_local[F_CONSTR];
ils_local = &il_local[F_SETTLE];
- dc->ncon = 0;
- ilc_local->nr = 0;
+ dc->ncon = 0;
+ gmx::ArrayRef<const ListOfLists<int>> at2con_mt;
+ std::vector<int>* ireq = nullptr;
+ ilc_local->clear();
if (dd->constraint_comm)
{
// TODO Perhaps gmx_domdec_constraints_t should keep a valid constr?
ireq = &dc->requestedGlobalAtomIndices[0];
ireq->clear();
}
- else
- {
- // Currently unreachable
- at2con_mt = {};
- ireq = nullptr;
- }
gmx::ArrayRef<const std::vector<int>> at2settle_mt;
/* When settle works inside charge groups, we assigned them already */
{
// TODO Perhaps gmx_domdec_constraints_t should keep a valid constr?
GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
- at2settle_mt = constr->atom2settle_moltype();
- ils_local->nr = 0;
+ at2settle_mt = constr->atom2settle_moltype();
+ ils_local->clear();
}
if (at2settle_mt.empty())
if (thread >= t0_set)
{
- int cg0, cg1;
- t_ilist* ilst;
+ int cg0, cg1;
+ InteractionList* ilst;
/* Distribute the settle check+assignments over
* dc->nthread or dc->nthread-1 threads.
{
ilst = &dc->ils[thread];
}
- ilst->nr = 0;
+ ilst->clear();
std::vector<int>& ireqt = dc->requestedGlobalAtomIndices[thread];
if (thread > 0)
/* Combine the generate settles and requested indices */
for (int thread = 1; thread < dc->nthread; thread++)
{
- t_ilist* ilst;
- int ia;
-
if (thread > t0_set)
{
- ilst = &dc->ils[thread];
- if (ils_local->nr + ilst->nr > ils_local->nalloc)
- {
- ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr);
- srenew(ils_local->iatoms, ils_local->nalloc);
- }
- for (ia = 0; ia < ilst->nr; ia++)
- {
- ils_local->iatoms[ils_local->nr + ia] = ilst->iatoms[ia];
- }
- ils_local->nr += ilst->nr;
+ ils_local->append(dc->ils[thread]);
}
const std::vector<int>& ireqt = dc->requestedGlobalAtomIndices[thread];
if (debug)
{
- fprintf(debug, "Settles: total %3d\n", ils_local->nr / 4);
+ fprintf(debug, "Settles: total %3d\n", ils_local->size() / 4);
}
}
ga2la_specat = dd->constraints->ga2la.get();
nral1 = 1 + NRAL(F_CONSTR);
- for (i = 0; i < ilc_local->nr; i += nral1)
+ for (i = 0; i < ilc_local->size(); i += nral1)
{
- iap = ilc_local->iatoms + i;
+ int* iap = ilc_local->iatoms.data() + i;
for (j = 1; j < nral1; j++)
{
if (iap[j] < 0)
}
nral1 = 1 + NRAL(F_SETTLE);
- for (i = 0; i < ils_local->nr; i += nral1)
+ for (i = 0; i < ils_local->size(); i += nral1)
{
- iap = ils_local->iatoms + i;
+ int* iap = ils_local->iatoms.data() + i;
for (j = 1; j < nral1; j++)
{
if (iap[j] < 0)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2005,2006,2007,2008,2009,2010,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2005,2006,2007,2008,2009 by the GROMACS development team.
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_DOMDEC_DOMDEC_CONSTRAINTS_H
#define GMX_DOMDEC_DOMDEC_CONSTRAINTS_H
+#include "gromacs/utility/arrayref.h"
+
namespace gmx
{
class Constraints;
struct gmx_domdec_t;
struct gmx_mtop_t;
-struct t_ilist;
+struct InteractionList;
/*! \brief Clears the local indices for the constraint communication setup */
void dd_clear_local_constraint_indices(gmx_domdec_t* dd);
/*! \brief Sets up communication and atom indices for all local+connected constraints */
-int dd_make_local_constraints(struct gmx_domdec_t* dd,
- int at_start,
- const struct gmx_mtop_t* mtop,
- const int* cginfo,
- gmx::Constraints* constr,
- int nrec,
- struct t_ilist* il_local);
+int dd_make_local_constraints(struct gmx_domdec_t* dd,
+ int at_start,
+ const struct gmx_mtop_t* mtop,
+ const int* cginfo,
+ gmx::Constraints* constr,
+ int nrec,
+ gmx::ArrayRef<InteractionList> il_local);
/*! \brief Initializes the data structures for constraint communication */
void init_domdec_constraints(gmx_domdec_t* dd, const gmx_mtop_t* mtop);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Flop counter (0=no,1=yes,2=with (eFlop-1)*5% noise
int eFlop = 0;
- //! Request 1D domain decomposition with maximum one communication pulse
- bool request1DAnd1Pulse;
+ //! Request 1D domain decomposition
+ bool request1D;
//! Whether to order the DD dimensions from z to x
bool useDDOrderZYX = false;
/*! Returns the size of the buffer to hold fractional cell boundaries for DD dimension index dimIndex */
static inline int ddCellFractionBufferSize(const gmx_domdec_t* dd, int dimIndex)
{
- return dd->nc[dd->dim[dimIndex]] + 1 + dimIndex * 2 + 1 + dimIndex;
+ return dd->numCells[dd->dim[dimIndex]] + 1 + dimIndex * 2 + 1 + dimIndex;
}
/*! \brief Maximum number of ranks for using send/recv for state scattering and gathering
/*! \brief Return whether the DD inhomogeneous in the z direction */
static gmx_bool inhomogeneous_z(const t_inputrec& ir)
{
- return ((EEL_PME(ir.coulombtype) || ir.coulombtype == eelEWALD) && ir.ePBC == epbcXYZ
+ return ((EEL_PME(ir.coulombtype) || ir.coulombtype == eelEWALD) && ir.pbcType == PbcType::Xyz
&& ir.ewald_geometry == eewg3DC);
}
float temp;
/* Check the DD algorithm restrictions */
- if ((ir.ePBC == epbcXY && ir.nwall < 2 && nc[ZZ] > 1)
- || (ir.ePBC == epbcSCREW && (nc[XX] == 1 || nc[YY] > 1 || nc[ZZ] > 1)))
+ if ((ir.pbcType == PbcType::XY && ir.nwall < 2 && nc[ZZ] > 1)
+ || (ir.pbcType == PbcType::Screw && (nc[XX] == 1 || nc[YY] > 1 || nc[ZZ] > 1)))
{
return -1;
}
/* Add cost of pbc_dx for bondeds */
cost_pbcdx = 0;
- if ((nc[XX] == 1 || nc[YY] == 1) || (nc[ZZ] == 1 && ir.ePBC != epbcXY))
+ if ((nc[XX] == 1 || nc[YY] == 1) || (nc[ZZ] == 1 && ir.pbcType != PbcType::XY))
{
if ((ddbox.tric_dir[XX] && nc[XX] == 1) || (ddbox.tric_dir[YY] && nc[YY] == 1))
{
const int numRanksRequested,
const int numPmeOnlyRanks,
const real cellSizeLimit,
- const bool request1DAnd1Pulse,
+ const bool request1D,
const gmx_mtop_t& mtop,
const matrix box,
const gmx_ddbox_t& ddbox,
gmx::IVec itry = { 1, 1, 1 };
gmx::IVec numDomains = { 0, 0, 0 };
- assign_factors(cellSizeLimit, request1DAnd1Pulse, systemInfo.cutoff, box, ddbox, mtop.natoms, ir,
- pbcdxr, numRanksDoingPmeWork, div.size(), div.data(), mdiv.data(), &itry, &numDomains);
+ assign_factors(cellSizeLimit, request1D, systemInfo.cutoff, box, ddbox, mtop.natoms, ir, pbcdxr,
+ numRanksDoingPmeWork, div.size(), div.data(), mdiv.data(), &itry, &numDomains);
return numDomains;
}
real getDDGridSetupCellSizeLimit(const gmx::MDLogger& mdlog,
- const bool request1DAnd1Pulse,
const bool bDynLoadBal,
const real dlb_scale,
const t_inputrec& ir,
- const real systemInfoCellSizeLimit)
+ real systemInfoCellSizeLimit)
{
real cellSizeLimit = systemInfoCellSizeLimit;
- if (request1DAnd1Pulse)
- {
- cellSizeLimit = std::max(cellSizeLimit, ir.rlist);
- }
/* Add a margin for DLB and/or pressure scaling */
if (bDynLoadBal)
{
int numPmeOnlyRanks = getNumPmeOnlyRanksToUse(mdlog, options, mtop, ir, box, numRanksRequested);
- if (ddSettings.request1DAnd1Pulse && (numRanksRequested - numPmeOnlyRanks == 1))
+ if (ddSettings.request1D && (numRanksRequested - numPmeOnlyRanks == 1))
{
// With only one PP rank, there will not be a need for
// GPU-based halo exchange that wants to request that any DD
- // has only 1 dimension and 1 pulse.
+ // has only 1 dimension.
return DDGridSetup{};
}
if (MASTER(cr))
{
numDomains = optimizeDDCells(mdlog, numRanksRequested, numPmeOnlyRanks, cellSizeLimit,
- ddSettings.request1DAnd1Pulse, mtop, box, *ddbox, ir, systemInfo);
+ ddSettings.request1D, mtop, box, *ddbox, ir, systemInfo);
}
}
/* Communicate the information set by the master to all ranks */
- gmx_bcast(sizeof(numDomains), numDomains, cr);
+ gmx_bcast(sizeof(numDomains), numDomains, cr->mpi_comm_mygroup);
if (EEL_PME(ir.coulombtype))
{
- gmx_bcast(sizeof(numPmeOnlyRanks), &numPmeOnlyRanks, cr);
+ gmx_bcast(sizeof(numPmeOnlyRanks), &numPmeOnlyRanks, cr->mpi_comm_mygroup);
}
DDGridSetup ddGridSetup;
/*! \brief Return the minimum cell size (in nm) required for DD */
real getDDGridSetupCellSizeLimit(const gmx::MDLogger& mdlog,
- bool request1DAnd1Pulse,
bool bDynLoadBal,
real dlb_scale,
const t_inputrec& ir,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2006,2007,2008,2009,2010,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2006,2007,2008,2009,2010 by the GROMACS development team.
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
for (int d = dd->ndim - 1; d >= 0; d--)
{
dim = dd->dim[d];
- if (dd->nc[dim] > 2)
+ if (dd->numCells[dim] > 2)
{
/* Pulse the grid forward and backward */
spas = spac->spas[d];
vbuf + spas[0].a.size(), spas[1].a.size());
for (dir = 0; dir < 2; dir++)
{
- bPBC = ((dir == 0 && dd->ci[dim] == 0) || (dir == 1 && dd->ci[dim] == dd->nc[dim] - 1));
+ bPBC = ((dir == 0 && dd->ci[dim] == 0)
+ || (dir == 1 && dd->ci[dim] == dd->numCells[dim] - 1));
bScrew = (bPBC && dd->unitCellInfo.haveScrewPBC && dim == XX);
spas = &spac->spas[d][dir];
spas->a.size());
/* Sum the buffer into the required forces */
if (dd->unitCellInfo.haveScrewPBC && dim == XX
- && (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1))
+ && (dd->ci[dim] == 0 || dd->ci[dim] == dd->numCells[dim] - 1))
{
int i = 0;
for (int a : spas->a)
for (d = 0; d < dd->ndim; d++)
{
dim = dd->dim[d];
- if (dd->nc[dim] > 2)
+ if (dd->numCells[dim] > 2)
{
/* Pulse the grid forward and backward */
rvec* vbuf = as_rvec_array(spac->vbuf.data());
bScrew = (dd->unitCellInfo.haveScrewPBC && dim == XX);
copy_rvec(box[dim], shift);
}
- else if (dir == 1 && dd->ci[dim] == dd->nc[dim] - 1)
+ else if (dir == 1 && dd->ci[dim] == dd->numCells[dim] - 1)
{
bPBC = TRUE;
bScrew = (dd->unitCellInfo.haveScrewPBC && dim == XX);
{
rvec* x = (v == 0 ? x0 : x1);
if (dd->unitCellInfo.haveScrewPBC && dim == XX
- && (dd->ci[XX] == 0 || dd->ci[XX] == dd->nc[XX] - 1))
+ && (dd->ci[XX] == 0 || dd->ci[XX] == dd->numCells[XX] - 1))
{
/* Here we only perform the rotation, the rest of the pbc
* is handled in the constraint or viste routines.
/* Pulse the grid forward and backward */
dim = dd->dim[d];
bPBC = (dim < dd->unitCellInfo.npbcdim);
- if (dd->nc[dim] == 2)
+ if (dd->numCells[dim] == 2)
{
/* Only 2 cells, so we only need to communicate once */
ndir = 1;
}
for (int dir = 0; dir < ndir; dir++)
{
- if (!bPBC && dd->nc[dim] > 2
- && ((dir == 0 && dd->ci[dim] == dd->nc[dim] - 1) || (dir == 1 && dd->ci[dim] == 0)))
+ if (!bPBC && dd->numCells[dim] > 2
+ && ((dir == 0 && dd->ci[dim] == dd->numCells[dim] - 1) || (dir == 1 && dd->ci[dim] == 0)))
{
/* No pbc: the fist/last cell should not request atoms */
nsend_ptr = nsend_zero;
for (int d = 0; d < dd->ndim; d++)
{
/* Pulse the grid forward and backward */
- if (dd->dim[d] >= dd->unitCellInfo.npbcdim || dd->nc[dd->dim[d]] > 2)
+ if (dd->dim[d] >= dd->unitCellInfo.npbcdim || dd->numCells[dd->dim[d]] > 2)
{
ndir = 2;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2005,2006,2007,2008,2009,2010,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2005,2006,2007,2008,2009 by the GROMACS development team.
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! The j-atom range
gmx::Range<int> jAtomRange;
//! Minimum shifts to consider
- ivec shift0 = {};
+ gmx::IVec shift0 = { 0, 0, 0 };
//! Maximum shifts to consider
- ivec shift1 = {};
+ gmx::IVec shift1 = { 0, 0, 0 };
};
typedef struct
{
/* Zone lower corner in triclinic coordinates */
- rvec x0 = {};
+ gmx::RVec x0 = { 0, 0, 0 };
/* Zone upper corner in triclinic coordinates */
- rvec x1 = {};
+ gmx::RVec x1 = { 0, 0, 0 };
/* Zone bounding box lower corner in Cartesian coords */
- rvec bb_x0 = {};
+ gmx::RVec bb_x0 = { 0, 0, 0 };
/* Zone bounding box upper corner in Cartesian coords */
- rvec bb_x1 = {};
+ gmx::RVec bb_x1 = { 0, 0, 0 };
} gmx_domdec_zone_size_t;
struct gmx_domdec_zones_t
struct gmx_ddbox_t
{
- int npbcdim;
- int nboundeddim;
- rvec box0;
- rvec box_size;
+ int npbcdim;
+ int nboundeddim;
+ gmx::RVec box0 = { 0, 0, 0 };
+ gmx::RVec box_size = { 0, 0, 0 };
/* Tells if the box is skewed for each of the three cartesian directions */
- ivec tric_dir;
- rvec skew_fac;
+ gmx::IVec tric_dir = { 0, 0, 0 };
+ gmx::RVec skew_fac = { 0, 0, 0 };
/* Orthogonal vectors for triclinic cells, Cartesian index */
rvec v[DIM][DIM];
/* Normal vectors for the cells walls */
int nnodes = 0;
MPI_Comm mpi_comm_all = MPI_COMM_NULL;
/* The local DD cell index and rank */
- ivec ci = { 0, 0, 0 };
- int rank = 0;
- ivec master_ci = { 0, 0, 0 };
- int masterrank = 0;
+ gmx::IVec ci = { 0, 0, 0 };
+ int rank = 0;
+ gmx::IVec master_ci = { 0, 0, 0 };
+ int masterrank = 0;
/* Communication with the PME only nodes */
int pme_nodeid = 0;
gmx_bool pme_receive_vir_ener = false;
UnitCellInfo unitCellInfo;
/* The communication setup, identical for each cell, cartesian index */
- ivec nc = { 0, 0, 0 };
- int ndim = 0;
- ivec dim = { 0, 0, 0 }; /* indexed by 0 to ndim */
+ //! Todo: refactor nbnxm to not rely on this sometimes being a nullptr so this can be IVec
+ ivec numCells = { 0, 0, 0 };
+ int ndim = 0;
+ gmx::IVec dim = { 0, 0, 0 }; /* indexed by 0 to ndim */
/* Forward and backward neighboring cells, indexed by 0 to ndim */
int neighbor[DIM][2] = { { 0, 0 }, { 0, 0 }, { 0, 0 } };
std::vector<gmx::RVec> pmeForceReceiveBuffer;
/* GPU halo exchange object */
- std::unique_ptr<gmx::GpuHaloExchange> gpuHaloExchange;
+ std::vector<std::unique_ptr<gmx::GpuHaloExchange>> gpuHaloExchange;
};
//! Are we the master node for domain decomposition
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/forcerec.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
+#include "gromacs/mdlib/vsite.h"
#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strconvert.h"
#include "domdec_vsite.h"
#include "dump.h"
+using gmx::ListOfLists;
+
/*! \brief The number of integer item in the local state, used for broadcasting of the state */
#define NITEM_DD_INIT_LOCAL_STATE 5
/*! \brief Struct for thread local work data for local topology generation */
struct thread_work_t
{
- t_idef idef; /**< Partial local topology */
+ /*! \brief Constructor
+ *
+ * \param[in] ffparams The interaction parameters, the lifetime of the created object should not exceed the lifetime of the passed parameters
+ */
+ thread_work_t(const gmx_ffparams_t& ffparams) : idef(ffparams) {}
+
+ InteractionDefinitions idef; /**< Partial local topology */
std::unique_ptr<VsitePbc> vsitePbc; /**< vsite PBC structure */
int nbonded; /**< The number of bondeds in this struct */
- t_blocka excl; /**< List of exclusions */
+ ListOfLists<int> excl; /**< List of exclusions */
int excl_count; /**< The total exclusion count for \p excl */
};
struct gmx_reverse_top_t
{
//! @cond Doxygen_Suppress
- //! \brief The maximum number of exclusions one atom can have
- int n_excl_at_max = 0;
//! \brief Are there constraints in this revserse top?
bool bConstr = false;
//! \brief Are there settles in this revserse top?
*
* \note This function needs to be called on all ranks (contains a global summation)
*/
-static std::string print_missing_interactions_mb(t_commrec* cr,
- const gmx_reverse_top_t* rt,
- const char* moltypename,
- const reverse_ilist_t* ril,
- int a_start,
- int a_end,
- int nat_mol,
- int nmol,
- const t_idef* idef)
+static std::string print_missing_interactions_mb(t_commrec* cr,
+ const gmx_reverse_top_t* rt,
+ const char* moltypename,
+ const reverse_ilist_t* ril,
+ int a_start,
+ int a_end,
+ int nat_mol,
+ int nmol,
+ const InteractionDefinitions* idef)
{
int* assigned;
int nril_mol = ril->index[nat_mol];
{
if (dd_check_ftype(ftype, rt->bBCheck, rt->bConstr, rt->bSettle))
{
- int nral = NRAL(ftype);
- const t_ilist* il = &idef->il[ftype];
- const t_iatom* ia = il->iatoms;
- for (int i = 0; i < il->nr; i += 1 + nral)
+ int nral = NRAL(ftype);
+ const InteractionList* il = &idef->il[ftype];
+ const int* ia = il->iatoms.data();
+ for (int i = 0; i < il->size(); i += 1 + nral)
{
int a0 = gatindex[ia[1]];
/* Check if this interaction is in
}
/*! \brief Help print error output when interactions are missing */
-static void print_missing_interactions_atoms(const gmx::MDLogger& mdlog,
- t_commrec* cr,
- const gmx_mtop_t* mtop,
- const t_idef* idef)
+static void print_missing_interactions_atoms(const gmx::MDLogger& mdlog,
+ t_commrec* cr,
+ const gmx_mtop_t* mtop,
+ const InteractionDefinitions* idef)
{
const gmx_reverse_top_t* rt = cr->dd->reverse_top;
}
}
-void dd_print_missing_interactions(const gmx::MDLogger& mdlog,
- t_commrec* cr,
- int local_count,
- const gmx_mtop_t* top_global,
- const gmx_localtop_t* top_local,
- const rvec* x,
- const matrix box)
+void dd_print_missing_interactions(const gmx::MDLogger& mdlog,
+ t_commrec* cr,
+ int local_count,
+ const gmx_mtop_t* top_global,
+ const gmx_localtop_t* top_local,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const matrix box)
{
int ndiff_tot, cl[F_NRE], n, ndiff, rest_global, rest_local;
int ftype, nral;
for (ftype = 0; ftype < F_NRE; ftype++)
{
nral = NRAL(ftype);
- cl[ftype] = top_local->idef.il[ftype].nr / (1 + nral);
+ cl[ftype] = top_local->idef.il[ftype].size() / (1 + nral);
}
gmx_sumi(F_NRE, cl, cr);
}
print_missing_interactions_atoms(mdlog, cr, top_global, &top_local->idef);
- write_dd_pdb("dd_dump_err", 0, "dump", top_global, cr, -1, x, box);
+ write_dd_pdb("dd_dump_err", 0, "dump", top_global, cr, -1, as_rvec_array(x.data()), box);
std::string errorMessage;
}
/*! \brief Returns the maximum number of exclusions per atom */
-static int getMaxNumExclusionsPerAtom(const t_blocka& excls)
+static int getMaxNumExclusionsPerAtom(const ListOfLists<int>& excls)
{
int maxNumExcls = 0;
- for (int at = 0; at < excls.nr; at++)
+ for (gmx::index at = 0; at < excls.ssize(); at++)
{
- const int numExcls = excls.index[at + 1] - excls.index[at];
+ const auto list = excls[at];
+ const int numExcls = list.ssize();
- GMX_RELEASE_ASSERT(numExcls != 1 || excls.a[excls.index[at]] == at,
+ GMX_RELEASE_ASSERT(numExcls != 1 || list[0] == at,
"With 1 exclusion we expect a self-exclusion");
maxNumExcls = std::max(maxNumExcls, numExcls);
rt.mbi.push_back(mbi);
}
- rt.th_work.resize(gmx_omp_nthreads_get(emntDomdec));
+ for (int th = 0; th < gmx_omp_nthreads_get(emntDomdec); th++)
+ {
+ rt.th_work.emplace_back(mtop->ffparams);
+ }
return rt;
}
make_reverse_top(mtop, ir->efep != efepNO, !dd->comm->systemInfo.haveSplitConstraints,
!dd->comm->systemInfo.haveSplitSettles, bBCheck, &dd->nbonded_global);
- gmx_reverse_top_t* rt = dd->reverse_top;
-
dd->haveExclusions = false;
- rt->n_excl_at_max = 0;
for (const gmx_molblock_t& molb : mtop->molblock)
{
const int maxNumExclusionsPerAtom = getMaxNumExclusionsPerAtom(mtop->moltype[molb.type].excls);
{
dd->haveExclusions = true;
}
- rt->n_excl_at_max = std::max(rt->n_excl_at_max, maxNumExclusionsPerAtom);
}
if (vsite && vsite->numInterUpdategroupVsites > 0)
int a_gl,
int a_mol,
const t_iatom* iatoms,
- t_ilist* il)
+ InteractionList* il)
{
- t_iatom* liatoms;
-
- if (il->nr + 1 + nral > il->nalloc)
- {
- il->nalloc = over_alloc_large(il->nr + 1 + nral);
- srenew(il->iatoms, il->nalloc);
- }
- liatoms = il->iatoms + il->nr;
- il->nr += 1 + nral;
-
/* Copy the type */
tiatoms[0] = iatoms[0];
tiatoms[1] = -a_gl - 1;
}
+ GMX_ASSERT(nral >= 2 && nral <= 5, "Invalid nral for vsites");
for (int k = 2; k < 1 + nral; k++)
{
int ak_gl = a_gl + iatoms[k] - a_mol;
// Note that ga2la_get_home always sets the third parameter if
// it returns TRUE
}
- for (int k = 0; k < 1 + nral; k++)
- {
- liatoms[k] = tiatoms[k];
- }
-}
-
-/*! \brief Store a bonded interaction at the end of \p il */
-static inline void add_ifunc(int nral, const t_iatom* tiatoms, t_ilist* il)
-{
- t_iatom* liatoms;
- int k;
-
- if (il->nr + 1 + nral > il->nalloc)
- {
- il->nalloc = over_alloc_large(il->nr + 1 + nral);
- srenew(il->iatoms, il->nalloc);
- }
- liatoms = il->iatoms + il->nr;
- for (k = 0; k <= nral; k++)
- {
- liatoms[k] = tiatoms[k];
- }
- il->nr += 1 + nral;
+ il->push_back(tiatoms[0], nral, tiatoms + 1);
}
/*! \brief Store a position restraint in idef and iatoms, complex because the parameters are different for each entry */
-static void add_posres(int mol,
- int a_mol,
- int numAtomsInMolecule,
- const gmx_molblock_t* molb,
- t_iatom* iatoms,
- const t_iparams* ip_in,
- t_idef* idef)
+static void add_posres(int mol,
+ int a_mol,
+ int numAtomsInMolecule,
+ const gmx_molblock_t* molb,
+ t_iatom* iatoms,
+ const t_iparams* ip_in,
+ InteractionDefinitions* idef)
{
- int n, a_molb;
- t_iparams* ip;
-
/* This position restraint has not been added yet,
* so it's index is the current number of position restraints.
*/
- n = idef->il[F_POSRES].nr / 2;
- if (n + 1 > idef->iparams_posres_nalloc)
- {
- idef->iparams_posres_nalloc = over_alloc_dd(n + 1);
- srenew(idef->iparams_posres, idef->iparams_posres_nalloc);
- }
- ip = &idef->iparams_posres[n];
- /* Copy the force constants */
- *ip = ip_in[iatoms[0]];
+ const int n = idef->il[F_POSRES].size() / 2;
/* Get the position restraint coordinates from the molblock */
- a_molb = mol * numAtomsInMolecule + a_mol;
+ const int a_molb = mol * numAtomsInMolecule + a_mol;
GMX_ASSERT(a_molb < ssize(molb->posres_xA),
"We need a sufficient number of position restraint coordinates");
- ip->posres.pos0A[XX] = molb->posres_xA[a_molb][XX];
- ip->posres.pos0A[YY] = molb->posres_xA[a_molb][YY];
- ip->posres.pos0A[ZZ] = molb->posres_xA[a_molb][ZZ];
+ /* Copy the force constants */
+ t_iparams ip = ip_in[iatoms[0]];
+ ip.posres.pos0A[XX] = molb->posres_xA[a_molb][XX];
+ ip.posres.pos0A[YY] = molb->posres_xA[a_molb][YY];
+ ip.posres.pos0A[ZZ] = molb->posres_xA[a_molb][ZZ];
if (!molb->posres_xB.empty())
{
- ip->posres.pos0B[XX] = molb->posres_xB[a_molb][XX];
- ip->posres.pos0B[YY] = molb->posres_xB[a_molb][YY];
- ip->posres.pos0B[ZZ] = molb->posres_xB[a_molb][ZZ];
+ ip.posres.pos0B[XX] = molb->posres_xB[a_molb][XX];
+ ip.posres.pos0B[YY] = molb->posres_xB[a_molb][YY];
+ ip.posres.pos0B[ZZ] = molb->posres_xB[a_molb][ZZ];
}
else
{
- ip->posres.pos0B[XX] = ip->posres.pos0A[XX];
- ip->posres.pos0B[YY] = ip->posres.pos0A[YY];
- ip->posres.pos0B[ZZ] = ip->posres.pos0A[ZZ];
+ ip.posres.pos0B[XX] = ip.posres.pos0A[XX];
+ ip.posres.pos0B[YY] = ip.posres.pos0A[YY];
+ ip.posres.pos0B[ZZ] = ip.posres.pos0A[ZZ];
}
- /* Set the parameter index for idef->iparams_posre */
+ /* Set the parameter index for idef->iparams_posres */
iatoms[0] = n;
+ idef->iparams_posres.push_back(ip);
+
+ GMX_ASSERT(int(idef->iparams_posres.size()) == n + 1,
+ "The index of the parameter type should match n");
}
/*! \brief Store a flat-bottomed position restraint in idef and iatoms, complex because the parameters are different for each entry */
-static void add_fbposres(int mol,
- int a_mol,
- int numAtomsInMolecule,
- const gmx_molblock_t* molb,
- t_iatom* iatoms,
- const t_iparams* ip_in,
- t_idef* idef)
+static void add_fbposres(int mol,
+ int a_mol,
+ int numAtomsInMolecule,
+ const gmx_molblock_t* molb,
+ t_iatom* iatoms,
+ const t_iparams* ip_in,
+ InteractionDefinitions* idef)
{
- int n, a_molb;
- t_iparams* ip;
-
/* This flat-bottom position restraint has not been added yet,
* so it's index is the current number of position restraints.
*/
- n = idef->il[F_FBPOSRES].nr / 2;
- if (n + 1 > idef->iparams_fbposres_nalloc)
- {
- idef->iparams_fbposres_nalloc = over_alloc_dd(n + 1);
- srenew(idef->iparams_fbposres, idef->iparams_fbposres_nalloc);
- }
- ip = &idef->iparams_fbposres[n];
- /* Copy the force constants */
- *ip = ip_in[iatoms[0]];
+ const int n = idef->il[F_FBPOSRES].size() / 2;
/* Get the position restraint coordinats from the molblock */
- a_molb = mol * numAtomsInMolecule + a_mol;
+ const int a_molb = mol * numAtomsInMolecule + a_mol;
GMX_ASSERT(a_molb < ssize(molb->posres_xA),
"We need a sufficient number of position restraint coordinates");
+ /* Copy the force constants */
+ t_iparams ip = ip_in[iatoms[0]];
/* Take reference positions from A position of normal posres */
- ip->fbposres.pos0[XX] = molb->posres_xA[a_molb][XX];
- ip->fbposres.pos0[YY] = molb->posres_xA[a_molb][YY];
- ip->fbposres.pos0[ZZ] = molb->posres_xA[a_molb][ZZ];
+ ip.fbposres.pos0[XX] = molb->posres_xA[a_molb][XX];
+ ip.fbposres.pos0[YY] = molb->posres_xA[a_molb][YY];
+ ip.fbposres.pos0[ZZ] = molb->posres_xA[a_molb][ZZ];
/* Note: no B-type for flat-bottom posres */
- /* Set the parameter index for idef->iparams_posre */
+ /* Set the parameter index for idef->iparams_fbposres */
iatoms[0] = n;
+ idef->iparams_fbposres.push_back(ip);
+
+ GMX_ASSERT(int(idef->iparams_fbposres.size()) == n + 1,
+ "The index of the parameter type should match n");
}
/*! \brief Store a virtual site interaction, complex because of PBC and recursion */
int a_gl,
int a_mol,
const t_iatom* iatoms,
- t_idef* idef)
+ InteractionDefinitions* idef)
{
int k;
t_iatom tiatoms[1 + MAXATOMLIST];
return norm2(dx);
}
-/*! \brief Append t_blocka block structures 1 to nsrc in src to *dest */
-static void combine_blocka(t_blocka* dest, gmx::ArrayRef<const thread_work_t> src)
-{
- int ni = src.back().excl.nr;
- int na = 0;
- for (const thread_work_t& th_work : src)
- {
- na += th_work.excl.nra;
- }
- if (ni + 1 > dest->nalloc_index)
- {
- dest->nalloc_index = over_alloc_large(ni + 1);
- srenew(dest->index, dest->nalloc_index);
- }
- if (dest->nra + na > dest->nalloc_a)
- {
- dest->nalloc_a = over_alloc_large(dest->nra + na);
- srenew(dest->a, dest->nalloc_a);
- }
- for (gmx::index s = 1; s < src.ssize(); s++)
- {
- for (int i = dest->nr + 1; i < src[s].excl.nr + 1; i++)
- {
- dest->index[i] = dest->nra + src[s].excl.index[i];
- }
- for (int i = 0; i < src[s].excl.nra; i++)
- {
- dest->a[dest->nra + i] = src[s].excl.a[i];
- }
- dest->nr = src[s].excl.nr;
- dest->nra += src[s].excl.nra;
- }
-}
-
/*! \brief Append t_idef structures 1 to nsrc in src to *dest */
-static void combine_idef(t_idef* dest, gmx::ArrayRef<const thread_work_t> src)
+static void combine_idef(InteractionDefinitions* dest, gmx::ArrayRef<const thread_work_t> src)
{
int ftype;
int n = 0;
for (gmx::index s = 1; s < src.ssize(); s++)
{
- n += src[s].idef.il[ftype].nr;
+ n += src[s].idef.il[ftype].size();
}
if (n > 0)
{
- t_ilist* ild;
-
- ild = &dest->il[ftype];
-
- if (ild->nr + n > ild->nalloc)
- {
- ild->nalloc = over_alloc_large(ild->nr + n);
- srenew(ild->iatoms, ild->nalloc);
- }
-
for (gmx::index s = 1; s < src.ssize(); s++)
{
- const t_ilist& ils = src[s].idef.il[ftype];
-
- for (int i = 0; i < ils.nr; i++)
- {
- ild->iatoms[ild->nr + i] = ils.iatoms[i];
- }
-
- ild->nr += ils.nr;
+ dest->il[ftype].append(src[s].idef.il[ftype]);
}
/* Position restraints need an additional treatment */
if (ftype == F_POSRES || ftype == F_FBPOSRES)
{
- int nposres = dest->il[ftype].nr / 2;
- // TODO: Simplify this code using std::vector
- t_iparams*& iparams_dest =
+ int nposres = dest->il[ftype].size() / 2;
+ std::vector<t_iparams>& iparams_dest =
(ftype == F_POSRES ? dest->iparams_posres : dest->iparams_fbposres);
- int& posres_nalloc = (ftype == F_POSRES ? dest->iparams_posres_nalloc
- : dest->iparams_fbposres_nalloc);
- if (nposres > posres_nalloc)
- {
- posres_nalloc = over_alloc_large(nposres);
- srenew(iparams_dest, posres_nalloc);
- }
/* Set nposres to the number of original position restraints in dest */
for (gmx::index s = 1; s < src.ssize(); s++)
{
- nposres -= src[s].idef.il[ftype].nr / 2;
+ nposres -= src[s].idef.il[ftype].size() / 2;
}
for (gmx::index s = 1; s < src.ssize(); s++)
{
- const t_iparams* iparams_src = (ftype == F_POSRES ? src[s].idef.iparams_posres
- : src[s].idef.iparams_fbposres);
+ const std::vector<t_iparams>& iparams_src =
+ (ftype == F_POSRES ? src[s].idef.iparams_posres : src[s].idef.iparams_fbposres);
+ iparams_dest.insert(iparams_dest.end(), iparams_src.begin(), iparams_src.end());
- for (int i = 0; i < src[s].idef.il[ftype].nr / 2; i++)
+ /* Correct the indices into iparams_posres */
+ for (int i = 0; i < src[s].idef.il[ftype].size() / 2; i++)
{
/* Correct the index into iparams_posres */
dest->il[ftype].iatoms[nposres * 2] = nposres;
- /* Copy the position restraint force parameters */
- iparams_dest[nposres] = iparams_src[i];
nposres++;
}
}
+ GMX_RELEASE_ASSERT(
+ int(iparams_dest.size()) == nposres,
+ "The number of parameters should match the number of restraints");
}
}
}
t_pbc* pbc_null,
rvec* cg_cm,
const t_iparams* ip_in,
- t_idef* idef,
+ InteractionDefinitions* idef,
int iz,
gmx_bool bBCheck,
int* nbonded_local)
if (bUse)
{
/* Add this interaction to the local topology */
- add_ifunc(nral, tiatoms, &idef->il[ftype]);
+ idef->il[ftype].push_back(tiatoms[0], nral, tiatoms + 1);
/* Sum so we can check in global_stat
* if we have everything.
*/
t_pbc* pbc_null,
rvec* cg_cm,
const t_iparams* ip_in,
- t_idef* idef,
+ InteractionDefinitions* idef,
int izone,
const gmx::Range<int>& atomRange)
{
return nbonded_local;
}
-/*! \brief Set the exclusion data for i-zone \p iz for the case of no exclusions */
-static void set_no_exclusions_zone(const gmx_domdec_zones_t* zones, int iz, t_blocka* lexcls)
-{
- for (int a = zones->cg_range[iz]; a < zones->cg_range[iz + 1]; a++)
- {
- lexcls->index[a + 1] = lexcls->nra;
- }
-}
-
/*! \brief Set the exclusion data for i-zone \p iz */
static void make_exclusions_zone(gmx_domdec_t* dd,
gmx_domdec_zones_t* zones,
const std::vector<gmx_moltype_t>& moltype,
const int* cginfo,
- t_blocka* lexcls,
+ ListOfLists<int>* lexcls,
int iz,
int at_start,
int at_end,
const gmx::ArrayRef<const int> intermolecularExclusionGroup)
{
- int n_excl_at_max, n, at;
-
const gmx_ga2la_t& ga2la = *dd->ga2la;
const auto& jAtomRange = zones->iZones[iz].jAtomRange;
- n_excl_at_max = dd->reverse_top->n_excl_at_max;
+ const gmx::index oldNumLists = lexcls->ssize();
- /* We set the end index, but note that we might not start at zero here */
- lexcls->nr = at_end;
-
- n = lexcls->nra;
- for (at = at_start; at < at_end; at++)
+ std::vector<int> exclusionsForAtom;
+ for (int at = at_start; at < at_end; at++)
{
- if (n + 1000 > lexcls->nalloc_a)
- {
- lexcls->nalloc_a = over_alloc_large(n + 1000);
- srenew(lexcls->a, lexcls->nalloc_a);
- }
+ exclusionsForAtom.clear();
if (GET_CGINFO_EXCL_INTER(cginfo[at]))
{
- int a_gl, mb, mt, mol, a_mol, j;
- const t_blocka* excls;
-
- if (n + n_excl_at_max > lexcls->nalloc_a)
- {
- lexcls->nalloc_a = over_alloc_large(n + n_excl_at_max);
- srenew(lexcls->a, lexcls->nalloc_a);
- }
+ int a_gl, mb, mt, mol, a_mol;
/* Copy the exclusions from the global top */
- lexcls->index[at] = n;
- a_gl = dd->globalAtomIndices[at];
+ a_gl = dd->globalAtomIndices[at];
global_atomnr_to_moltype_ind(dd->reverse_top, a_gl, &mb, &mt, &mol, &a_mol);
- excls = &moltype[mt].excls;
- for (j = excls->index[a_mol]; j < excls->index[a_mol + 1]; j++)
+ const auto excls = moltype[mt].excls[a_mol];
+ for (const int aj_mol : excls)
{
- const int aj_mol = excls->a[j];
-
if (const auto* jEntry = ga2la.find(a_gl + aj_mol - a_mol))
{
/* This check is not necessary, but it can reduce
*/
if (jAtomRange.isInRange(jEntry->la))
{
- lexcls->a[n++] = jEntry->la;
+ exclusionsForAtom.push_back(jEntry->la);
}
}
}
}
- else
- {
- /* We don't need exclusions for this atom */
- lexcls->index[at] = n;
- }
bool isExcludedAtom = !intermolecularExclusionGroup.empty()
&& std::find(intermolecularExclusionGroup.begin(),
if (isExcludedAtom)
{
- if (n + intermolecularExclusionGroup.ssize() > lexcls->nalloc_a)
- {
- lexcls->nalloc_a = over_alloc_large(n + intermolecularExclusionGroup.size());
- srenew(lexcls->a, lexcls->nalloc_a);
- }
for (int qmAtomGlobalIndex : intermolecularExclusionGroup)
{
if (const auto* entry = dd->ga2la->find(qmAtomGlobalIndex))
{
- lexcls->a[n++] = entry->la;
+ exclusionsForAtom.push_back(entry->la);
}
}
}
- }
- lexcls->index[lexcls->nr] = n;
- lexcls->nra = n;
-}
-
-
-/*! \brief Ensure we have enough space in \p ba for \p nindex_max indices */
-static void check_alloc_index(t_blocka* ba, int nindex_max)
-{
- if (nindex_max + 1 > ba->nalloc_index)
- {
- ba->nalloc_index = over_alloc_dd(nindex_max + 1);
- srenew(ba->index, ba->nalloc_index);
+ /* Append the exclusions for this atom to the topology */
+ lexcls->pushBack(exclusionsForAtom);
}
-}
-
-/*! \brief Ensure that we have enough space for exclusion storate in \p lexcls */
-static void check_exclusions_alloc(const gmx_domdec_t* dd, const gmx_domdec_zones_t* zones, t_blocka* lexcls)
-{
- const int nr = zones->iZones.back().iAtomRange.end();
-
- check_alloc_index(lexcls, nr);
- for (size_t thread = 1; thread < dd->reverse_top->th_work.size(); thread++)
- {
- check_alloc_index(&dd->reverse_top->th_work[thread].excl, nr);
- }
-}
-
-/*! \brief Set the total count indexes for the local exclusions, needed by several functions */
-static void finish_local_exclusions(gmx_domdec_t* dd, gmx_domdec_zones_t* zones, t_blocka* lexcls)
-{
- const gmx::Range<int> nonhomeIzonesAtomRange(zones->iZones[0].iAtomRange.end(),
- zones->iZones.back().iAtomRange.end());
-
- if (!dd->haveExclusions)
- {
- /* There are no exclusions involving non-home charge groups,
- * but we need to set the indices for neighborsearching.
- */
- for (int la : nonhomeIzonesAtomRange)
- {
- lexcls->index[la] = lexcls->nra;
- }
-
- /* nr is only used to loop over the exclusions for Ewald and RF,
- * so we can set it to the number of home atoms for efficiency.
- */
- lexcls->nr = nonhomeIzonesAtomRange.begin();
- }
- else
- {
- lexcls->nr = nonhomeIzonesAtomRange.end();
- }
-}
-
-/*! \brief Clear a t_idef struct */
-static void clear_idef(t_idef* idef)
-{
- int ftype;
-
- /* Clear the counts */
- for (ftype = 0; ftype < F_NRE; ftype++)
- {
- idef->il[ftype].nr = 0;
- }
+ GMX_RELEASE_ASSERT(
+ lexcls->ssize() - oldNumLists == at_end - at_start,
+ "The number of exclusion list should match the number of atoms in the range");
}
/*! \brief Generate and store all required local bonded interactions in \p idef and local exclusions in \p lexcls */
-static int make_local_bondeds_excls(gmx_domdec_t* dd,
- gmx_domdec_zones_t* zones,
- const gmx_mtop_t* mtop,
- const int* cginfo,
- gmx_bool bRCheckMB,
- ivec rcheck,
- gmx_bool bRCheck2B,
- real rc,
- t_pbc* pbc_null,
- rvec* cg_cm,
- t_idef* idef,
- t_blocka* lexcls,
- int* excl_count)
+static int make_local_bondeds_excls(gmx_domdec_t* dd,
+ gmx_domdec_zones_t* zones,
+ const gmx_mtop_t* mtop,
+ const int* cginfo,
+ gmx_bool bRCheckMB,
+ ivec rcheck,
+ gmx_bool bRCheck2B,
+ real rc,
+ t_pbc* pbc_null,
+ rvec* cg_cm,
+ InteractionDefinitions* idef,
+ ListOfLists<int>* lexcls,
+ int* excl_count)
{
- int nzone_bondeds, nzone_excl;
+ int nzone_bondeds;
int cg0, cg1;
real rc2;
int nbonded_local;
nzone_bondeds = 1;
}
- if (dd->haveExclusions)
- {
- /* We only use exclusions from i-zones to i- and j-zones */
- nzone_excl = zones->iZones.size();
- }
- else
- {
- /* There are no exclusions and only zone 0 sees itself */
- nzone_excl = 1;
- }
-
- check_exclusions_alloc(dd, zones, lexcls);
+ /* We only use exclusions from i-zones to i- and j-zones */
+ const int numIZonesForExclusions = (dd->haveExclusions ? zones->iZones.size() : 0);
rt = dd->reverse_top;
rc2 = rc * rc;
/* Clear the counts */
- clear_idef(idef);
+ idef->clear();
nbonded_local = 0;
- lexcls->nr = 0;
- lexcls->nra = 0;
+ lexcls->clear();
*excl_count = 0;
for (int izone = 0; izone < nzone_bondeds; izone++)
{
try
{
- int cg0t, cg1t;
- t_idef* idef_t;
- t_blocka* excl_t;
+ int cg0t, cg1t;
+ InteractionDefinitions* idef_t;
cg0t = cg0 + ((cg1 - cg0) * thread) / numThreads;
cg1t = cg0 + ((cg1 - cg0) * (thread + 1)) / numThreads;
else
{
idef_t = &rt->th_work[thread].idef;
- clear_idef(idef_t);
+ idef_t->clear();
}
rt->th_work[thread].nbonded = make_bondeds_zone(
dd, zones, mtop->molblock, bRCheckMB, rcheck, bRCheck2B, rc2, pbc_null,
- cg_cm, idef->iparams, idef_t, izone, gmx::Range<int>(cg0t, cg1t));
+ cg_cm, idef->iparams.data(), idef_t, izone, gmx::Range<int>(cg0t, cg1t));
- if (izone < nzone_excl)
+ if (izone < numIZonesForExclusions)
{
+ ListOfLists<int>* excl_t;
if (thread == 0)
{
+ // Thread 0 stores exclusions directly in the final storage
excl_t = lexcls;
}
else
{
- excl_t = &rt->th_work[thread].excl;
- excl_t->nr = 0;
- excl_t->nra = 0;
+ // Threads > 0 store in temporary storage, starting at list index 0
+ excl_t = &rt->th_work[thread].excl;
+ excl_t->clear();
}
/* No charge groups and no distance check required */
nbonded_local += th_work.nbonded;
}
- if (izone < nzone_excl)
+ if (izone < numIZonesForExclusions)
{
- if (rt->th_work.size() > 1)
+ for (std::size_t th = 1; th < rt->th_work.size(); th++)
{
- combine_blocka(lexcls, rt->th_work);
+ lexcls->appendListOfLists(rt->th_work[th].excl);
}
-
for (const thread_work_t& th_work : rt->th_work)
{
*excl_count += th_work.excl_count;
}
}
- /* Some zones might not have exclusions, but some code still needs to
- * loop over the index, so we set the indices here.
- */
- for (size_t iZone = nzone_excl; iZone < zones->iZones.size(); iZone++)
- {
- set_no_exclusions_zone(zones, iZone, lexcls);
- }
-
- finish_local_exclusions(dd, zones, lexcls);
if (debug)
{
- fprintf(debug, "We have %d exclusions, check count %d\n", lexcls->nra, *excl_count);
+ fprintf(debug, "We have %d exclusions, check count %d\n", lexcls->numElements(), *excl_count);
}
return nbonded_local;
/* Only need to check for dimensions where the part of the box
* that is not communicated is smaller than the cut-off.
*/
- if (d < npbcdim && dd->nc[d] > 1 && (dd->nc[d] - npulse[d]) * cellsize_min[d] < 2 * rc)
+ if (d < npbcdim && dd->numCells[d] > 1
+ && (dd->numCells[d] - npulse[d]) * cellsize_min[d] < 2 * rc)
{
- if (dd->nc[d] == 2)
+ if (dd->numCells[d] == 2)
{
rcheck[d] = TRUE;
bRCheckMB = TRUE;
{
if (fr->bMolPBC)
{
- pbc_null = set_pbc_dd(&pbc, fr->ePBC, dd->nc, TRUE, box);
+ pbc_null = set_pbc_dd(&pbc, fr->pbcType, dd->numCells, TRUE, box);
}
else
{
* we can only do this when we have the charge arrays.
*/
ltop->idef.ilsort = ilsortUNKNOWN;
-
- ltop->atomtypes = mtop.atomtypes;
}
void dd_sort_local_top(gmx_domdec_t* dd, const t_mdatoms* mdatoms, gmx_localtop_t* ltop)
}
}
-void dd_init_local_top(const gmx_mtop_t& top_global, gmx_localtop_t* top)
-{
- /* TODO: Get rid of the const casts below, e.g. by using a reference */
- top->idef.ntypes = top_global.ffparams.numTypes();
- top->idef.atnr = top_global.ffparams.atnr;
- top->idef.functype = const_cast<t_functype*>(top_global.ffparams.functype.data());
- top->idef.iparams = const_cast<t_iparams*>(top_global.ffparams.iparams.data());
- top->idef.fudgeQQ = top_global.ffparams.fudgeQQ;
- top->idef.cmap_grid = new gmx_cmap_t;
- *top->idef.cmap_grid = top_global.ffparams.cmap_grid;
-
- top->idef.ilsort = ilsortUNKNOWN;
- top->useInDomainDecomp_ = true;
-}
-
void dd_init_local_state(gmx_domdec_t* dd, const t_state* state_global, t_state* state_local)
{
int buf[NITEM_DD_INIT_LOCAL_STATE];
}
}
-t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_mb)
+t_blocka* makeBondedLinks(const gmx_mtop_t& mtop, gmx::ArrayRef<cginfo_mb_t> cginfo_mb)
{
t_blocka* link;
cginfo_mb_t* cgi_mb;
*/
reverse_ilist_t ril_intermol;
- if (mtop->bIntermolecularInteractions)
+ if (mtop.bIntermolecularInteractions)
{
t_atoms atoms;
- atoms.nr = mtop->natoms;
+ atoms.nr = mtop.natoms;
atoms.atom = nullptr;
- GMX_RELEASE_ASSERT(mtop->intermolecular_ilist,
+ GMX_RELEASE_ASSERT(mtop.intermolecular_ilist,
"We should have an ilist when intermolecular interactions are on");
- make_reverse_ilist(*mtop->intermolecular_ilist, &atoms, FALSE, FALSE, FALSE, TRUE, &ril_intermol);
+ make_reverse_ilist(*mtop.intermolecular_ilist, &atoms, FALSE, FALSE, FALSE, TRUE, &ril_intermol);
}
snew(link, 1);
- snew(link->index, mtop->natoms + 1);
+ snew(link->index, mtop.natoms + 1);
link->nalloc_a = 0;
link->a = nullptr;
link->index[0] = 0;
int cg_offset = 0;
int ncgi = 0;
- for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
+ for (size_t mb = 0; mb < mtop.molblock.size(); mb++)
{
- const gmx_molblock_t& molb = mtop->molblock[mb];
+ const gmx_molblock_t& molb = mtop.molblock[mb];
if (molb.nmol == 0)
{
continue;
}
- const gmx_moltype_t& molt = mtop->moltype[molb.type];
+ const gmx_moltype_t& molt = mtop.moltype[molb.type];
/* Make a reverse ilist in which the interactions are linked
* to all atoms, not only the first atom as in gmx_reverse_top.
* The constraints are discarded here.
cgi_mb = &cginfo_mb[mb];
int mol;
- for (mol = 0; mol < (mtop->bIntermolecularInteractions ? molb.nmol : 1); mol++)
+ for (mol = 0; mol < (mtop.bIntermolecularInteractions ? molb.nmol : 1); mol++)
{
for (int a = 0; a < molt.atoms.nr; a++)
{
i += nral_rt(ftype);
}
- if (mtop->bIntermolecularInteractions)
+ if (mtop.bIntermolecularInteractions)
{
int i = ril_intermol.index[cg_gl];
while (i < ril_intermol.index[cg_gl + 1])
if (debug)
{
- fprintf(debug, "Of the %d atoms %d are linked via bonded interactions\n", mtop->natoms, ncgi);
+ fprintf(debug, "Of the %d atoms %d are linked via bonded interactions\n", mtop.natoms, ncgi);
}
return link;
}
if (bExcl)
{
- const t_blocka* excls = &molt->excls;
- for (int ai = 0; ai < excls->nr; ai++)
+ const auto& excls = molt->excls;
+ for (gmx::index ai = 0; ai < excls.ssize(); ai++)
{
- for (int j = excls->index[ai]; j < excls->index[ai + 1]; j++)
+ for (const int aj : excls[ai])
{
- int aj = excls->a[j];
if (ai != aj)
{
real rij2 = distance2(cg_cm[ai], cg_cm[aj]);
static void bonded_distance_intermol(const InteractionLists& ilists_intermol,
gmx_bool bBCheck,
const rvec* x,
- int ePBC,
+ PbcType pbcType,
const matrix box,
bonded_distance_t* bd_2b,
bonded_distance_t* bd_mb)
{
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (int ftype = 0; ftype < F_NRE; ftype++)
{
bool hasVsite = false;
for (int i = 0; i < F_NRE; i++)
{
- if ((interaction_function[i].flags & IF_VSITE) && molt.ilist[i].size() > 0)
+ if ((interaction_function[i].flags & IF_VSITE) && !molt.ilist[i].empty())
{
hasVsite = true;
}
//! Returns coordinates not broken over PBC for a molecule
static void getWholeMoleculeCoordinates(const gmx_moltype_t* molt,
const gmx_ffparams_t* ffparams,
- int ePBC,
+ PbcType pbcType,
t_graph* graph,
const matrix box,
const rvec* x,
{
int n, i;
- if (ePBC != epbcNONE)
+ if (pbcType != PbcType::No)
{
- mk_mshift(nullptr, graph, ePBC, box, x);
+ mk_mshift(nullptr, graph, pbcType, box, x);
shift_x(graph, box, x, xs);
/* By doing an extra mk_mshift the molecules that are broken
* will be made whole again. Such are the healing powers
* of GROMACS.
*/
- mk_mshift(nullptr, graph, ePBC, box, xs);
+ mk_mshift(nullptr, graph, pbcType, box, xs);
}
else
{
if (moltypeHasVsite(*molt))
{
- /* Convert to old, deprecated format */
- t_ilist ilist[F_NRE];
- for (int ftype = 0; ftype < F_NRE; ftype++)
- {
- if (interaction_function[ftype].flags & IF_VSITE)
- {
- ilist[ftype].nr = molt->ilist[ftype].size();
- ilist[ftype].iatoms = const_cast<int*>(molt->ilist[ftype].iatoms.data());
- }
- }
-
- construct_vsites(nullptr, xs, 0.0, nullptr, ffparams->iparams.data(), ilist, epbcNONE, TRUE,
- nullptr, nullptr);
+ construct_vsites(nullptr, xs, 0.0, nullptr, ffparams->iparams, molt->ilist, PbcType::No,
+ TRUE, nullptr, nullptr);
}
}
{
gmx_bool bExclRequired;
int at_offset;
- t_graph graph;
rvec* xs;
bonded_distance_t bd_2b = { 0, -1, -1, -1 };
bonded_distance_t bd_mb = { 0, -1, -1, -1 };
}
else
{
- if (ir->ePBC != epbcNONE)
+ t_graph graph;
+ if (ir->pbcType != PbcType::No)
{
- mk_graph_moltype(molt, &graph);
+ graph = mk_graph_moltype(molt);
}
snew(xs, molt.atoms.nr);
for (int mol = 0; mol < molb.nmol; mol++)
{
- getWholeMoleculeCoordinates(&molt, &mtop->ffparams, ir->ePBC, &graph, box,
+ getWholeMoleculeCoordinates(&molt, &mtop->ffparams, ir->pbcType, &graph, box,
x + at_offset, xs);
bonded_distance_t bd_mol_2b = { 0, -1, -1, -1 };
at_offset += molt.atoms.nr;
}
sfree(xs);
- if (ir->ePBC != epbcNONE)
- {
- done_graph(&graph);
- }
}
}
GMX_RELEASE_ASSERT(mtop->intermolecular_ilist,
"We should have an ilist when intermolecular interactions are on");
- bonded_distance_intermol(*mtop->intermolecular_ilist, bBCheck, x, ir->ePBC, box, &bd_2b, &bd_mb);
+ bonded_distance_intermol(*mtop->intermolecular_ilist, bBCheck, x, ir->pbcType, box, &bd_2b, &bd_mb);
}
*r_2b = sqrt(bd_2b.r2);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2006,2007,2008,2009,2010,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2006,2007,2008,2009,2010 by the GROMACS development team.
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-int dd_make_local_vsites(gmx_domdec_t* dd, int at_start, t_ilist* lil)
+int dd_make_local_vsites(gmx_domdec_t* dd, int at_start, gmx::ArrayRef<InteractionList> lil)
{
std::vector<int>& ireq = dd->vsite_requestedGlobalAtomIndices;
gmx::HashedMap<int>* ga2la_specat = dd->ga2la_vsite;
{
if (interaction_function[ftype].flags & IF_VSITE)
{
- const int nral = NRAL(ftype);
- const t_ilist& lilf = lil[ftype];
- for (int i = 0; i < lilf.nr; i += 1 + nral)
+ const int nral = NRAL(ftype);
+ const InteractionList& lilf = lil[ftype];
+ for (int i = 0; i < lilf.size(); i += 1 + nral)
{
- const t_iatom* iatoms = lilf.iatoms + i;
+ const int* iatoms = lilf.iatoms.data() + i;
/* Check if we have the other atoms */
for (int j = 1; j < 1 + nral; j++)
{
{
if (interaction_function[ftype].flags & IF_VSITE)
{
- const int nral = NRAL(ftype);
- t_ilist& lilf = lil[ftype];
- for (int i = 0; i < lilf.nr; i += 1 + nral)
+ const int nral = NRAL(ftype);
+ InteractionList& lilf = lil[ftype];
+ for (int i = 0; i < lilf.size(); i += 1 + nral)
{
- t_iatom* iatoms = lilf.iatoms + i;
+ t_iatom* iatoms = lilf.iatoms.data() + i;
for (int j = 1; j < 1 + nral; j++)
{
if (iatoms[j] < 0)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2005,2006,2007,2008,2009,2010,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2005,2006,2007,2008,2009 by the GROMACS development team.
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_DOMDEC_DOMDEC_VSITE_H
#define GMX_DOMDEC_DOMDEC_VSITE_H
-struct t_ilist;
+#include "gromacs/utility/arrayref.h"
+
struct gmx_domdec_t;
+struct InteractionList;
/*! \brief Clears the local indices for the virtual site communication setup */
void dd_clear_local_vsite_indices(struct gmx_domdec_t* dd);
/*! \brief Sets up communication and atom indices for all local vsites */
-int dd_make_local_vsites(struct gmx_domdec_t* dd, int at_start, struct t_ilist* lil);
+int dd_make_local_vsites(struct gmx_domdec_t* dd, int at_start, gmx::ArrayRef<InteractionList> lil);
/*! \brief Initializes the data structures for virtual site communication */
void init_domdec_vsites(struct gmx_domdec_t* dd, int n_intercg_vsite);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
else
{
- if (d < ddbox->npbcdim && dd->nc[d] > 1)
+ if (d < ddbox->npbcdim && dd->numCells[d] > 1)
{
tric[d][i] = box[i][d] / box[i][i];
}
}
sprintf(fname, "%s_%s.pdb", fn, gmx_step_str(step, buf));
out = gmx_fio_fopen(fname, "w");
- gmx_write_pdb_box(out, dd->unitCellInfo.haveScrewPBC ? epbcSCREW : epbcXYZ, box);
+ gmx_write_pdb_box(out, dd->unitCellInfo.haveScrewPBC ? PbcType::Screw : PbcType::Xyz, box);
a = 1;
for (i = 0; i < dd->nnodes; i++)
{
out = gmx_fio_fopen(fname, "w");
fprintf(out, "TITLE %s\n", title);
- gmx_write_pdb_box(out, dd->unitCellInfo.haveScrewPBC ? epbcSCREW : epbcXYZ, box);
+ gmx_write_pdb_box(out, dd->unitCellInfo.haveScrewPBC ? PbcType::Screw : PbcType::Xyz, box);
int molb = 0;
for (int i = 0; i < natoms; i++)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/gmxmpi.h"
struct gmx_domdec_t;
+class DeviceContext;
+class DeviceStream;
class GpuEventSynchronizer;
namespace gmx
*
* \param [inout] dd domdec structure
* \param [in] mpi_comm_mysim communicator used for simulation
+ * \param [in] deviceContext GPU device context
* \param [in] streamLocal local NB CUDA stream.
* \param [in] streamNonLocal non-local NB CUDA stream.
+ * \param [in] pulse the communication pulse for this instance
*/
- GpuHaloExchange(gmx_domdec_t* dd, MPI_Comm mpi_comm_mysim, void* streamLocal, void* streamNonLocal);
+ GpuHaloExchange(gmx_domdec_t* dd,
+ MPI_Comm mpi_comm_mysim,
+ const DeviceContext& deviceContext,
+ const DeviceStream& streamLocal,
+ const DeviceStream& streamNonLocal,
+ int pulse);
~GpuHaloExchange();
/*! \brief
* \param [in] d_coordinateBuffer pointer to coordinates buffer in GPU memory
* \param [in] d_forcesBuffer pointer to coordinates buffer in GPU memory
*/
- void reinitHalo(DeviceBuffer<float> d_coordinateBuffer, DeviceBuffer<float> d_forcesBuffer);
+ void reinitHalo(DeviceBuffer<RVec> d_coordinateBuffer, DeviceBuffer<RVec> d_forcesBuffer);
/*! \brief GPU halo exchange of coordinates buffer.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*!\brief Constructor stub. */
GpuHaloExchange::GpuHaloExchange(gmx_domdec_t* /* dd */,
MPI_Comm /* mpi_comm_mysim */,
- void* /*streamLocal */,
- void* /*streamNonLocal */) :
+ const DeviceContext& /* deviceContext */,
+ const DeviceStream& /*streamLocal */,
+ const DeviceStream& /*streamNonLocal */,
+ int /*pulse */) :
impl_(nullptr)
{
GMX_ASSERT(false,
GpuHaloExchange::~GpuHaloExchange() = default;
/*!\brief init halo exhange stub. */
-void GpuHaloExchange::reinitHalo(DeviceBuffer<float> /* d_coordinatesBuffer */,
- DeviceBuffer<float> /* d_forcesBuffer */)
+void GpuHaloExchange::reinitHalo(DeviceBuffer<RVec> /* d_coordinatesBuffer */,
+ DeviceBuffer<RVec> /* d_forcesBuffer */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for GPU Halo Exchange was called insted of the correct implementation.");
}
void GpuHaloExchange::communicateHaloCoordinates(const matrix /* box */,
GpuEventSynchronizer* /*coordinatesOnDeviceEvent*/)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for GPU Halo Exchange exchange was called insted of the correct "
"implementation.");
}
/*!\brief apply F halo exchange stub. */
void GpuHaloExchange::communicateHaloForces(bool gmx_unused accumulateForces)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for GPU Halo Exchange was called insted of the correct implementation.");
}
/*!\brief get forces ready on device event stub. */
GpuEventSynchronizer* GpuHaloExchange::getForcesReadyOnDeviceEvent()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for GPU Halo Exchange was called insted of the correct implementation.");
return nullptr;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/domdec/gpuhaloexchange.h"
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/devicebuffer.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
+#include "gromacs/gpu_utils/typecasts.cuh"
#include "gromacs/gpu_utils/vectype_ops.cuh"
+#include "gromacs/math/vectypes.h"
#include "gromacs/pbcutil/ishift.h"
#include "gromacs/utility/gmxmpi.h"
d_x_ = d_coordinatesBuffer;
d_f_ = d_forcesBuffer;
- cudaStream_t stream = nonLocalStream_;
- int nzone = 1;
const gmx_domdec_comm_t& comm = *dd_->comm;
const gmx_domdec_comm_dim_t& cd = comm.cd[0];
- const gmx_domdec_ind_t& ind = cd.ind[0];
- int newSize = ind.nsend[nzone + 1];
+ const gmx_domdec_ind_t& ind = cd.ind[pulse_];
+ int newSize = ind.nsend[nzone_ + 1];
- GMX_RELEASE_ASSERT(cd.numPulses() == 1,
- "Multiple pulses are not yet supported in GPU halo exchange");
GMX_ASSERT(cd.receiveInPlace, "Out-of-place receive is not yet supported in GPU halo exchange");
// reallocates only if needed
// reallocate on device only if needed
if (newSize > maxPackedBufferSize_)
{
- reallocateDeviceBuffer(&d_indexMap_, newSize, &indexMapSize_, &indexMapSizeAlloc_, nullptr);
- reallocateDeviceBuffer(&d_sendBuf_, newSize, &sendBufSize_, &sendBufSizeAlloc_, nullptr);
- reallocateDeviceBuffer(&d_recvBuf_, newSize, &recvBufSize_, &recvBufSizeAlloc_, nullptr);
+ reallocateDeviceBuffer(&d_indexMap_, newSize, &indexMapSize_, &indexMapSizeAlloc_, deviceContext_);
+ reallocateDeviceBuffer(&d_sendBuf_, newSize, &sendBufSize_, &sendBufSizeAlloc_, deviceContext_);
+ reallocateDeviceBuffer(&d_recvBuf_, newSize, &recvBufSize_, &recvBufSizeAlloc_, deviceContext_);
maxPackedBufferSize_ = newSize;
}
GMX_ASSERT(ind.index.size() == h_indexMap_.size(), "Size mismatch");
std::copy(ind.index.begin(), ind.index.end(), h_indexMap_.begin());
- copyToDeviceBuffer(&d_indexMap_, h_indexMap_.data(), 0, newSize, stream,
+ copyToDeviceBuffer(&d_indexMap_, h_indexMap_.data(), 0, newSize, nonLocalStream_,
GpuApiCallBehavior::Async, nullptr);
// This rank will push data to its neighbor, so needs to know
// Coordinates buffer:
#if GMX_MPI
- void* recvPtr = static_cast<void*>(&d_coordinatesBuffer[numHomeAtoms_]);
+ int pulseOffset = 0;
+ for (int p = pulse_ - 1; p >= 0; p--)
+ {
+ pulseOffset += cd.ind[p].nrecv[nzone_ + 1];
+ }
+ // void* recvPtr = static_cast<void*>(&d_coordinatesBuffer[numHomeAtoms_ + pulseOffset]);
+ void* recvPtr = static_cast<void*>(&d_x_[numHomeAtoms_ + pulseOffset]);
MPI_Sendrecv(&recvPtr, sizeof(void*), MPI_BYTE, recvRankX_, 0, &remoteXPtr_, sizeof(void*),
MPI_BYTE, sendRankX_, 0, mpi_comm_mysim_, MPI_STATUS_IGNORE);
MPI_BYTE, sendRankF_, 0, mpi_comm_mysim_, MPI_STATUS_IGNORE);
#endif
-
return;
}
GpuEventSynchronizer* coordinatesReadyOnDeviceEvent)
{
- // ensure stream waits until coordinate data is available on device
- coordinatesReadyOnDeviceEvent->enqueueWaitEvent(nonLocalStream_);
+ if (pulse_ == 0)
+ {
+ // ensure stream waits until coordinate data is available on device
+ coordinatesReadyOnDeviceEvent->enqueueWaitEvent(nonLocalStream_);
+ }
// launch kernel to pack send buffer
KernelLaunchConfig config;
config.gridSize[1] = 1;
config.gridSize[2] = 1;
config.sharedMemorySize = 0;
- config.stream = nonLocalStream_;
const float3* sendBuf = d_sendBuf_;
const float3* d_x = d_x_;
const auto kernelArgs = prepareGpuKernelArguments(kernelFn, config, &sendBuf, &d_x,
&indexMap, &size, &coordinateShift);
- launchGpuKernel(kernelFn, config, nullptr, "Domdec GPU Apply X Halo Exchange", kernelArgs);
+ launchGpuKernel(kernelFn, config, nonLocalStream_, nullptr,
+ "Domdec GPU Apply X Halo Exchange", kernelArgs);
}
communicateHaloData(d_x_, HaloQuantity::HaloCoordinates, coordinatesReadyOnDeviceEvent);
float3* d_f = d_f_;
- if (!accumulateForces)
+ if (pulse_ == (dd_->comm->cd[0].numPulses() - 1))
{
- // Clear local portion of force array (in local stream)
- cudaMemsetAsync(d_f, 0, numHomeAtoms_ * sizeof(rvec), localStream_);
- }
+ if (!accumulateForces)
+ {
+ // Clear local portion of force array (in local stream)
+ cudaMemsetAsync(d_f, 0, numHomeAtoms_ * sizeof(rvec), localStream_.stream());
+ }
- // ensure non-local stream waits for local stream, due to dependence on
- // the previous H2D copy of CPU forces (if accumulateForces is true)
- // or the above clearing.
- // TODO remove this dependency on localStream - edmine issue #3093
- GpuEventSynchronizer eventLocal;
- eventLocal.markEvent(localStream_);
- eventLocal.enqueueWaitEvent(nonLocalStream_);
+ // ensure non-local stream waits for local stream, due to dependence on
+ // the previous H2D copy of CPU forces (if accumulateForces is true)
+ // or the above clearing.
+ // TODO remove this dependency on localStream - edmine Issue #3093
+ GpuEventSynchronizer eventLocal;
+ eventLocal.markEvent(localStream_);
+ eventLocal.enqueueWaitEvent(nonLocalStream_);
+ }
// Unpack halo buffer into force array
config.gridSize[1] = 1;
config.gridSize[2] = 1;
config.sharedMemorySize = 0;
- config.stream = nonLocalStream_;
const float3* recvBuf = d_recvBuf_;
const int* indexMap = d_indexMap_;
const int size = fRecvSize_;
+ if (pulse_ > 0)
+ {
+ // We need to accumulate rather than set, since it is possible
+ // that, in this pulse, a value could be written to a location
+ // corresponding to the halo region of a following pulse.
+ accumulateForces = true;
+ }
+
if (size > 0)
{
auto kernelFn = accumulateForces ? unpackRecvBufKernel<true> : unpackRecvBufKernel<false>;
const auto kernelArgs =
prepareGpuKernelArguments(kernelFn, config, &d_f, &recvBuf, &indexMap, &size);
- launchGpuKernel(kernelFn, config, nullptr, "Domdec GPU Apply F Halo Exchange", kernelArgs);
+ launchGpuKernel(kernelFn, config, nonLocalStream_, nullptr,
+ "Domdec GPU Apply F Halo Exchange", kernelArgs);
+ }
+
+ if (pulse_ == 0)
+ {
+ fReadyOnDevice_.markEvent(nonLocalStream_);
}
- fReadyOnDevice_.markEvent(nonLocalStream_);
}
}
else
{
- sendPtr = static_cast<void*>(&(d_ptr[numHomeAtoms_]));
+ int recvOffset = dd_->comm->atomRanges.end(DDAtomRanges::Type::Zones);
+ for (int p = pulse_; p < dd_->comm->cd[0].numPulses(); p++)
+ {
+ recvOffset -= dd_->comm->cd[0].ind[p].nrecv[nzone_ + 1];
+ }
+ sendPtr = static_cast<void*>(&(d_ptr[recvOffset]));
sendSize = fSendSize_;
remotePtr = remoteFPtr_;
sendRank = sendRankF_;
int recvRank)
{
- cudaError_t stat;
- cudaStream_t stream = nonLocalStream_;
+ cudaError_t stat;
// We asynchronously push data to remote rank. The remote
// destination pointer has already been set in the init fn. We
if (sendSize > 0)
{
stat = cudaMemcpyAsync(remotePtr, sendPtr, sendSize * DIM * sizeof(float),
- cudaMemcpyDeviceToDevice, stream);
+ cudaMemcpyDeviceToDevice, nonLocalStream_.stream());
CU_RET_ERR(stat, "cudaMemcpyAsync on GPU Domdec CUDA direct data transfer failed");
}
// to its stream.
GpuEventSynchronizer* haloDataTransferRemote;
- haloDataTransferLaunched_->markEvent(stream);
+ haloDataTransferLaunched_->markEvent(nonLocalStream_);
MPI_Sendrecv(&haloDataTransferLaunched_, sizeof(GpuEventSynchronizer*), MPI_BYTE, sendRank, 0,
&haloDataTransferRemote, sizeof(GpuEventSynchronizer*), MPI_BYTE, recvRank, 0,
mpi_comm_mysim_, MPI_STATUS_IGNORE);
- haloDataTransferRemote->enqueueWaitEvent(stream);
+ haloDataTransferRemote->enqueueWaitEvent(nonLocalStream_);
#else
GMX_UNUSED_VALUE(sendRank);
GMX_UNUSED_VALUE(recvRank);
}
/*! \brief Create Domdec GPU object */
-GpuHaloExchange::Impl::Impl(gmx_domdec_t* dd, MPI_Comm mpi_comm_mysim, void* localStream, void* nonLocalStream) :
+GpuHaloExchange::Impl::Impl(gmx_domdec_t* dd,
+ MPI_Comm mpi_comm_mysim,
+ const DeviceContext& deviceContext,
+ const DeviceStream& localStream,
+ const DeviceStream& nonLocalStream,
+ int pulse) :
dd_(dd),
sendRankX_(dd->neighbor[0][1]),
recvRankX_(dd->neighbor[0][0]),
usePBC_(dd->ci[dd->dim[0]] == 0),
haloDataTransferLaunched_(new GpuEventSynchronizer()),
mpi_comm_mysim_(mpi_comm_mysim),
- localStream_(*static_cast<cudaStream_t*>(localStream)),
- nonLocalStream_(*static_cast<cudaStream_t*>(nonLocalStream))
+ deviceContext_(deviceContext),
+ localStream_(localStream),
+ nonLocalStream_(nonLocalStream),
+ pulse_(pulse)
{
GMX_RELEASE_ASSERT(GMX_THREAD_MPI,
changePinningPolicy(&h_indexMap_, gmx::PinningPolicy::PinnedIfSupported);
- allocateDeviceBuffer(&d_fShift_, 1, nullptr);
+ allocateDeviceBuffer(&d_fShift_, 1, deviceContext_);
}
GpuHaloExchange::Impl::~Impl()
delete haloDataTransferLaunched_;
}
-GpuHaloExchange::GpuHaloExchange(gmx_domdec_t* dd, MPI_Comm mpi_comm_mysim, void* localStream, void* nonLocalStream) :
- impl_(new Impl(dd, mpi_comm_mysim, localStream, nonLocalStream))
+GpuHaloExchange::GpuHaloExchange(gmx_domdec_t* dd,
+ MPI_Comm mpi_comm_mysim,
+ const DeviceContext& deviceContext,
+ const DeviceStream& localStream,
+ const DeviceStream& nonLocalStream,
+ int pulse) :
+ impl_(new Impl(dd, mpi_comm_mysim, deviceContext, localStream, nonLocalStream, pulse))
{
}
GpuHaloExchange::~GpuHaloExchange() = default;
-void GpuHaloExchange::reinitHalo(DeviceBuffer<float> d_coordinatesBuffer, DeviceBuffer<float> d_forcesBuffer)
+void GpuHaloExchange::reinitHalo(DeviceBuffer<RVec> d_coordinatesBuffer, DeviceBuffer<RVec> d_forcesBuffer)
{
- impl_->reinitHalo(reinterpret_cast<float3*>(d_coordinatesBuffer),
- reinterpret_cast<float3*>(d_forcesBuffer));
+ impl_->reinitHalo(asFloat3(d_coordinatesBuffer), asFloat3(d_forcesBuffer));
}
void GpuHaloExchange::communicateHaloCoordinates(const matrix box,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_DOMDEC_GPUHALOEXCHANGE_IMPL_H
#include "gromacs/domdec/gpuhaloexchange.h"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/utility/gmxmpi.h"
*
* \param [inout] dd domdec structure
* \param [in] mpi_comm_mysim communicator used for simulation
+ * \param [in] deviceContext GPU device context
* \param [in] localStream local NB CUDA stream
* \param [in] nonLocalStream non-local NB CUDA stream
+ * \param [in] pulse the communication pulse for this instance
*/
- Impl(gmx_domdec_t* dd, MPI_Comm mpi_comm_mysim, void* localStream, void* nonLocalStream);
+ Impl(gmx_domdec_t* dd,
+ MPI_Comm mpi_comm_mysim,
+ const DeviceContext& deviceContext,
+ const DeviceStream& localStream,
+ const DeviceStream& nonLocalStream,
+ int pulse);
~Impl();
/*! \brief
GpuEventSynchronizer* haloDataTransferLaunched_ = nullptr;
//! MPI communicator used for simulation
MPI_Comm mpi_comm_mysim_;
+ //! GPU context object
+ const DeviceContext& deviceContext_;
//! CUDA stream for local non-bonded calculations
- cudaStream_t localStream_ = nullptr;
+ const DeviceStream& localStream_;
//! CUDA stream for non-local non-bonded calculations
- cudaStream_t nonLocalStream_ = nullptr;
+ const DeviceStream& nonLocalStream_;
//! full coordinates buffer in GPU memory
float3* d_x_ = nullptr;
//! full forces buffer in GPU memory
float3* d_f_ = nullptr;
//! An event recorded once the exchanged forces are ready on the GPU
GpuEventSynchronizer fReadyOnDevice_;
+ //! The pulse corresponding to this halo exchange instance
+ int pulse_ = 0;
+ //! Number of zones. Always 1 for 1-D case.
+ const int nzone_ = 1;
};
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief Global indices of the atoms in this set. */
const std::vector<int> globalIndex_;
/*! \brief Maps indices on this rank [0..num_atoms_local_) to global atom indicices,
- * so that localIndex[i] = globalIndex[collectiveIndex[i]].
+ * so that localIndex[i] identifies the same atom as globalIndex[collectiveIndex[i]].
*
* This translation of locally dense atom data to global representation,
* allows to adresses per-atom properties, e.g., scattering factors,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/pbcutil/mshift.h"
+#include "gromacs/mdtypes/interaction_const.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
+namespace gmx
+{
+
/* TODO: Add a routine that collects the initial setup of the algorithms.
*
* The final solution should be an MD algorithm base class with methods
* for initialization and atom-data setup.
*/
-void mdAlgorithmsSetupAtomData(const t_commrec* cr,
- const t_inputrec* ir,
- const gmx_mtop_t& top_global,
- gmx_localtop_t* top,
- t_forcerec* fr,
- t_graph** graph,
- gmx::MDAtoms* mdAtoms,
- gmx::Constraints* constr,
- gmx_vsite_t* vsite,
- gmx_shellfc_t* shellfc)
+void mdAlgorithmsSetupAtomData(const t_commrec* cr,
+ const t_inputrec* ir,
+ const gmx_mtop_t& top_global,
+ gmx_localtop_t* top,
+ t_forcerec* fr,
+ PaddedHostVector<RVec>* force,
+ MDAtoms* mdAtoms,
+ Constraints* constr,
+ gmx_vsite_t* vsite,
+ gmx_shellfc_t* shellfc)
{
bool usingDomDec = DOMAINDECOMP(cr);
- int numAtomIndex, numHomeAtoms;
+ int numAtomIndex;
int* atomIndex;
+ int numHomeAtoms;
+ int numTotalAtoms;
if (usingDomDec)
{
- numAtomIndex = dd_natoms_mdatoms(cr->dd);
- atomIndex = cr->dd->globalAtomIndices.data();
- numHomeAtoms = dd_numHomeAtoms(*cr->dd);
+ numAtomIndex = dd_natoms_mdatoms(cr->dd);
+ atomIndex = cr->dd->globalAtomIndices.data();
+ numHomeAtoms = dd_numHomeAtoms(*cr->dd);
+ numTotalAtoms = dd_natoms_mdatoms(cr->dd);
}
else
{
- numAtomIndex = -1;
- atomIndex = nullptr;
- numHomeAtoms = top_global.natoms;
+ numAtomIndex = -1;
+ atomIndex = nullptr;
+ numHomeAtoms = top_global.natoms;
+ numTotalAtoms = top_global.natoms;
}
+
+ if (force != nullptr)
+ {
+ /* We need to allocate one element extra, since we might use
+ * (unaligned) 4-wide SIMD loads to access rvec entries.
+ */
+ force->resizeWithPadding(numTotalAtoms);
+ }
+
atoms2md(&top_global, ir, numAtomIndex, atomIndex, numHomeAtoms, mdAtoms);
auto mdatoms = mdAtoms->mdatoms();
}
}
- if (!usingDomDec && ir->ePBC != epbcNONE && !fr->bMolPBC)
- {
- GMX_ASSERT(graph != nullptr, "We use a graph with PBC (no periodic mols) and without DD");
-
- *graph = mk_graph(nullptr, &(top->idef), 0, top_global.natoms, FALSE, FALSE);
- }
- else if (graph != nullptr)
- {
- *graph = nullptr;
- }
-
/* Note that with DD only flexible constraints, not shells, are supported
* and these don't require setup in make_local_shells().
*
if (constr)
{
- constr->setConstraints(*top, *mdatoms);
+ constr->setConstraints(top, *mdatoms);
}
}
+
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_DOMDEC_MDSETUP_H
#define GMX_DOMDEC_MDSETUP_H
+#include "gromacs/gpu_utils/hostallocator.h"
+#include "gromacs/math/vectypes.h"
+
struct bonded_threading_t;
struct gmx_localtop_t;
struct gmx_mtop_t;
struct gmx_vsite_t;
struct t_commrec;
struct t_forcerec;
-struct t_graph;
struct t_inputrec;
struct t_mdatoms;
{
class Constraints;
class MDAtoms;
-} // namespace gmx
/*! \brief Gets the local shell with domain decomposition
*
* \param[in] top_global The global topology
* \param[in,out] top The local topology
* \param[in,out] fr The force calculation parameter/data record
- * \param[out] graph The molecular graph, can be NULL
+ * \param[out] force The force buffer
* \param[out] mdAtoms The MD atom data
* \param[in,out] constr The constraints handler, can be NULL
* \param[in,out] vsite The virtual site data, can be NULL
* \param[in,out] shellfc The shell/flexible-constraint data, can be NULL
*/
-void mdAlgorithmsSetupAtomData(const t_commrec* cr,
- const t_inputrec* ir,
- const gmx_mtop_t& top_global,
- gmx_localtop_t* top,
- t_forcerec* fr,
- t_graph** graph,
- gmx::MDAtoms* mdAtoms,
- gmx::Constraints* constr,
- gmx_vsite_t* vsite,
- gmx_shellfc_t* shellfc);
+void mdAlgorithmsSetupAtomData(const t_commrec* cr,
+ const t_inputrec* ir,
+ const gmx_mtop_t& top_global,
+ gmx_localtop_t* top,
+ t_forcerec* fr,
+ PaddedHostVector<RVec>* force,
+ MDAtoms* mdAtoms,
+ Constraints* constr,
+ gmx_vsite_t* vsite,
+ gmx_shellfc_t* shellfc);
+
+} // namespace gmx
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/ga2la.h"
#include "gromacs/domdec/localatomsetmanager.h"
#include "gromacs/domdec/mdsetup.h"
-#include "gromacs/ewald/pme.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/imd/imd.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/nblist.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/nbnxm/nbnxm.h"
if (applyPbc)
{
/* Take the minimum to avoid double communication */
- numPulsesMin = std::min(numPulses, dd->nc[dim] - 1 - numPulses);
+ numPulsesMin = std::min(numPulses, dd->numCells[dim] - 1 - numPulses);
}
else
{
for (int pulse = 0; pulse < numPulses; pulse++)
{
/* Communicate all the zone information backward */
- bool receiveValidData = (applyPbc || dd->ci[dim] < dd->nc[dim] - 1);
+ bool receiveValidData = (applyPbc || dd->ci[dim] < dd->numCells[dim] - 1);
static_assert(
sizeof(gmx_ddzone_t) == c_ddzoneNumReals * sizeof(real),
*/
buf_s[i] = buf_r[i];
}
- if (((applyPbc || dd->ci[dim] + numPulses < dd->nc[dim]) && pulse == numPulses - 1)
- || (!applyPbc && dd->ci[dim] + 1 + pulse == dd->nc[dim] - 1))
+ if (((applyPbc || dd->ci[dim] + numPulses < dd->numCells[dim]) && pulse == numPulses - 1)
+ || (!applyPbc && dd->ci[dim] + 1 + pulse == dd->numCells[dim] - 1))
{
/* Store the extremes */
int pos = 0;
{
if (fr != nullptr)
{
- const cginfo_mb_t* cginfo_mb = fr->cginfo_mb;
- gmx::ArrayRef<int> cginfo = fr->cginfo;
+ gmx::ArrayRef<cginfo_mb_t> cginfo_mb = fr->cginfo_mb;
+ gmx::ArrayRef<int> cginfo = fr->cginfo;
for (int cg = cg0; cg < cg1; cg++)
{
dim = dd->dim[dim_ind];
/* Without PBC we don't have restrictions on the outer cells */
- if (!(dim >= ddbox->npbcdim && (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1))
+ if (!(dim >= ddbox->npbcdim && (dd->ci[dim] == 0 || dd->ci[dim] == dd->numCells[dim] - 1))
&& isDlbOn(comm)
&& (comm->cell_x1[dim] - comm->cell_x0[dim]) * ddbox->skew_fac[dim] < comm->cellsize_min[dim])
{
load->mdf = 0;
load->pme = 0;
int pos = 0;
- for (int i = 0; i < dd->nc[dim]; i++)
+ for (int i = 0; i < dd->numCells[dim]; i++)
{
load->sum += load->load[pos++];
load->max = std::max(load->max, load->load[pos]);
}
if (isDlbOn(comm) && rowMaster->dlbIsLimited)
{
- load->sum_m *= dd->nc[dim];
+ load->sum_m *= dd->numCells[dim];
load->flags |= (1 << d);
}
}
{
comm->load[d].sum_m = comm->load[d].sum;
- int nc = dd->nc[dd->dim[d]];
+ int nc = dd->numCells[dd->dim[d]];
for (int i = 0; i < nc; i++)
{
rowMaster->cellFrac[i] = i / static_cast<real>(nc);
const int* recv_i,
gmx::ArrayRef<gmx::RVec> x,
gmx::ArrayRef<const gmx::RVec> recv_vr,
- cginfo_mb_t* cginfo_mb,
+ gmx::ArrayRef<cginfo_mb_t> cginfo_mb,
gmx::ArrayRef<int> cginfo)
{
gmx_domdec_ind_t *ind, *ind_p;
}
//! Prepare DD communication.
-static void setup_dd_communication(gmx_domdec_t* dd,
- matrix box,
- gmx_ddbox_t* ddbox,
- t_forcerec* fr,
- t_state* state,
- PaddedHostVector<gmx::RVec>* f)
+static void setup_dd_communication(gmx_domdec_t* dd, matrix box, gmx_ddbox_t* ddbox, t_forcerec* fr, t_state* state)
{
int dim_ind, dim, dim0, dim1, dim2, dimd, nat_tot;
int nzone, nzone_send, zone, zonei, cg0, cg1;
gmx_domdec_comm_t* comm;
gmx_domdec_zones_t* zones;
gmx_domdec_comm_dim_t* cd;
- cginfo_mb_t* cginfo_mb;
gmx_bool bBondComm, bDist2B, bDistMB, bDistBonded;
dd_corners_t corners;
rvec * normal, *v_d, *v_0 = nullptr, *v_1 = nullptr;
v_1 = ddbox->v[dim1];
}
- zone_cg_range = zones->cg_range;
- cginfo_mb = fr->cginfo_mb;
+ zone_cg_range = zones->cg_range;
+ gmx::ArrayRef<cginfo_mb_t> cginfo_mb = fr->cginfo_mb;
zone_cg_range[0] = 0;
zone_cg_range[1] = dd->ncg_home;
ddSendrecv<int>(dd, dim_ind, dddirBackward, work.atomGroupBuffer, integerBufferRef);
/* Make space for cg_cm */
- dd_check_alloc_ncg(fr, state, f, pos_cg + ind->nrecv[nzone]);
+ dd_resize_atominfo_and_state(fr, state, pos_cg + ind->nrecv[nzone]);
/* Communicate the coordinates */
gmx::ArrayRef<gmx::RVec> rvecBufferRef;
set_ddbox(*dd, true, DDMASTER(dd) ? state_global->box : nullptr, true, xGlobal, &ddbox);
- distributeState(mdlog, dd, top_global, state_global, ddbox, state_local, f);
+ distributeState(mdlog, dd, top_global, state_global, ddbox, state_local);
/* Ensure that we have space for the new distribution */
- dd_check_alloc_ncg(fr, state_local, f, dd->ncg_home);
+ dd_resize_atominfo_and_state(fr, state_local, dd->ncg_home);
inc_nrnb(nrnb, eNR_CGCM, comm->atomRanges.numHomeAtoms());
wallcycle_sub_start(wcycle, ewcsDD_REDIST);
ncgindex_set = dd->ncg_home;
- dd_redistribute_cg(fplog, step, dd, ddbox.tric_dir, state_local, f, fr, nrnb, &ncg_moved);
+ dd_redistribute_cg(fplog, step, dd, ddbox.tric_dir, state_local, fr, nrnb, &ncg_moved);
GMX_RELEASE_ASSERT(bSortCG, "Sorting is required after redistribution");
dd_sort_state(dd, fr, state_local);
/* After sorting and compacting we set the correct size */
- dd_resize_state(state_local, f, comm->atomRanges.numHomeAtoms());
+ state_change_natoms(state_local, comm->atomRanges.numHomeAtoms());
/* Rebuild all the indices */
dd->ga2la->clear();
make_dd_indices(dd, ncgindex_set);
/* Setup up the communication and communicate the coordinates */
- setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local, f);
+ setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local);
/* Set the indices for the halo atoms */
make_dd_indices(dd, dd->ncg_home);
*/
state_local->natoms = comm->atomRanges.numAtomsTotal();
- dd_resize_state(state_local, f, state_local->natoms);
+ state_change_natoms(state_local, state_local->natoms);
if (fr->haveDirectVirialContributions)
{
comm->atomRanges.end(DDAtomRanges::Type::Constraints), nat_f_novirsum);
/* Update atom data for mdatoms and several algorithms */
- mdAlgorithmsSetupAtomData(cr, ir, top_global, top_local, fr, nullptr, mdAtoms, constr, vsite, nullptr);
+ mdAlgorithmsSetupAtomData(cr, ir, top_global, top_local, fr, f, mdAtoms, constr, vsite, nullptr);
auto mdatoms = mdAtoms->mdatoms();
if (!thisRankHasDuty(cr, DUTY_PME))
}
/*! \brief Check whether bonded interactions are missing, if appropriate */
-void checkNumberOfBondedInteractions(const gmx::MDLogger& mdlog,
- t_commrec* cr,
- int totalNumberOfBondedInteractions,
- const gmx_mtop_t* top_global,
- const gmx_localtop_t* top_local,
- const rvec* x,
- const matrix box,
- bool* shouldCheckNumberOfBondedInteractions)
+void checkNumberOfBondedInteractions(const gmx::MDLogger& mdlog,
+ t_commrec* cr,
+ int totalNumberOfBondedInteractions,
+ const gmx_mtop_t* top_global,
+ const gmx_localtop_t* top_local,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const matrix box,
+ bool* shouldCheckNumberOfBondedInteractions)
{
if (*shouldCheckNumberOfBondedInteractions)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] box Box matrix for the error message
* \param[in,out] shouldCheckNumberOfBondedInteractions Whether we should do the check. Always set to false.
*/
-void checkNumberOfBondedInteractions(const gmx::MDLogger& mdlog,
- t_commrec* cr,
- int totalNumberOfBondedInteractions,
- const gmx_mtop_t* top_global,
- const gmx_localtop_t* top_local,
- const rvec* x,
- const matrix box,
- bool* shouldCheckNumberOfBondedInteractions);
+void checkNumberOfBondedInteractions(const gmx::MDLogger& mdlog,
+ t_commrec* cr,
+ int totalNumberOfBondedInteractions,
+ const gmx_mtop_t* top_global,
+ const gmx_localtop_t* top_local,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const matrix box,
+ bool* shouldCheckNumberOfBondedInteractions);
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2005,2006,2007,2008,2009 by the GROMACS development team.
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
flag |= DD_FLAG_BW(d);
if (firstMoveDimValue == -1)
{
- if (dd.nc[dim] > 2)
+ if (dd.numCells[dim] > 2)
{
firstMoveDimValue = d * 2 + 1;
}
/* Do pbc and check DD cell boundary crossings */
for (int d = DIM - 1; d >= 0; d--)
{
- if (dd->nc[d] > 1)
+ if (dd->numCells[d] > 1)
{
bool bScrew = (dd->unitCellInfo.haveScrewPBC && d == XX);
/* Determine the location of this cg in lattice coordinates */
cm_new, cm_new, pos_d);
}
dev[d] = 1;
- if (dd->ci[d] == dd->nc[d] - 1)
+ if (dd->ci[d] == dd->numCells[d] - 1)
{
rvec_dec(cm_new, state->box[d]);
if (bScrew)
/* Do pbc and check DD cell boundary crossings */
for (int d = DIM - 1; d >= 0; d--)
{
- if (dd->nc[d] > 1)
+ if (dd->numCells[d] > 1)
{
/* Determine the location of this COG in lattice coordinates */
real pos_d = cog[d];
cogOld, cog, pos_d);
}
dev[d] = 1;
- if (dd->ci[d] == dd->nc[d] - 1)
+ if (dd->ci[d] == dd->numCells[d] - 1)
{
rvec_dec(cog, state->box[d]);
}
}
}
-void dd_redistribute_cg(FILE* fplog,
- int64_t step,
- gmx_domdec_t* dd,
- ivec tric_dir,
- t_state* state,
- PaddedHostVector<gmx::RVec>* f,
- t_forcerec* fr,
- t_nrnb* nrnb,
- int* ncg_moved)
+void dd_redistribute_cg(FILE* fplog,
+ int64_t step,
+ gmx_domdec_t* dd,
+ ivec tric_dir,
+ t_state* state,
+ t_forcerec* fr,
+ t_nrnb* nrnb,
+ int* ncg_moved)
{
gmx_domdec_comm_t* comm = dd->comm;
{
cell_x0[d] = comm->cell_x0[d];
}
- if (d >= npbcdim && dd->ci[d] == dd->nc[d] - 1)
+ if (d >= npbcdim && dd->ci[d] == dd->numCells[d] - 1)
{
cell_x1[d] = GMX_FLOAT_MAX;
}
/* We reuse the intBuffer without reacquiring since we are in the same scope */
DDBufferAccess<int>& flagBuffer = moveBuffer;
- const cginfo_mb_t* cginfo_mb = fr->cginfo_mb;
+ gmx::ArrayRef<const cginfo_mb_t> cginfo_mb = fr->cginfo_mb;
/* Temporarily store atoms passed to our rank at the end of the range */
int home_pos_cg = dd->ncg_home;
const int dim = dd->dim[d];
int ncg_recv = 0;
int nvr = 0;
- for (int dir = 0; dir < (dd->nc[dim] == 2 ? 1 : 2); dir++)
+ for (int dir = 0; dir < (dd->numCells[dim] == 2 ? 1 : 2); dir++)
{
const int cdd = d * 2 + dir;
/* Communicate the cg and atom counts */
nvr += i;
}
- dd_check_alloc_ncg(fr, state, f, home_pos_cg + ncg_recv);
+ dd_resize_atominfo_and_state(fr, state, home_pos_cg + ncg_recv);
/* Process the received charge or update groups */
int buf_pos = 0;
int flag = flagBuffer.buffer[cg * DD_CGIBS + 1];
const gmx::RVec& cog = rvecBuffer.buffer[buf_pos];
- if (dim >= npbcdim && dd->nc[dim] > 2)
+ if (dim >= npbcdim && dd->numCells[dim] > 2)
{
/* No pbc in this dim and more than one domain boundary.
* We do a separate check if a charge group didn't move too far.
* so we do not need to handle boundary crossings.
* This also means we do not have to handle PBC here.
*/
- if (!((dd->ci[dim2] == dd->nc[dim2] - 1 && (flag & DD_FLAG_FW(d2)))
+ if (!((dd->ci[dim2] == dd->numCells[dim2] - 1 && (flag & DD_FLAG_FW(d2)))
|| (dd->ci[dim2] == 0 && (flag & DD_FLAG_BW(d2)))))
{
/* Clear the two flags for this dimension */
* to an adjacent cell because of the
* staggering.
*/
- if (pos_d >= cell_x1[dim2] && dd->ci[dim2] != dd->nc[dim2] - 1)
+ if (pos_d >= cell_x1[dim2] && dd->ci[dim2] != dd->numCells[dim2] - 1)
{
flag |= DD_FLAG_FW(d2);
}
}
else if (flag & DD_FLAG_BW(d2))
{
- if (dd->nc[dd->dim[d2]] > 2)
+ if (dd->numCells[dd->dim[d2]] > 2)
{
mc = d2 * 2 + 1;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdio>
-#include "gromacs/gpu_utils/hostallocator.h"
+#include "gromacs/math/vectypes.h"
#include "gromacs/utility/basedefinitions.h"
struct gmx_domdec_t;
class t_state;
/*! \brief Redistribute the atoms to their, new, local domains */
-void dd_redistribute_cg(FILE* fplog,
- int64_t step,
- gmx_domdec_t* dd,
- ivec tric_dir,
- t_state* state,
- gmx::PaddedHostVector<gmx::RVec>* f,
- t_forcerec* fr,
- t_nrnb* nrnb,
- int* ncg_moved);
+void dd_redistribute_cg(FILE* fplog,
+ int64_t step,
+ gmx_domdec_t* dd,
+ ivec tric_dir,
+ t_state* state,
+ t_forcerec* fr,
+ t_nrnb* nrnb,
+ int* ncg_moved);
#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2018, by the GROMACS development team, led by
+# Copyright (c) 2014,2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(DomDecTests domdec-test
- hashedmap.cpp
- localatomsetmanager.cpp)
+ CPP_SOURCE_FILES
+ hashedmap.cpp
+ localatomsetmanager.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_fatal(FARGS, "pbc=screw with non-zero box_zy is not supported");
}
}
-/*! \brief Resize the state and f*/
-void dd_resize_state(t_state* state, PaddedHostVector<gmx::RVec>* f, int natoms)
-{
- if (debug)
- {
- fprintf(debug, "Resizing state: currently %d, required %d\n", state->natoms, natoms);
- }
-
- state_change_natoms(state, natoms);
-
- if (f != nullptr)
- {
- /* We need to allocate one element extra, since we might use
- * (unaligned) 4-wide SIMD loads to access rvec entries.
- */
- f->resizeWithPadding(natoms);
- }
-}
-/*! \brief Ensure fr, state and f, if != nullptr, can hold numChargeGroups
- * atoms for the Verlet scheme and charge groups for the group scheme.
- *
- * todo refactor this now that group scheme is removed
- */
-void dd_check_alloc_ncg(t_forcerec* fr, t_state* state, PaddedHostVector<gmx::RVec>* f, int numChargeGroups)
+void dd_resize_atominfo_and_state(t_forcerec* fr, t_state* state, const int numAtoms)
{
- fr->cginfo.resize(numChargeGroups);
+ fr->cginfo.resize(numAtoms);
/* We use x during the setup of the atom communication */
- dd_resize_state(state, f, numChargeGroups);
+ state_change_natoms(state, numAtoms);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_DOMDEC_DOMDEC_UTILITY_H
#define GMX_DOMDEC_DOMDEC_UTILITY_H
-#include "gromacs/gpu_utils/hostallocator.h"
+#include "gromacs/math/vectypes.h"
#include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/utility/arrayref.h"
#include "domdec_internal.h"
void check_screw_box(const matrix box);
/*! \brief Return the charge group information flags for charge group cg */
-static inline int ddcginfo(const cginfo_mb_t* cginfo_mb, int cg)
+static inline int ddcginfo(gmx::ArrayRef<const cginfo_mb_t> cginfo_mb, int cg)
{
- while (cg >= cginfo_mb->cg_end)
+ size_t index = 0;
+ while (cg >= cginfo_mb[index].cg_end)
{
- cginfo_mb++;
+ index++;
}
+ const cginfo_mb_t& cgimb = cginfo_mb[index];
- return cginfo_mb->cginfo[(cg - cginfo_mb->cg_start) % cginfo_mb->cg_mod];
+ return cgimb.cginfo[(cg - cgimb.cg_start) % cgimb.cg_mod];
};
/*! \brief Returns the number of MD steps for which load has been recorded */
return (comm->ddSettings.eFlop ? comm->flop_n : comm->cycl_n[ddCyclF]);
}
-/*! \brief Resize the state and f, if !=nullptr, to natoms
+/*! \brief Ensure fr and state can hold numAtoms atoms
*
- * \param[in] state Current state
- * \param[in] f The vector of forces to be resized
- * \param[out] natoms New number of atoms to accommodate
+ * \param[in] fr Force record
+ * \param[in] state Current state
+ * \param[out] numAtoms Number of atoms
*/
-void dd_resize_state(t_state* state, gmx::PaddedHostVector<gmx::RVec>* f, int natoms);
-
-/*! \brief Enrsure fr, state and f, if != nullptr, can hold numChargeGroups atoms for the Verlet scheme and charge groups for the group scheme
- *
- * \param[in] fr Force record
- * \param[in] state Current state
- * \param[in] f The force buffer
- * \param[out] numChargeGroups Number of charged groups
- */
-void dd_check_alloc_ncg(t_forcerec* fr, t_state* state, gmx::PaddedHostVector<gmx::RVec>* f, int numChargeGroups);
+void dd_resize_atominfo_and_state(t_forcerec* fr, t_state* state, int numAtoms);
/*! \brief Returns a domain-to-domain cutoff distance given an atom-to-atom cutoff */
static inline real atomToAtomIntoDomainToDomainCutoff(const DDSystemInfo& systemInfo, real cutoff)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(EnergyAnalysisUnitTests energyanalysis-test
+ CPP_SOURCE_FILES
legacyenergy.cpp
-)
+ )
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* Broadcasts the structure data */
static void bc_ed_positions(const t_commrec* cr, struct gmx_edx* s, EssentialDynamicsStructure stype)
{
- snew_bc(cr, s->anrs, s->nr); /* Index numbers */
- snew_bc(cr, s->x, s->nr); /* Positions */
- nblock_bc(cr, s->nr, s->anrs);
- nblock_bc(cr, s->nr, s->x);
+ snew_bc(MASTER(cr), s->anrs, s->nr); /* Index numbers */
+ snew_bc(MASTER(cr), s->x, s->nr); /* Positions */
+ nblock_bc(cr->mpi_comm_mygroup, s->nr, s->anrs);
+ nblock_bc(cr->mpi_comm_mygroup, s->nr, s->x);
/* For the average & reference structures we need an array for the collective indices,
* and we need to broadcast the masses as well */
snew(s->c_ind, s->nr); /* Collective indices */
/* Local atom indices get assigned in dd_make_local_group_indices.
* There, also memory is allocated */
- s->nalloc_loc = 0; /* allocation size of s->anrs_loc */
- snew_bc(cr, s->x_old, s->nr); /* To be able to always make the ED molecule whole, ... */
- nblock_bc(cr, s->nr, s->x_old); /* ... keep track of shift changes with the help of old coords */
+ s->nalloc_loc = 0; /* allocation size of s->anrs_loc */
+ snew_bc(MASTER(cr), s->x_old, s->nr); /* To be able to always make the ED molecule whole, ... */
+ nblock_bc(cr->mpi_comm_mygroup, s->nr,
+ s->x_old); /* ... keep track of shift changes with the help of old coords */
}
/* broadcast masses for the reference structure (for mass-weighted fitting) */
if (stype == EssentialDynamicsStructure::Reference)
{
- snew_bc(cr, s->m, s->nr);
- nblock_bc(cr, s->nr, s->m);
+ snew_bc(MASTER(cr), s->m, s->nr);
+ nblock_bc(cr->mpi_comm_mygroup, s->nr, s->m);
}
/* For the average structure we might need the masses for mass-weighting */
if (stype == EssentialDynamicsStructure::Average)
{
- snew_bc(cr, s->sqrtm, s->nr);
- nblock_bc(cr, s->nr, s->sqrtm);
- snew_bc(cr, s->m, s->nr);
- nblock_bc(cr, s->nr, s->m);
+ snew_bc(MASTER(cr), s->sqrtm, s->nr);
+ nblock_bc(cr->mpi_comm_mygroup, s->nr, s->sqrtm);
+ snew_bc(MASTER(cr), s->m, s->nr);
+ nblock_bc(cr->mpi_comm_mygroup, s->nr, s->m);
}
}
{
int i;
- snew_bc(cr, ev->ieig, ev->neig); /* index numbers of eigenvector */
- snew_bc(cr, ev->stpsz, ev->neig); /* stepsizes per eigenvector */
- snew_bc(cr, ev->xproj, ev->neig); /* instantaneous x projection */
- snew_bc(cr, ev->fproj, ev->neig); /* instantaneous f projection */
- snew_bc(cr, ev->refproj, ev->neig); /* starting or target projection */
+ snew_bc(MASTER(cr), ev->ieig, ev->neig); /* index numbers of eigenvector */
+ snew_bc(MASTER(cr), ev->stpsz, ev->neig); /* stepsizes per eigenvector */
+ snew_bc(MASTER(cr), ev->xproj, ev->neig); /* instantaneous x projection */
+ snew_bc(MASTER(cr), ev->fproj, ev->neig); /* instantaneous f projection */
+ snew_bc(MASTER(cr), ev->refproj, ev->neig); /* starting or target projection */
- nblock_bc(cr, ev->neig, ev->ieig);
- nblock_bc(cr, ev->neig, ev->stpsz);
- nblock_bc(cr, ev->neig, ev->xproj);
- nblock_bc(cr, ev->neig, ev->fproj);
- nblock_bc(cr, ev->neig, ev->refproj);
+ nblock_bc(cr->mpi_comm_mygroup, ev->neig, ev->ieig);
+ nblock_bc(cr->mpi_comm_mygroup, ev->neig, ev->stpsz);
+ nblock_bc(cr->mpi_comm_mygroup, ev->neig, ev->xproj);
+ nblock_bc(cr->mpi_comm_mygroup, ev->neig, ev->fproj);
+ nblock_bc(cr->mpi_comm_mygroup, ev->neig, ev->refproj);
- snew_bc(cr, ev->vec, ev->neig); /* Eigenvector components */
+ snew_bc(MASTER(cr), ev->vec, ev->neig); /* Eigenvector components */
for (i = 0; i < ev->neig; i++)
{
- snew_bc(cr, ev->vec[i], length);
- nblock_bc(cr, length, ev->vec[i]);
+ snew_bc(MASTER(cr), ev->vec[i], length);
+ nblock_bc(cr->mpi_comm_mygroup, length, ev->vec[i]);
}
}
static void broadcast_ed_data(const t_commrec* cr, gmx_edsam* ed)
{
/* Master lets the other nodes know if its ED only or also flooding */
- gmx_bcast(sizeof(ed->eEDtype), &(ed->eEDtype), cr);
+ gmx_bcast(sizeof(ed->eEDtype), &(ed->eEDtype), cr->mpi_comm_mygroup);
int numedis = ed->edpar.size();
/* First let everybody know how many ED data sets to expect */
- gmx_bcast(sizeof(numedis), &numedis, cr);
- nblock_abc(cr, numedis, &(ed->edpar));
+ gmx_bcast(sizeof(numedis), &numedis, cr->mpi_comm_mygroup);
+ nblock_abc(MASTER(cr), cr->mpi_comm_mygroup, numedis, &(ed->edpar));
/* Now transfer the ED data set(s) */
for (auto& edi : ed->edpar)
{
/* Broadcast a single ED data set */
- block_bc(cr, edi);
+ block_bc(cr->mpi_comm_mygroup, edi);
/* Broadcast positions */
bc_ed_positions(cr, &(edi.sref),
/* For harmonic restraints the reference projections can change with time */
if (edi.flood.bHarmonic)
{
- snew_bc(cr, edi.flood.initialReferenceProjection, edi.flood.vecs.neig);
- snew_bc(cr, edi.flood.referenceProjectionSlope, edi.flood.vecs.neig);
- nblock_bc(cr, edi.flood.vecs.neig, edi.flood.initialReferenceProjection);
- nblock_bc(cr, edi.flood.vecs.neig, edi.flood.referenceProjectionSlope);
+ snew_bc(MASTER(cr), edi.flood.initialReferenceProjection, edi.flood.vecs.neig);
+ snew_bc(MASTER(cr), edi.flood.referenceProjectionSlope, edi.flood.vecs.neig);
+ nblock_bc(cr->mpi_comm_mygroup, edi.flood.vecs.neig, edi.flood.initialReferenceProjection);
+ nblock_bc(cr->mpi_comm_mygroup, edi.flood.vecs.neig, edi.flood.referenceProjectionSlope);
}
}
}
/* Remove PBC, make molecule(s) subject to ED whole. */
snew(x_pbc, mtop->natoms);
copy_rvecn(globalState->x.rvec_array(), x_pbc, 0, mtop->natoms);
- do_pbc_first_mtop(nullptr, ir->ePBC, globalState->box, mtop, x_pbc);
+ do_pbc_first_mtop(nullptr, ir->pbcType, globalState->box, mtop, x_pbc);
}
/* Reset pointer to first ED data set which contains the actual ED data */
auto edi = ed->edpar.begin();
for (auto edi = ed->edpar.begin(); edi != ed->edpar.end(); ++edi)
{
/* Allocate space for ED buffer variables */
- snew_bc(cr, edi->buf, 1); /* MASTER has already allocated edi->buf in init_edi() */
+ snew_bc(MASTER(cr), edi->buf, 1); /* MASTER has already allocated edi->buf in init_edi() */
snew(edi->buf->do_edsam, 1);
/* Space for collective ED buffer variables */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
if (BUILD_TESTING)
add_subdirectory(tests)
endif()
+
+
+set(PME_OCL_KERNEL_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/pme_gpu_utils.clh"
+ "${CMAKE_CURRENT_SOURCE_DIR}/pme_solve.clh"
+ "${CMAKE_CURRENT_SOURCE_DIR}/pme_gather.clh"
+ "${CMAKE_CURRENT_SOURCE_DIR}/pme_spread.clh")
+
+if(CLANG_TIDY_EXE)
+ set(OCL_COMPILER "${CLANG_TIDY_EXE}")
+ set(CLANG_TIDY_ARGS "-quiet;-checks=*,-readability-implicit-bool-conversion,-llvm-header-guard,-hicpp-signed-bitwise,-clang-analyzer-deadcode.DeadStores,-google-readability-todo,-clang-diagnostic-padded,-fcomment-block-commands=internal;--;${CMAKE_C_COMPILER}")
+else()
+ set(OCL_COMPILER "${CMAKE_C_COMPILER}")
+endif()
+
+# TODO: test all warp sizes on all vendor targets?
+foreach(VENDOR AMD NVIDIA INTEL)
+ foreach(WARPSIZE 16 32 64)
+ math(EXPR SPREAD_WG_SIZE "8*${WARPSIZE}")
+ math(EXPR SOLVE_WG_SIZE "8*${WARPSIZE}")
+ math(EXPR GATHER_WG_SIZE "4*${WARPSIZE}")
+ set(OBJ_FILE pme_ocl_kernel_warpSize${WARPSIZE}_${VENDOR}.o)
+ add_custom_command(OUTPUT ${OBJ_FILE} COMMAND ${OCL_COMPILER}
+ ${CMAKE_CURRENT_SOURCE_DIR}/pme_program.cl ${CLANG_TIDY_ARGS}
+ -Xclang -finclude-default-header -D_${VENDOR}_SOURCE_
+ -Dwarp_size=${WARPSIZE}
+ -Dorder=4
+ -DthreadsPerAtom=16
+ -Dc_pmeMaxUnitcellShift=2
+ -Dc_skipNeutralAtoms=false
+ -Dc_virialAndEnergyCount=7
+ -Dc_spreadWorkGroupSize=${SPREAD_WG_SIZE}
+ -Dc_solveMaxWorkGroupSize=${SOLVE_WG_SIZE}
+ -Dc_gatherWorkGroupSize=${GATHER_WG_SIZE}
+ -DDIM=3 -DXX=0 -DYY=1 -DZZ=2
+ -DwrapX=true -DwrapY=true
+ -c -I ${CMAKE_SOURCE_DIR}/src -std=cl1.2
+ -Weverything -Wno-conversion -Wno-missing-variable-declarations -Wno-used-but-marked-unused
+ -Wno-cast-align -Wno-incompatible-pointer-types
+ # to avoid "warning: unknown command tag name" for \internal
+ -Wno-documentation-unknown-command
+ # to avoid pme_gpu_types.h:100:52: warning: padding struct 'struct PmeGpuConstParams' with 4 bytes to align 'd_virialAndEnergy'
+ -Wno-padded
+ -o${OBJ_FILE}
+ )
+ list(APPEND PME_OCL_KERNELS ${OBJ_FILE})
+ endforeach()
+endforeach()
+
+add_custom_target(ocl_pme_kernels DEPENDS ${PME_OCL_KERNELS} )
+gmx_set_custom_target_output(ocl_pme_kernels ${PME_OCL_KERNELS})
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
-#include "pme_internal.h"
-
static void make_dft_mod(real* mod, const double* data, int splineOrder, int ndata)
{
for (int i = 0; i < ndata; i++)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_EWALD_CALCULATE_SPLINE_MODULI_H
#define GMX_EWALD_CALCULATE_SPLINE_MODULI_H
-#include "pme_internal.h"
+#include "spline_vectors.h"
/* Calulate plain SPME B-spline interpolation */
void make_bspline_moduli(splinevec bsp_mod, int nx, int ny, int nz, int order);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
-#include "pme_internal.h"
-
/* There's nothing special to do here if just masses are perturbed,
* but if either charge or type is perturbed then the implementation
* requires that B states are defined for both charge and type, and
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/timing/cyclecounter.h"
#include "gromacs/timing/wallcycle.h"
return (enumerator + denominator - 1) / denominator;
}
-gmx_pme_t* gmx_pme_init(const t_commrec* cr,
- const NumPmeDomains& numPmeDomains,
- const t_inputrec* ir,
- gmx_bool bFreeEnergy_q,
- gmx_bool bFreeEnergy_lj,
- gmx_bool bReproducible,
- real ewaldcoeff_q,
- real ewaldcoeff_lj,
- int nthread,
- PmeRunMode runMode,
- PmeGpu* pmeGpu,
- const gmx_device_info_t* gpuInfo,
- PmeGpuProgramHandle pmeGpuProgram,
+gmx_pme_t* gmx_pme_init(const t_commrec* cr,
+ const NumPmeDomains& numPmeDomains,
+ const t_inputrec* ir,
+ gmx_bool bFreeEnergy_q,
+ gmx_bool bFreeEnergy_lj,
+ gmx_bool bReproducible,
+ real ewaldcoeff_q,
+ real ewaldcoeff_lj,
+ int nthread,
+ PmeRunMode runMode,
+ PmeGpu* pmeGpu,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
const gmx::MDLogger& /*mdlog*/)
{
int use_threads, sum_use_threads, i;
}
pme->bUseThreads = (sum_use_threads > 0);
- if (ir->ePBC == epbcSCREW)
+ if (ir->pbcType == PbcType::Screw)
{
gmx_fatal(FARGS, "pme does not (yet) work with pbc = screw");
}
pme->atc.emplace_back(pme->mpi_comm_d[1], pme->nthread, pme->pme_order, secondDimIndex, doSpread);
}
- if (pme_gpu_active(pme.get()))
+ // Initial check of validity of the input for running on the GPU
+ if (pme->runMode != PmeRunMode::CPU)
{
- if (!pme->gpu)
+ std::string errorString;
+ bool canRunOnGpu = pme_gpu_check_restrictions(pme.get(), &errorString);
+ if (!canRunOnGpu)
{
- // Initial check of validity of the data
- std::string errorString;
- bool canRunOnGpu = pme_gpu_check_restrictions(pme.get(), &errorString);
- if (!canRunOnGpu)
- {
- GMX_THROW(gmx::NotImplementedError(errorString));
- }
+ GMX_THROW(gmx::NotImplementedError(errorString));
}
-
- pme_gpu_reinit(pme.get(), gpuInfo, pmeGpuProgram);
+ pme_gpu_reinit(pme.get(), deviceContext, deviceStream, pmeGpuProgram);
+ }
+ else
+ {
+ GMX_ASSERT(pme->gpu == nullptr, "Should not have PME GPU object when PME is on a CPU.");
}
+
pme_init_all_work(&pme->solve_work, pme->nthread, pme->nkx);
// no exception was thrown during the init, so we hand over the PME structure handle
// TODO: This would be better as just copying a sub-structure that contains
// all the PME parameters and nothing else.
t_inputrec irc;
- irc.ePBC = ir->ePBC;
+ irc.pbcType = ir->pbcType;
irc.coulombtype = ir->coulombtype;
irc.vdwtype = ir->vdwtype;
irc.efep = ir->efep;
NumPmeDomains numPmeDomains = { pme_src->nnodes_major, pme_src->nnodes_minor };
*pmedata = gmx_pme_init(cr, numPmeDomains, &irc, pme_src->bFEP_q, pme_src->bFEP_lj, FALSE,
ewaldcoeff_q, ewaldcoeff_lj, pme_src->nthread, pme_src->runMode,
- pme_src->gpu, nullptr, nullptr, dummyLogger);
+ pme_src->gpu, nullptr, nullptr, nullptr, dummyLogger);
/* When running PME on the CPU not using domain decomposition,
* the atom data is allocated once only in gmx_pme_(re)init().
*/
real lambda_lj,
real* dvdlambda_q,
real* dvdlambda_lj,
- int flags)
+ const gmx::StepWorkload& stepWork)
{
GMX_ASSERT(pme->runMode == PmeRunMode::CPU,
"gmx_pme_do should not be called on the GPU PME run.");
gmx_bool bFirst, bDoSplines;
int fep_state;
int fep_states_lj = pme->bFEP_lj ? 2 : 1;
- const gmx_bool bCalcEnerVir = (flags & GMX_PME_CALC_ENER_VIR) != 0;
- const gmx_bool bBackFFT = (flags & (GMX_PME_CALC_F | GMX_PME_CALC_POT)) != 0;
- const gmx_bool bCalcF = (flags & GMX_PME_CALC_F) != 0;
+ // There's no support for computing energy without virial, or vice versa
+ const bool computeEnergyAndVirial = (stepWork.computeEnergy || stepWork.computeVirial);
/* We could be passing lambda!=0 while no q or LJ is actually perturbed */
if (!pme->bFEP_q)
fprintf(debug, "Rank= %6d, pme local particles=%6d\n", cr->nodeid, atc.numAtoms());
}
- if (flags & GMX_PME_SPREAD)
+ wallcycle_start(wcycle, ewcPME_SPREAD);
+
+ /* Spread the coefficients on a grid */
+ spread_on_grid(pme, &atc, pmegrid, bFirst, TRUE, fftgrid, bDoSplines, grid_index);
+
+ if (bFirst)
{
- wallcycle_start(wcycle, ewcPME_SPREAD);
+ inc_nrnb(nrnb, eNR_WEIGHTS, DIM * atc.numAtoms());
+ }
+ inc_nrnb(nrnb, eNR_SPREADBSP, pme->pme_order * pme->pme_order * pme->pme_order * atc.numAtoms());
- /* Spread the coefficients on a grid */
- spread_on_grid(pme, &atc, pmegrid, bFirst, TRUE, fftgrid, bDoSplines, grid_index);
+ if (!pme->bUseThreads)
+ {
+ wrap_periodic_pmegrid(pme, grid);
- if (bFirst)
+ /* sum contributions to local grid from other nodes */
+ if (pme->nnodes > 1)
{
- inc_nrnb(nrnb, eNR_WEIGHTS, DIM * atc.numAtoms());
+ gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_FORWARD);
}
- inc_nrnb(nrnb, eNR_SPREADBSP,
- pme->pme_order * pme->pme_order * pme->pme_order * atc.numAtoms());
-
- if (!pme->bUseThreads)
- {
- wrap_periodic_pmegrid(pme, grid);
-
- /* sum contributions to local grid from other nodes */
- if (pme->nnodes > 1)
- {
- gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_FORWARD);
- }
- copy_pmegrid_to_fftgrid(pme, grid, fftgrid, grid_index);
- }
+ copy_pmegrid_to_fftgrid(pme, grid, fftgrid, grid_index);
+ }
- wallcycle_stop(wcycle, ewcPME_SPREAD);
+ wallcycle_stop(wcycle, ewcPME_SPREAD);
- /* TODO If the OpenMP and single-threaded implementations
- converge, then spread_on_grid() and
- copy_pmegrid_to_fftgrid() will perhaps live in the same
- source file.
- */
- }
+ /* TODO If the OpenMP and single-threaded implementations
+ converge, then spread_on_grid() and
+ copy_pmegrid_to_fftgrid() will perhaps live in the same
+ source file.
+ */
/* Here we start a large thread parallel region */
#pragma omp parallel num_threads(pme->nthread) private(thread)
try
{
thread = gmx_omp_get_thread_num();
- if (flags & GMX_PME_SOLVE)
- {
- int loop_count;
+ int loop_count;
- /* do 3d-fft */
- if (thread == 0)
- {
- wallcycle_start(wcycle, ewcPME_FFT);
- }
- gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_REAL_TO_COMPLEX, thread, wcycle);
- if (thread == 0)
- {
- wallcycle_stop(wcycle, ewcPME_FFT);
- }
-
- /* solve in k-space for our local cells */
- if (thread == 0)
- {
- wallcycle_start(wcycle, (grid_index < DO_Q ? ewcPME_SOLVE : ewcLJPME));
- }
- if (grid_index < DO_Q)
- {
- loop_count = solve_pme_yzx(
- pme, cfftgrid, scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
- bCalcEnerVir, pme->nthread, thread);
- }
- else
- {
- loop_count = solve_pme_lj_yzx(
- pme, &cfftgrid, FALSE,
- scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
- bCalcEnerVir, pme->nthread, thread);
- }
+ /* do 3d-fft */
+ if (thread == 0)
+ {
+ wallcycle_start(wcycle, ewcPME_FFT);
+ }
+ gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_REAL_TO_COMPLEX, thread, wcycle);
+ if (thread == 0)
+ {
+ wallcycle_stop(wcycle, ewcPME_FFT);
+ }
- if (thread == 0)
- {
- wallcycle_stop(wcycle, (grid_index < DO_Q ? ewcPME_SOLVE : ewcLJPME));
- inc_nrnb(nrnb, eNR_SOLVEPME, loop_count);
- }
+ /* solve in k-space for our local cells */
+ if (thread == 0)
+ {
+ wallcycle_start(wcycle, (grid_index < DO_Q ? ewcPME_SOLVE : ewcLJPME));
+ }
+ if (grid_index < DO_Q)
+ {
+ loop_count = solve_pme_yzx(
+ pme, cfftgrid, scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
+ computeEnergyAndVirial, pme->nthread, thread);
+ }
+ else
+ {
+ loop_count =
+ solve_pme_lj_yzx(pme, &cfftgrid, FALSE,
+ scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
+ computeEnergyAndVirial, pme->nthread, thread);
}
- if (bBackFFT)
+ if (thread == 0)
{
- /* do 3d-invfft */
- if (thread == 0)
- {
- wallcycle_start(wcycle, ewcPME_FFT);
- }
- gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_COMPLEX_TO_REAL, thread, wcycle);
- if (thread == 0)
- {
- wallcycle_stop(wcycle, ewcPME_FFT);
+ wallcycle_stop(wcycle, (grid_index < DO_Q ? ewcPME_SOLVE : ewcLJPME));
+ inc_nrnb(nrnb, eNR_SOLVEPME, loop_count);
+ }
+ /* do 3d-invfft */
+ if (thread == 0)
+ {
+ wallcycle_start(wcycle, ewcPME_FFT);
+ }
+ gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_COMPLEX_TO_REAL, thread, wcycle);
+ if (thread == 0)
+ {
+ wallcycle_stop(wcycle, ewcPME_FFT);
- if (pme->nodeid == 0)
- {
- real ntot = pme->nkx * pme->nky * pme->nkz;
- npme = static_cast<int>(ntot * std::log(ntot) / std::log(2.0));
- inc_nrnb(nrnb, eNR_FFT, 2 * npme);
- }
- /* Note: this wallcycle region is closed below
- outside an OpenMP region, so take care if
- refactoring code here. */
- wallcycle_start(wcycle, ewcPME_GATHER);
+ if (pme->nodeid == 0)
+ {
+ real ntot = pme->nkx * pme->nky * pme->nkz;
+ npme = static_cast<int>(ntot * std::log(ntot) / std::log(2.0));
+ inc_nrnb(nrnb, eNR_FFT, 2 * npme);
}
- copy_fftgrid_to_pmegrid(pme, fftgrid, grid, grid_index, pme->nthread, thread);
+ /* Note: this wallcycle region is closed below
+ outside an OpenMP region, so take care if
+ refactoring code here. */
+ wallcycle_start(wcycle, ewcPME_GATHER);
}
+
+ copy_fftgrid_to_pmegrid(pme, fftgrid, grid, grid_index, pme->nthread, thread);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
* With MPI we have to synchronize here before gmx_sum_qgrid_dd.
*/
- if (bBackFFT)
+ /* distribute local grid to all nodes */
+ if (pme->nnodes > 1)
{
- /* distribute local grid to all nodes */
- if (pme->nnodes > 1)
- {
- gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_BACKWARD);
- }
-
- unwrap_periodic_pmegrid(pme, grid);
+ gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_BACKWARD);
}
- if (bCalcF)
+ unwrap_periodic_pmegrid(pme, grid);
+
+ if (stepWork.computeForces)
{
/* interpolate forces for our local atoms */
wallcycle_stop(wcycle, ewcPME_GATHER);
}
- if (bCalcEnerVir)
+ if (computeEnergyAndVirial)
{
/* This should only be called on the master thread
* and after the threads have synchronized.
calc_next_lb_coeffs(coefficientBuffer, local_sigma);
grid = pmegrid->grid.grid;
- if (flags & GMX_PME_SPREAD)
- {
- wallcycle_start(wcycle, ewcPME_SPREAD);
- /* Spread the c6 on a grid */
- spread_on_grid(pme, &atc, pmegrid, bFirst, TRUE, fftgrid, bDoSplines, grid_index);
+ wallcycle_start(wcycle, ewcPME_SPREAD);
+ /* Spread the c6 on a grid */
+ spread_on_grid(pme, &atc, pmegrid, bFirst, TRUE, fftgrid, bDoSplines, grid_index);
- if (bFirst)
- {
- inc_nrnb(nrnb, eNR_WEIGHTS, DIM * atc.numAtoms());
- }
+ if (bFirst)
+ {
+ inc_nrnb(nrnb, eNR_WEIGHTS, DIM * atc.numAtoms());
+ }
- inc_nrnb(nrnb, eNR_SPREADBSP,
- pme->pme_order * pme->pme_order * pme->pme_order * atc.numAtoms());
- if (pme->nthread == 1)
+ inc_nrnb(nrnb, eNR_SPREADBSP,
+ pme->pme_order * pme->pme_order * pme->pme_order * atc.numAtoms());
+ if (pme->nthread == 1)
+ {
+ wrap_periodic_pmegrid(pme, grid);
+ /* sum contributions to local grid from other nodes */
+ if (pme->nnodes > 1)
{
- wrap_periodic_pmegrid(pme, grid);
- /* sum contributions to local grid from other nodes */
- if (pme->nnodes > 1)
- {
- gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_FORWARD);
- }
- copy_pmegrid_to_fftgrid(pme, grid, fftgrid, grid_index);
+ gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_FORWARD);
}
- wallcycle_stop(wcycle, ewcPME_SPREAD);
+ copy_pmegrid_to_fftgrid(pme, grid, fftgrid, grid_index);
}
+ wallcycle_stop(wcycle, ewcPME_SPREAD);
+
/*Here we start a large thread parallel region*/
#pragma omp parallel num_threads(pme->nthread) private(thread)
{
try
{
thread = gmx_omp_get_thread_num();
- if (flags & GMX_PME_SOLVE)
+ /* do 3d-fft */
+ if (thread == 0)
{
- /* do 3d-fft */
- if (thread == 0)
- {
- wallcycle_start(wcycle, ewcPME_FFT);
- }
+ wallcycle_start(wcycle, ewcPME_FFT);
+ }
- gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_REAL_TO_COMPLEX, thread, wcycle);
- if (thread == 0)
- {
- wallcycle_stop(wcycle, ewcPME_FFT);
- }
+ gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_REAL_TO_COMPLEX, thread, wcycle);
+ if (thread == 0)
+ {
+ wallcycle_stop(wcycle, ewcPME_FFT);
}
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
bFirst = FALSE;
}
- if (flags & GMX_PME_SOLVE)
- {
- /* solve in k-space for our local cells */
+ /* solve in k-space for our local cells */
#pragma omp parallel num_threads(pme->nthread) private(thread)
+ {
+ try
{
- try
+ int loop_count;
+ thread = gmx_omp_get_thread_num();
+ if (thread == 0)
{
- int loop_count;
- thread = gmx_omp_get_thread_num();
- if (thread == 0)
- {
- wallcycle_start(wcycle, ewcLJPME);
- }
+ wallcycle_start(wcycle, ewcLJPME);
+ }
- loop_count = solve_pme_lj_yzx(
- pme, &pme->cfftgrid[2], TRUE,
- scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
- bCalcEnerVir, pme->nthread, thread);
- if (thread == 0)
- {
- wallcycle_stop(wcycle, ewcLJPME);
- inc_nrnb(nrnb, eNR_SOLVEPME, loop_count);
- }
+ loop_count =
+ solve_pme_lj_yzx(pme, &pme->cfftgrid[2], TRUE,
+ scaledBox[XX][XX] * scaledBox[YY][YY] * scaledBox[ZZ][ZZ],
+ computeEnergyAndVirial, pme->nthread, thread);
+ if (thread == 0)
+ {
+ wallcycle_stop(wcycle, ewcLJPME);
+ inc_nrnb(nrnb, eNR_SOLVEPME, loop_count);
}
- GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
- if (bCalcEnerVir)
+ if (computeEnergyAndVirial)
{
/* This should only be called on the master thread and
* after the threads have synchronized.
get_pme_ener_vir_lj(pme->solve_work, pme->nthread, &output[fep_state]);
}
- if (bBackFFT)
+ bFirst = !pme->doCoulomb;
+ calc_initial_lb_coeffs(coefficientBuffer, local_c6, local_sigma);
+ for (grid_index = 8; grid_index >= 2; --grid_index)
{
- bFirst = !pme->doCoulomb;
- calc_initial_lb_coeffs(coefficientBuffer, local_c6, local_sigma);
- for (grid_index = 8; grid_index >= 2; --grid_index)
- {
- /* Unpack structure */
- pmegrid = &pme->pmegrid[grid_index];
- fftgrid = pme->fftgrid[grid_index];
- pfft_setup = pme->pfft_setup[grid_index];
- grid = pmegrid->grid.grid;
- calc_next_lb_coeffs(coefficientBuffer, local_sigma);
+ /* Unpack structure */
+ pmegrid = &pme->pmegrid[grid_index];
+ fftgrid = pme->fftgrid[grid_index];
+ pfft_setup = pme->pfft_setup[grid_index];
+ grid = pmegrid->grid.grid;
+ calc_next_lb_coeffs(coefficientBuffer, local_sigma);
#pragma omp parallel num_threads(pme->nthread) private(thread)
+ {
+ try
{
- try
+ thread = gmx_omp_get_thread_num();
+ /* do 3d-invfft */
+ if (thread == 0)
{
- thread = gmx_omp_get_thread_num();
- /* do 3d-invfft */
- if (thread == 0)
- {
- wallcycle_start(wcycle, ewcPME_FFT);
- }
+ wallcycle_start(wcycle, ewcPME_FFT);
+ }
- gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_COMPLEX_TO_REAL, thread, wcycle);
- if (thread == 0)
- {
- wallcycle_stop(wcycle, ewcPME_FFT);
+ gmx_parallel_3dfft_execute(pfft_setup, GMX_FFT_COMPLEX_TO_REAL, thread, wcycle);
+ if (thread == 0)
+ {
+ wallcycle_stop(wcycle, ewcPME_FFT);
- if (pme->nodeid == 0)
- {
- real ntot = pme->nkx * pme->nky * pme->nkz;
- npme = static_cast<int>(ntot * std::log(ntot) / std::log(2.0));
- inc_nrnb(nrnb, eNR_FFT, 2 * npme);
- }
- wallcycle_start(wcycle, ewcPME_GATHER);
+ if (pme->nodeid == 0)
+ {
+ real ntot = pme->nkx * pme->nky * pme->nkz;
+ npme = static_cast<int>(ntot * std::log(ntot) / std::log(2.0));
+ inc_nrnb(nrnb, eNR_FFT, 2 * npme);
}
-
- copy_fftgrid_to_pmegrid(pme, fftgrid, grid, grid_index, pme->nthread, thread);
+ wallcycle_start(wcycle, ewcPME_GATHER);
}
- GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
- } /*#pragma omp parallel*/
- /* distribute local grid to all nodes */
- if (pme->nnodes > 1)
- {
- gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_BACKWARD);
+ copy_fftgrid_to_pmegrid(pme, fftgrid, grid, grid_index, pme->nthread, thread);
}
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+ } /*#pragma omp parallel*/
- unwrap_periodic_pmegrid(pme, grid);
+ /* distribute local grid to all nodes */
+ if (pme->nnodes > 1)
+ {
+ gmx_sum_qgrid_dd(pme, grid, GMX_SUM_GRID_BACKWARD);
+ }
- if (bCalcF)
- {
- /* interpolate forces for our local atoms */
- bClearF = (bFirst && PAR(cr));
- scale = pme->bFEP ? (fep_state < 1 ? 1.0 - lambda_lj : lambda_lj) : 1.0;
- scale *= lb_scale_factor[grid_index - 2];
+ unwrap_periodic_pmegrid(pme, grid);
+
+ if (stepWork.computeForces)
+ {
+ /* interpolate forces for our local atoms */
+ bClearF = (bFirst && PAR(cr));
+ scale = pme->bFEP ? (fep_state < 1 ? 1.0 - lambda_lj : lambda_lj) : 1.0;
+ scale *= lb_scale_factor[grid_index - 2];
#pragma omp parallel for num_threads(pme->nthread) schedule(static)
- for (thread = 0; thread < pme->nthread; thread++)
+ for (thread = 0; thread < pme->nthread; thread++)
+ {
+ try
{
- try
- {
- gather_f_bsplines(pme, grid, bClearF, &pme->atc[0],
- &pme->atc[0].spline[thread], scale);
- }
- GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+ gather_f_bsplines(pme, grid, bClearF, &pme->atc[0],
+ &pme->atc[0].spline[thread], scale);
}
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+ }
- inc_nrnb(nrnb, eNR_GATHERFBSP,
- pme->pme_order * pme->pme_order * pme->pme_order * pme->atc[0].numAtoms());
- }
- wallcycle_stop(wcycle, ewcPME_GATHER);
+ inc_nrnb(nrnb, eNR_GATHERFBSP,
+ pme->pme_order * pme->pme_order * pme->pme_order * pme->atc[0].numAtoms());
+ }
+ wallcycle_stop(wcycle, ewcPME_GATHER);
- bFirst = FALSE;
- } /* for (grid_index = 8; grid_index >= 2; --grid_index) */
- } /* if (bCalcF) */
- } /* for (fep_state = 0; fep_state < fep_states_lj; ++fep_state) */
- } /* if ((flags & GMX_PME_DO_LJ) && pme->ljpme_combination_rule == eljpmeLB) */
+ bFirst = FALSE;
+ } /* for (grid_index = 8; grid_index >= 2; --grid_index) */
+ } /* for (fep_state = 0; fep_state < fep_states_lj; ++fep_state) */
+ } /* if (pme->doLJ && pme->ljpme_combination_rule == eljpmeLB) */
- if (bCalcF && pme->nnodes > 1)
+ if (stepWork.computeForces && pme->nnodes > 1)
{
wallcycle_start(wcycle, ewcPME_REDISTXF);
for (d = 0; d < pme->ndecompdim; d++)
wallcycle_stop(wcycle, ewcPME_REDISTXF);
}
- if (bCalcEnerVir)
+ if (computeEnergyAndVirial)
{
if (pme->doCoulomb)
{
destroy_pme_spline_work(pme->spline_work);
- if (pme_gpu_active(pme) && pme->gpu)
+ if (pme->gpu != nullptr)
{
pme_gpu_destroy(pme->gpu);
}
void gmx_pme_reinit_atoms(gmx_pme_t* pme, const int numAtoms, const real* charges)
{
- if (pme_gpu_active(pme))
+ if (pme->gpu != nullptr)
{
pme_gpu_reinit_atoms(pme->gpu, numAtoms, charges);
}
// TODO: set the charges here as well
}
}
+
+bool gmx_pme_grid_matches(const gmx_pme_t& pme, const ivec grid_size)
+{
+ return (pme.nkx == grid_size[XX] && pme.nky == grid_size[YY] && pme.nkz == grid_size[ZZ]);
+}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "pme_gpu_types.h"
/*! \brief \internal
- * A single structure encompassing all the PME data used in CUDA kernels.
- * This inherits from PmeGpuKernelParamsBase and adds a couple cudaTextureObject_t handles,
- * which we would like to avoid in plain C++.
+ * An alias for PME parameters in CUDA.
+ * \todo Remove if we decide to unify CUDA and OpenCL
*/
struct PmeGpuCudaKernelParams : PmeGpuKernelParamsBase
{
- /* These are CUDA texture objects, related to the grid size. */
- /*! \brief CUDA texture object for accessing grid.d_fractShiftsTable */
- cudaTextureObject_t fractShiftsTableTexture;
- /*! \brief CUDA texture object for accessing grid.d_gridlineIndicesTable */
- cudaTextureObject_t gridlineIndicesTableTexture;
+ // Place CUDA-specific stuff here
};
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gpu_macros.h"
#include "gromacs/math/vectypes.h"
-#include "gromacs/timing/walltime_accounting.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
struct gmx_hw_info_t;
-struct interaction_const_t;
struct t_commrec;
-struct t_forcerec;
struct t_inputrec;
struct t_nrnb;
struct PmeGpu;
struct gmx_wallclock_gpu_pme_t;
-struct gmx_device_info_t;
struct gmx_enerdata_t;
struct gmx_mtop_t;
struct gmx_pme_t;
struct gmx_wallcycle;
struct NumPmeDomains;
+class DeviceContext;
+class DeviceStream;
enum class GpuTaskCompletion;
class PmeGpuProgram;
class GpuEventSynchronizer;
-//! Convenience name.
-using PmeGpuProgramHandle = const PmeGpuProgram*;
namespace gmx
{
-class PmePpCommGpu;
class ForceWithVirial;
class MDLogger;
enum class PinningPolicy : int;
+class StepWorkload;
} // namespace gmx
enum
Mixed, //!< Mixed mode: only spread and gather run on GPU; FFT and solving are done on CPU.
};
-//! PME gathering output forces treatment
-enum class PmeForceOutputHandling
-{
- Set, /**< Gather simply writes into provided force buffer */
- ReduceWithInput, /**< Gather adds its output to the buffer.
- On GPU, that means additional H2D copy before the kernel launch. */
-};
-
/*! \brief Return the smallest allowed PME grid size for \p pmeOrder */
int minimalPmeGridSize(int pmeOrder);
+//! Return whether the grid of \c pme is identical to \c grid_size.
+bool gmx_pme_grid_matches(const gmx_pme_t& pme, const ivec grid_size);
+
/*! \brief Check restrictions on pme_order and the PME grid nkx,nky,nkz.
*
* With errorsAreFatal=true, an exception or fatal error is generated
* \returns Pointer to newly allocated and initialized PME data.
*
* \todo We should evolve something like a \c GpuManager that holds \c
- * gmx_device_info_t * and \c PmeGpuProgramHandle and perhaps other
+ * DeviceInformation* and \c PmeGpuProgram* and perhaps other
* related things whose lifetime can/should exceed that of a task (or
- * perhaps task manager). See Redmine #2522.
+ * perhaps task manager). See Issue #2522.
*/
-gmx_pme_t* gmx_pme_init(const t_commrec* cr,
- const NumPmeDomains& numPmeDomains,
- const t_inputrec* ir,
- gmx_bool bFreeEnergy_q,
- gmx_bool bFreeEnergy_lj,
- gmx_bool bReproducible,
- real ewaldcoeff_q,
- real ewaldcoeff_lj,
- int nthread,
- PmeRunMode runMode,
- PmeGpu* pmeGpu,
- const gmx_device_info_t* gpuInfo,
- PmeGpuProgramHandle pmeGpuProgram,
- const gmx::MDLogger& mdlog);
+gmx_pme_t* gmx_pme_init(const t_commrec* cr,
+ const NumPmeDomains& numPmeDomains,
+ const t_inputrec* ir,
+ gmx_bool bFreeEnergy_q,
+ gmx_bool bFreeEnergy_lj,
+ gmx_bool bReproducible,
+ real ewaldcoeff_q,
+ real ewaldcoeff_lj,
+ int nthread,
+ PmeRunMode runMode,
+ PmeGpu* pmeGpu,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
+ const gmx::MDLogger& mdlog);
+
+/*! \brief As gmx_pme_init, but takes most settings, except the grid/Ewald coefficients, from
+ * pme_src. This is only called when the PME cut-off/grid size changes.
+ */
+void gmx_pme_reinit(gmx_pme_t** pmedata,
+ const t_commrec* cr,
+ gmx_pme_t* pme_src,
+ const t_inputrec* ir,
+ const ivec grid_size,
+ real ewaldcoeff_q,
+ real ewaldcoeff_lj);
/*! \brief Destroys the PME data structure.*/
void gmx_pme_destroy(gmx_pme_t* pme);
-//@{
-/*! \brief Flag values that control what gmx_pme_do() will calculate
- *
- * These can be combined with bitwise-OR if more than one thing is required.
- */
-#define GMX_PME_SPREAD (1 << 0)
-#define GMX_PME_SOLVE (1 << 1)
-#define GMX_PME_CALC_F (1 << 2)
-#define GMX_PME_CALC_ENER_VIR (1 << 3)
-/* This forces the grid to be backtransformed even without GMX_PME_CALC_F */
-#define GMX_PME_CALC_POT (1 << 4)
-
-#define GMX_PME_DO_ALL_F (GMX_PME_SPREAD | GMX_PME_SOLVE | GMX_PME_CALC_F)
-//@}
-
/*! \brief Do a PME calculation on a CPU for the long range electrostatics and/or LJ.
*
* Computes the PME forces and the energy and viral, when requested,
real lambda_lj,
real* dvdlambda_q,
real* dvdlambda_lj,
- int flags);
-
-/*! \brief Called on the nodes that do PME exclusively */
-int gmx_pmeonly(struct gmx_pme_t* pme,
- const t_commrec* cr,
- t_nrnb* mynrnb,
- gmx_wallcycle* wcycle,
- gmx_walltime_accounting_t walltime_accounting,
- t_inputrec* ir,
- PmeRunMode runMode);
+ const gmx::StepWorkload& stepWork);
/*! \brief Calculate the PME grid energy V for n charges.
*
* The potential (found in \p pme) must have been found already with a
- * call to gmx_pme_do() with at least GMX_PME_SPREAD and GMX_PME_SOLVE
- * specified. Note that the charges are not spread on the grid in the
+ * call to gmx_pme_do(). Note that the charges are not spread on the grid in the
* pme struct. Currently does not work in parallel or with free
* energy.
*/
void gmx_pme_calc_energy(gmx_pme_t* pme, gmx::ArrayRef<const gmx::RVec> x, gmx::ArrayRef<const real> q, real* V);
-/*! \brief Send the charges and maxshift to out PME-only node. */
-void gmx_pme_send_parameters(const t_commrec* cr,
- const interaction_const_t* ic,
- gmx_bool bFreeEnergy_q,
- gmx_bool bFreeEnergy_lj,
- real* chargeA,
- real* chargeB,
- real* sqrt_c6A,
- real* sqrt_c6B,
- real* sigmaA,
- real* sigmaB,
- int maxshift_x,
- int maxshift_y);
-
-/*! \brief Send the coordinates to our PME-only node and request a PME calculation */
-void gmx_pme_send_coordinates(t_forcerec* fr,
- const t_commrec* cr,
- const matrix box,
- const rvec* x,
- real lambda_q,
- real lambda_lj,
- gmx_bool bEnerVir,
- int64_t step,
- bool useGpuPmePpComms,
- bool reinitGpuPmePpComms,
- bool sendCoordinatesFromGpu,
- GpuEventSynchronizer* coordinatesReadyOnDeviceEvent,
- gmx_wallcycle* wcycle);
-
-/*! \brief Tell our PME-only node to finish */
-void gmx_pme_send_finish(const t_commrec* cr);
-
-/*! \brief Tell our PME-only node to reset all cycle and flop counters */
-void gmx_pme_send_resetcounters(const t_commrec* cr, int64_t step);
-
-/*! \brief PP nodes receive the long range forces from the PME nodes */
-void gmx_pme_receive_f(gmx::PmePpCommGpu* pmePpCommGpu,
- const t_commrec* cr,
- gmx::ForceWithVirial* forceWithVirial,
- real* energy_q,
- real* energy_lj,
- real* dvdlambda_q,
- real* dvdlambda_lj,
- bool useGpuPmePpComms,
- bool receivePmeForceToGpu,
- float* pme_cycles);
-
/*! \brief
* This function updates the local atom data on GPU after DD (charges, coordinates, etc.).
* TODO: it should update the PME CPU atom data as well.
return (pme != nullptr) && (pme_run_mode(pme) != PmeRunMode::CPU);
}
-/*! \brief Returns the size of the padding needed by GPU version of PME in the coordinates array.
+/*! \brief Returns the block size requirement
+ *
+ * The GPU version of PME requires that the coordinates array have a
+ * size divisible by the returned number.
*
* \param[in] pme The PME data structure.
*/
-GPU_FUNC_QUALIFIER int pme_gpu_get_padding_size(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
+GPU_FUNC_QUALIFIER int pme_gpu_get_block_size(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
GPU_FUNC_TERM_WITH_RETURN(0);
// The following functions are all the PME GPU entry points,
/*! \brief
* Prepares PME on GPU computation (updating the box if needed)
* \param[in] pme The PME data structure.
- * \param[in] needToUpdateBox Tells if the stored unit cell parameters should be updated from \p box.
* \param[in] box The unit cell box.
* \param[in] wcycle The wallclock counter.
- * \param[in] flags The combination of flags to affect this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
- * \param[in] useGpuForceReduction Whether PME forces are reduced on GPU this step or should be downloaded for CPU reduction
+ * \param[in] stepWork The required work for this simulation step
*/
-GPU_FUNC_QUALIFIER void pme_gpu_prepare_computation(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- bool GPU_FUNC_ARGUMENT(needToUpdateBox),
- const matrix GPU_FUNC_ARGUMENT(box),
+GPU_FUNC_QUALIFIER void pme_gpu_prepare_computation(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ const matrix GPU_FUNC_ARGUMENT(box),
gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
- int GPU_FUNC_ARGUMENT(flags),
- bool GPU_FUNC_ARGUMENT(useGpuForceReduction)) GPU_FUNC_TERM;
+ const gmx::StepWorkload& GPU_FUNC_ARGUMENT(stepWork)) GPU_FUNC_TERM;
/*! \brief
* Launches first stage of PME on GPU - spreading kernel.
*
* \param[in] pme The PME data structure.
* \param[in] wcycle The wallclock counter.
+ * \param[in] stepWork The required work for this simulation step
*/
-GPU_FUNC_QUALIFIER void pme_gpu_launch_complex_transforms(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle)) GPU_FUNC_TERM;
+GPU_FUNC_QUALIFIER void
+pme_gpu_launch_complex_transforms(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
+ const gmx::StepWorkload& GPU_FUNC_ARGUMENT(stepWork)) GPU_FUNC_TERM;
/*! \brief
* Launches last stage of PME on GPU - force gathering and D2H force transfer.
*
* \param[in] pme The PME data structure.
* \param[in] wcycle The wallclock counter.
- * \param[in] forceTreatment Tells how data should be treated. The gathering kernel either
- * stores the output reciprocal forces into the host array, or copies its contents to the GPU first
- * and accumulates. The reduction is non-atomic.
*/
GPU_FUNC_QUALIFIER void pme_gpu_launch_gather(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
- PmeForceOutputHandling GPU_FUNC_ARGUMENT(forceTreatment)) GPU_FUNC_TERM;
+ gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle)) GPU_FUNC_TERM;
/*! \brief
* Attempts to complete PME GPU tasks.
* by assigning the ArrayRef to the \p forces pointer passed in.
* Virial/energy are also outputs if they were to be computed.
*
- * \param[in] pme The PME data structure.
- * \param[in] flags The combination of flags to affect this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
- * \param[in] wcycle The wallclock counter.
+ * \param[in] pme The PME data structure.
+ * \param[in] stepWork The required work for this simulation step
+ * \param[in] wcycle The wallclock counter.
* \param[out] forceWithVirial The output force and virial
* \param[out] enerd The output energies
- * \param[in] flags The combination of flags to affect this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
* \param[in] completionKind Indicates whether PME task completion should only be checked rather
- * than waited for \returns True if the PME GPU tasks have completed
+ * than waited for
+ * \returns True if the PME GPU tasks have completed
*/
-GPU_FUNC_QUALIFIER bool pme_gpu_try_finish_task(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- int GPU_FUNC_ARGUMENT(flags),
- gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
+GPU_FUNC_QUALIFIER bool pme_gpu_try_finish_task(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ const gmx::StepWorkload& GPU_FUNC_ARGUMENT(stepWork),
+ gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
gmx::ForceWithVirial* GPU_FUNC_ARGUMENT(forceWithVirial),
gmx_enerdata_t* GPU_FUNC_ARGUMENT(enerd),
GpuTaskCompletion GPU_FUNC_ARGUMENT(completionKind))
* (if they were to be computed).
*
* \param[in] pme The PME data structure.
- * \param[in] flags The combination of flags to affect this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
+ * \param[in] stepWork The required work for this simulation step
* \param[in] wcycle The wallclock counter.
* \param[out] forceWithVirial The output force and virial
* \param[out] enerd The output energies
*/
-GPU_FUNC_QUALIFIER void pme_gpu_wait_and_reduce(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- int GPU_FUNC_ARGUMENT(flags),
- gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
+GPU_FUNC_QUALIFIER void pme_gpu_wait_and_reduce(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ const gmx::StepWorkload& GPU_FUNC_ARGUMENT(stepWork),
+ gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle),
gmx::ForceWithVirial* GPU_FUNC_ARGUMENT(forceWithVirial),
gmx_enerdata_t* GPU_FUNC_ARGUMENT(enerd)) GPU_FUNC_TERM;
GPU_FUNC_QUALIFIER void pme_gpu_reinit_computation(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle)) GPU_FUNC_TERM;
-
-/*! \brief Get pointer to device copy of coordinate data.
- * \param[in] pme The PME data structure.
- * \returns Pointer to coordinate data
- */
-GPU_FUNC_QUALIFIER DeviceBuffer<float> pme_gpu_get_device_x(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
- GPU_FUNC_TERM_WITH_RETURN(DeviceBuffer<float>{});
-
/*! \brief Set pointer to device copy of coordinate data.
* \param[in] pme The PME data structure.
* \param[in] d_x The pointer to the positions buffer to be set
*/
-GPU_FUNC_QUALIFIER void pme_gpu_set_device_x(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- DeviceBuffer<float> GPU_FUNC_ARGUMENT(d_x)) GPU_FUNC_TERM;
+GPU_FUNC_QUALIFIER void pme_gpu_set_device_x(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ DeviceBuffer<gmx::RVec> GPU_FUNC_ARGUMENT(d_x)) GPU_FUNC_TERM;
/*! \brief Get pointer to device copy of force data.
* \param[in] pme The PME data structure.
GPU_FUNC_QUALIFIER void* pme_gpu_get_device_f(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
GPU_FUNC_TERM_WITH_RETURN(nullptr);
-/*! \brief Returns the pointer to the GPU stream.
- * \param[in] pme The PME data structure.
- * \returns Pointer to GPU stream object.
- */
-GPU_FUNC_QUALIFIER void* pme_gpu_get_device_stream(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
- GPU_FUNC_TERM_WITH_RETURN(nullptr);
-
-/*! \brief Returns the pointer to the GPU context.
- * \param[in] pme The PME data structure.
- * \returns Pointer to GPU context object.
- */
-GPU_FUNC_QUALIFIER void* pme_gpu_get_device_context(const gmx_pme_t* GPU_FUNC_ARGUMENT(pme))
- GPU_FUNC_TERM_WITH_RETURN(nullptr);
-
/*! \brief Get pointer to the device synchronizer object that allows syncing on PME force calculation completion
* \param[in] pme The PME data structure.
* \returns Pointer to sychronizer
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_PMECOORDINATERECEIVERGPU_H
#define GMX_PMECOORDINATERECEIVERGPU_H
-#include "gromacs/ewald/pme.h"
-#include "gromacs/ewald/pme_force_sender_gpu.h"
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
+#include "gromacs/math/vectypes.h"
#include "gromacs/utility/classhelpers.h"
#include "gromacs/utility/gmxmpi.h"
+class DeviceStream;
+struct PpRanks;
+
namespace gmx
{
+template<typename>
+class ArrayRef;
+
class PmeCoordinateReceiverGpu
{
* \param[in] comm Communicator used for simulation
* \param[in] ppRanks List of PP ranks
*/
- PmeCoordinateReceiverGpu(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
+ PmeCoordinateReceiverGpu(const DeviceStream& pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
~PmeCoordinateReceiverGpu();
/*! \brief
* send coordinates buffer address to PP rank
* \param[in] d_x coordinates buffer in GPU memory
*/
- void sendCoordinateBufferAddressToPpRanks(rvec* d_x);
+ void sendCoordinateBufferAddressToPpRanks(DeviceBuffer<RVec> d_x);
/*! \brief
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
#include "gromacs/ewald/pme_coordinate_receiver_gpu.h"
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/gmxassert.h"
#if GMX_GPU != GMX_GPU_CUDA
};
/*!\brief Constructor stub. */
-PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void gmx_unused* pmeStream,
- MPI_Comm gmx_unused comm,
- gmx::ArrayRef<PpRanks> gmx_unused ppRanks) :
+PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(const DeviceStream& /* pmeStream */,
+ MPI_Comm /* comm */,
+ gmx::ArrayRef<PpRanks> /* ppRanks */) :
impl_(nullptr)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
PmeCoordinateReceiverGpu::~PmeCoordinateReceiverGpu() = default;
/*!\brief init PME-PP GPU communication stub */
-void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(rvec gmx_unused* d_x)
+void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(DeviceBuffer<RVec> /* d_x */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication initialization was called instead of the "
"correct implementation.");
}
-void PmeCoordinateReceiverGpu::launchReceiveCoordinatesFromPpCudaDirect(int gmx_unused ppRank)
+void PmeCoordinateReceiverGpu::launchReceiveCoordinatesFromPpCudaDirect(int /* ppRank */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
void PmeCoordinateReceiverGpu::enqueueWaitReceiveCoordinatesFromPpCudaDirect()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
-#include <assert.h>
-#include <stdio.h>
-
-#include "gromacs/ewald/pme.h"
+#include "gromacs/ewald/pme_force_sender_gpu.h"
#include "gromacs/gpu_utils/cudautils.cuh"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
#include "gromacs/utility/gmxmpi.h"
namespace gmx
{
-PmeCoordinateReceiverGpu::Impl::Impl(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks) :
- pmeStream_(*static_cast<cudaStream_t*>(pmeStream)),
+PmeCoordinateReceiverGpu::Impl::Impl(const DeviceStream& pmeStream,
+ MPI_Comm comm,
+ gmx::ArrayRef<PpRanks> ppRanks) :
+ pmeStream_(pmeStream),
comm_(comm),
ppRanks_(ppRanks)
{
PmeCoordinateReceiverGpu::Impl::~Impl() = default;
-void PmeCoordinateReceiverGpu::Impl::sendCoordinateBufferAddressToPpRanks(rvec* d_x)
+void PmeCoordinateReceiverGpu::Impl::sendCoordinateBufferAddressToPpRanks(DeviceBuffer<RVec> d_x)
{
int ind_start = 0;
}
}
-PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void* pmeStream,
+PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(const DeviceStream& pmeStream,
MPI_Comm comm,
gmx::ArrayRef<PpRanks> ppRanks) :
impl_(new Impl(pmeStream, comm, ppRanks))
PmeCoordinateReceiverGpu::~PmeCoordinateReceiverGpu() = default;
-void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(rvec* d_x)
+void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(DeviceBuffer<RVec> d_x)
{
impl_->sendCoordinateBufferAddressToPpRanks(d_x);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_PMECOORDINATERECEIVERGPU_IMPL_H
#include "gromacs/ewald/pme_coordinate_receiver_gpu.h"
-#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
+#include "gromacs/utility/arrayref.h"
+
+class GpuEventSynchronizer;
namespace gmx
{
* \param[in] comm Communicator used for simulation
* \param[in] ppRanks List of PP ranks
*/
- Impl(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
+ Impl(const DeviceStream& pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
~Impl();
/*! \brief
* send coordinates buffer address to PP rank
* \param[in] d_x coordinates buffer in GPU memory
*/
- void sendCoordinateBufferAddressToPpRanks(rvec* d_x);
+ void sendCoordinateBufferAddressToPpRanks(DeviceBuffer<RVec> d_x);
/*! \brief
* launch receive of coordinate data from PP rank
private:
//! CUDA stream for PME operations
- cudaStream_t pmeStream_ = nullptr;
+ const DeviceStream& pmeStream_;
//! communicator for simulation
MPI_Comm comm_;
//! list of PP ranks
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/classhelpers.h"
#include "gromacs/utility/gmxmpi.h"
+class DeviceStream;
+
/*! \libinternal
* \brief Contains information about the PP ranks that partner this PME rank. */
struct PpRanks
* \param[in] comm Communicator used for simulation
* \param[in] ppRanks List of PP ranks
*/
- PmeForceSenderGpu(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
+ PmeForceSenderGpu(const DeviceStream& pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
~PmeForceSenderGpu();
/*! \brief
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
};
/*!\brief Constructor stub. */
-PmeForceSenderGpu::PmeForceSenderGpu(void gmx_unused* pmeStream,
- MPI_Comm gmx_unused comm,
- gmx::ArrayRef<PpRanks> gmx_unused ppRanks) :
+PmeForceSenderGpu::PmeForceSenderGpu(const DeviceStream& /*pmeStream */,
+ MPI_Comm /* comm */,
+ gmx::ArrayRef<PpRanks> /* ppRanks */) :
impl_(nullptr)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
PmeForceSenderGpu::~PmeForceSenderGpu() = default;
/*!\brief init PME-PP GPU communication stub */
-void PmeForceSenderGpu::sendForceBufferAddressToPpRanks(rvec gmx_unused* d_f)
+void PmeForceSenderGpu::sendForceBufferAddressToPpRanks(rvec* /* d_f */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication initialization was called instead of the "
"correct implementation.");
}
-void PmeForceSenderGpu::sendFToPpCudaDirect(int gmx_unused ppRank)
+void PmeForceSenderGpu::sendFToPpCudaDirect(int /* ppRank */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
/*! \brief Create PME-PP GPU communication object */
-PmeForceSenderGpu::Impl::Impl(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks) :
- pmeStream_(*static_cast<cudaStream_t*>(pmeStream)),
+PmeForceSenderGpu::Impl::Impl(const DeviceStream& pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks) :
+ pmeStream_(pmeStream),
comm_(comm),
ppRanks_(ppRanks)
{
#endif
}
-PmeForceSenderGpu::PmeForceSenderGpu(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks) :
+PmeForceSenderGpu::PmeForceSenderGpu(const DeviceStream& pmeStream,
+ MPI_Comm comm,
+ gmx::ArrayRef<PpRanks> ppRanks) :
impl_(new Impl(pmeStream, comm, ppRanks))
{
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] comm Communicator used for simulation
* \param[in] ppRanks List of PP ranks
*/
- Impl(void* pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
+ Impl(const DeviceStream& pmeStream, MPI_Comm comm, gmx::ArrayRef<PpRanks> ppRanks);
~Impl();
/*! \brief
private:
//! CUDA stream for PME operations
- cudaStream_t pmeStream_ = nullptr;
+ const DeviceStream& pmeStream_;
//! Event triggered when to allow remote PP stream to syn with pme stream
GpuEventSynchronizer pmeSync_;
//! communicator for simulation
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* - atomsPerBlock which expresses how many atoms are processed by a single work group
* - order which is a PME interpolation order
- * - overwriteForces must evaluate to either true or false to specify whether the kernel
- * overwrites or reduces into the forces buffer
* - wrapX and wrapY must evaluate to either true or false to specify whether the grid overlap
* in dimension X/Y is to be used
*
*/
#include "pme_gpu_types.h"
-#include "pme_gpu_utils.clh"
+#include "pme_gpu_calculate_splines.clh"
#ifndef COMPILE_GATHER_HELPERS_ONCE
# define COMPILE_GATHER_HELPERS_ONCE
case XX: return realGridSizeFP[XX];
case YY: return realGridSizeFP[YY];
case ZZ: return realGridSizeFP[ZZ];
+ default: assert(false); break;
}
assert(false);
- return 0.0f;
+ return 0.0F;
}
/*! \brief Reduce the partial force contributions.
{
/* These are the atom indices - for the shared and global memory */
const int atomIndexLocal = get_local_id(ZZ);
- const int atomIndexOffset = get_group_id(XX) * atomsPerBlock;
+ const int atomIndexOffset = (int)get_group_id(XX) * atomsPerBlock;
const int atomIndexGlobal = atomIndexOffset + atomIndexLocal;
/* Some sizes which are defines and not consts because they go into the array size */
const int ithy = get_local_id(YY);
const int ithz = get_local_id(XX);
- const int threadLocalId = (get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0)
- + get_local_id(0);
+ assert((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0) + get_local_id(0)
+ <= MAX_INT);
+ const int threadLocalId =
+ (int)((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0)
+ + get_local_id(0));
/* These are the spline contribution indices in shared memory */
- const int splineIndex = (get_local_id(1) * get_local_size(0)
- + get_local_id(0)); /* Relative to the current particle , 0..15 for order 4 */
- const int lineIndex = threadLocalId; /* And to all the block's particles */
+ assert((get_local_id(1) * get_local_size(0) + get_local_id(0)) <= MAX_INT);
+ const int splineIndex =
+ (int)(get_local_id(1) * get_local_size(0)
+ + get_local_id(0)); /* Relative to the current particle , 0..15 for order 4 */
+ const int lineIndex = threadLocalId; /* And to all the block's particles */
/* Staging the atom gridline indices, DIM * atomsPerBlock threads */
const int localGridlineIndicesIndex = threadLocalId;
const int globalGridlineIndicesIndex =
- get_group_id(XX) * gridlineIndicesSize + localGridlineIndicesIndex;
- const int globalCheckIndices =
- pme_gpu_check_atom_data_index(globalGridlineIndicesIndex, kernelParams.atoms.nAtoms * DIM);
- if ((localGridlineIndicesIndex < gridlineIndicesSize) & globalCheckIndices)
+ (int)get_group_id(XX) * gridlineIndicesSize + localGridlineIndicesIndex;
+ if (localGridlineIndicesIndex < gridlineIndicesSize)
{
sm_gridlineIndices[localGridlineIndicesIndex] = gm_gridlineIndices[globalGridlineIndicesIndex];
assert(sm_gridlineIndices[localGridlineIndicesIndex] >= 0);
}
/* Staging the spline parameters, DIM * order * atomsPerBlock threads */
- const int localSplineParamsIndex = threadLocalId;
- const int globalSplineParamsIndex = get_group_id(XX) * splineParamsSize + localSplineParamsIndex;
- const int globalCheckSplineParams = pme_gpu_check_atom_data_index(
- globalSplineParamsIndex, kernelParams.atoms.nAtoms * DIM * order);
- if ((localSplineParamsIndex < splineParamsSize) && globalCheckSplineParams)
+ const int localSplineParamsIndex = threadLocalId;
+ const int globalSplineParamsIndex = (int)get_group_id(XX) * splineParamsSize + localSplineParamsIndex;
+ if (localSplineParamsIndex < splineParamsSize)
{
sm_splineParams[localSplineParamsIndex].x = gm_theta[globalSplineParamsIndex];
sm_splineParams[localSplineParamsIndex].y = gm_dtheta[globalSplineParamsIndex];
}
barrier(CLK_LOCAL_MEM_FENCE);
- float fx = 0.0f;
- float fy = 0.0f;
- float fz = 0.0f;
+ float fx = 0.0F;
+ float fy = 0.0F;
+ float fz = 0.0F;
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
const int chargeCheck = pme_gpu_check_atom_charge(gm_coefficients[atomIndexGlobal]);
- if (chargeCheck & globalCheck)
+ if (chargeCheck)
{
const int nx = kernelParams.grid.realGridSize[XX];
const int ny = kernelParams.grid.realGridSize[YY];
/* Calculating the final forces with no component branching, atomsPerBlock threads */
const int forceIndexLocal = threadLocalId;
const int forceIndexGlobal = atomIndexOffset + forceIndexLocal;
- const int calcIndexCheck = pme_gpu_check_atom_data_index(forceIndexGlobal, kernelParams.atoms.nAtoms);
- if ((forceIndexLocal < atomsPerBlock) & calcIndexCheck)
+ if (forceIndexLocal < atomsPerBlock)
{
const float3 atomForces = vload3(forceIndexLocal, sm_forces);
const float negCoefficient = -gm_coefficients[forceIndexGlobal];
for (int i = 0; i < numIter; i++)
{
const int outputIndexLocal = i * iterThreads + threadLocalId;
- const int outputIndexGlobal = get_group_id(XX) * blockForcesSize + outputIndexLocal;
- const int globalOutputCheck =
- pme_gpu_check_atom_data_index(outputIndexGlobal, kernelParams.atoms.nAtoms * DIM);
- if (globalOutputCheck)
- {
- const float outputForceComponent = sm_forces[outputIndexLocal];
- if (overwriteForces)
- {
- gm_forces[outputIndexGlobal] = outputForceComponent;
- }
- else
- {
- gm_forces[outputIndexGlobal] += outputForceComponent;
- }
- }
+ const int outputIndexGlobal = (int)get_group_id(XX) * blockForcesSize + outputIndexLocal;
+ const float outputForceComponent = sm_forces[outputIndexLocal];
+ gm_forces[outputIndexGlobal] = outputForceComponent;
}
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cassert>
#include "gromacs/gpu_utils/cuda_kernel_utils.cuh"
+#include "gromacs/gpu_utils/typecasts.cuh"
#include "pme.cuh"
-#include "pme_calculate_splines.cuh"
-#include "pme_gpu_utils.h"
+#include "pme_gpu_calculate_splines.cuh"
#include "pme_grid.h"
/*! \brief
*
* \tparam[in] order The PME order (must be 4).
* \tparam[in] atomDataSize The number of partial force contributions for each atom (currently
- * order^2 == 16) \tparam[in] blockSize The CUDA block size \param[out] sm_forces Shared
- * memory array with the output forces (number of elements is number of atoms per block) \param[in]
- * atomIndexLocal Local atom index \param[in] splineIndex Spline index \param[in]
- * lineIndex Line index (same as threadLocalId) \param[in] realGridSizeFP Local grid
- * size constant \param[in] fx Input force partial component X \param[in] fy Input
- * force partial component Y \param[in] fz Input force partial component Z
+ * order^2 == 16)
+ * \tparam[in] blockSize The CUDA block size
+ *
+ * \param[out] sm_forces Shared memory array with the output forces (number of elements
+ * is number of atoms per block)
+ * \param[in] atomIndexLocal Local atom index
+ * \param[in] splineIndex Spline index
+ * \param[in] lineIndex Line index (same as threadLocalId)
+ * \param[in] realGridSizeFP Local grid size constant
+ * \param[in] fx Input force partial component X
+ * \param[in] fy Input force partial component Y
+ * \param[in] fz Input force partial component Z
*/
-template<const int order, const int atomDataSize, const int blockSize>
+template<int order, int atomDataSize, int blockSize>
__device__ __forceinline__ void reduce_atom_forces(float3* __restrict__ sm_forces,
const int atomIndexLocal,
const int splineIndex,
* The grid is assumed to be wrapped in dimension Z.
*
* \tparam[in] order The PME order (must be 4 currently).
- * \tparam[in] overwriteForces True: the forces are written to the output buffer;
- * False: the forces are added non-atomically to the output buffer (e.g. to the bonded forces).
* \tparam[in] wrapX Tells if the grid is wrapped in the X dimension.
* \tparam[in] wrapY Tells if the grid is wrapped in the Y dimension.
* \tparam[in] readGlobal Tells if we should read spline values from global memory
- * \tparam[in] useOrderThreads Tells if we should use order threads per atom (order*order used if false)
+ * \tparam[in] threadsPerAtom How many threads work on each atom
+ *
* \param[in] kernelParams All the PME GPU data.
*/
-template<const int order, const bool overwriteForces, const bool wrapX, const bool wrapY, const bool readGlobal, const bool useOrderThreads>
+template<int order, bool wrapX, bool wrapY, bool readGlobal, ThreadsPerAtom threadsPerAtom>
__launch_bounds__(c_gatherMaxThreadsPerBlock, c_gatherMinBlocksPerMP) __global__
void pme_gather_kernel(const PmeGpuCudaKernelParams kernelParams)
{
float3 atomX;
float atomCharge;
- /* Some sizes */
- const int atomsPerBlock =
- useOrderThreads ? (c_gatherMaxThreadsPerBlock / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom)
- : (c_gatherMaxThreadsPerBlock / c_pmeSpreadGatherThreadsPerAtom);
const int blockIndex = blockIdx.y * gridDim.x + blockIdx.x;
/* Number of data components and threads for a single atom */
- const int atomDataSize = useOrderThreads ? c_pmeSpreadGatherThreadsPerAtom4ThPerAtom
- : c_pmeSpreadGatherThreadsPerAtom;
- const int atomsPerWarp = useOrderThreads ? c_pmeSpreadGatherAtomsPerWarp4ThPerAtom
- : c_pmeSpreadGatherAtomsPerWarp;
+ const int threadsPerAtomValue = (threadsPerAtom == ThreadsPerAtom::Order) ? order : order * order;
+ const int atomDataSize = threadsPerAtomValue;
+ const int atomsPerBlock = c_gatherMaxThreadsPerBlock / atomDataSize;
+ // Number of atoms processed by a single warp in spread and gather
+ const int atomsPerWarp = warp_size / atomDataSize;
const int blockSize = atomsPerBlock * atomDataSize;
assert(blockSize == blockDim.x * blockDim.y * blockDim.z);
/* Read splines */
const int localGridlineIndicesIndex = threadLocalId;
const int globalGridlineIndicesIndex = blockIndex * gridlineIndicesSize + localGridlineIndicesIndex;
- const int globalCheckIndices = pme_gpu_check_atom_data_index(
- globalGridlineIndicesIndex, kernelParams.atoms.nAtoms * DIM);
- if ((localGridlineIndicesIndex < gridlineIndicesSize) & globalCheckIndices)
+ if (localGridlineIndicesIndex < gridlineIndicesSize)
{
sm_gridlineIndices[localGridlineIndicesIndex] = gm_gridlineIndices[globalGridlineIndicesIndex];
assert(sm_gridlineIndices[localGridlineIndicesIndex] >= 0);
with order*order threads per atom, it is only required for each thread to load one data value */
const int iMin = 0;
- const int iMax = useOrderThreads ? 3 : 1;
+ const int iMax = (threadsPerAtom == ThreadsPerAtom::Order) ? 3 : 1;
for (int i = iMin; i < iMax; i++)
{
threadLocalId
+ i * threadLocalIdMax; /* i will always be zero for order*order threads per atom */
int globalSplineParamsIndex = blockIndex * splineParamsSize + localSplineParamsIndex;
- int globalCheckSplineParams = pme_gpu_check_atom_data_index(
- globalSplineParamsIndex, kernelParams.atoms.nAtoms * DIM * order);
- if ((localSplineParamsIndex < splineParamsSize) && globalCheckSplineParams)
+ if (localSplineParamsIndex < splineParamsSize)
{
sm_theta[localSplineParamsIndex] = gm_theta[globalSplineParamsIndex];
sm_dtheta[localSplineParamsIndex] = gm_dtheta[globalSplineParamsIndex];
}
else
{
+ const float3* __restrict__ gm_coordinates = asFloat3(kernelParams.atoms.d_coordinates);
/* Recaclulate Splines */
if (c_useAtomDataPrefetch)
{
// charges
__shared__ float sm_coefficients[atomsPerBlock];
// Coordinates
- __shared__ float sm_coordinates[DIM * atomsPerBlock];
+ __shared__ float3 sm_coordinates[atomsPerBlock];
/* Staging coefficients/charges */
- pme_gpu_stage_atom_data<float, atomsPerBlock, 1>(kernelParams, sm_coefficients,
- kernelParams.atoms.d_coefficients);
+ pme_gpu_stage_atom_data<float, atomsPerBlock, 1>(sm_coefficients, gm_coefficients);
/* Staging coordinates */
- pme_gpu_stage_atom_data<float, atomsPerBlock, DIM>(kernelParams, sm_coordinates,
- kernelParams.atoms.d_coordinates);
+ pme_gpu_stage_atom_data<float3, atomsPerBlock, 1>(sm_coordinates, gm_coordinates);
__syncthreads();
- atomX.x = sm_coordinates[atomIndexLocal * DIM + XX];
- atomX.y = sm_coordinates[atomIndexLocal * DIM + YY];
- atomX.z = sm_coordinates[atomIndexLocal * DIM + ZZ];
+ atomX = sm_coordinates[atomIndexLocal];
atomCharge = sm_coefficients[atomIndexLocal];
}
else
{
+ atomX = gm_coordinates[atomIndexGlobal];
atomCharge = gm_coefficients[atomIndexGlobal];
- atomX.x = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + XX];
- atomX.y = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + YY];
- atomX.z = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + ZZ];
}
calculate_splines<order, atomsPerBlock, atomsPerWarp, true, false>(
kernelParams, atomIndexOffset, atomX, atomCharge, sm_theta, sm_dtheta, sm_gridlineIndices);
float fy = 0.0f;
float fz = 0.0f;
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
const int chargeCheck = pme_gpu_check_atom_charge(gm_coefficients[atomIndexGlobal]);
- if (chargeCheck & globalCheck)
+ if (chargeCheck)
{
const int nx = kernelParams.grid.realGridSize[XX];
const int ny = kernelParams.grid.realGridSize[YY];
}
int constOffset, iy;
- const int ithyMin = useOrderThreads ? 0 : threadIdx.y;
- const int ithyMax = useOrderThreads ? order : threadIdx.y + 1;
+ const int ithyMin = (threadsPerAtom == ThreadsPerAtom::Order) ? 0 : threadIdx.y;
+ const int ithyMax = (threadsPerAtom == ThreadsPerAtom::Order) ? order : threadIdx.y + 1;
for (int ithy = ithyMin; ithy < ithyMax; ithy++)
{
const int splineIndexY = getSplineParamIndex<order, atomsPerWarp>(splineIndexBase, YY, ithy);
/* Calculating the final forces with no component branching, atomsPerBlock threads */
const int forceIndexLocal = threadLocalId;
const int forceIndexGlobal = atomIndexOffset + forceIndexLocal;
- const int calcIndexCheck = pme_gpu_check_atom_data_index(forceIndexGlobal, kernelParams.atoms.nAtoms);
- if ((forceIndexLocal < atomsPerBlock) & calcIndexCheck)
+ if (forceIndexLocal < atomsPerBlock)
{
const float3 atomForces = sm_forces[forceIndexLocal];
const float negCoefficient = -gm_coefficients[forceIndexGlobal];
#pragma unroll
for (int i = 0; i < numIter; i++)
{
- int outputIndexLocal = i * iterThreads + threadLocalId;
- int outputIndexGlobal = blockIndex * blockForcesSize + outputIndexLocal;
- const int globalOutputCheck =
- pme_gpu_check_atom_data_index(outputIndexGlobal, kernelParams.atoms.nAtoms * DIM);
- if (globalOutputCheck)
- {
- const float outputForceComponent = ((float*)sm_forces)[outputIndexLocal];
- if (overwriteForces)
- {
- gm_forces[outputIndexGlobal] = outputForceComponent;
- }
- else
- {
- gm_forces[outputIndexGlobal] += outputForceComponent;
- }
- }
+ int outputIndexLocal = i * iterThreads + threadLocalId;
+ int outputIndexGlobal = blockIndex * blockForcesSize + outputIndexLocal;
+ const float outputForceComponent = ((float*)sm_forces)[outputIndexLocal];
+ gm_forces[outputIndexGlobal] = outputForceComponent;
}
}
}
//! Kernel instantiations
-template __global__ void pme_gather_kernel<4, true, true, true, true, true>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, true, true, true, true, false>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, false, true, true, true, true>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, false, true, true, true, false>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, true, true, true, false, true>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, true, true, true, false, false>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, false, true, true, false, true>(const PmeGpuCudaKernelParams);
-template __global__ void pme_gather_kernel<4, false, true, true, false, false>(const PmeGpuCudaKernelParams);
+// clang-format off
+template __global__ void pme_gather_kernel<4, true, true, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_gather_kernel<4, true, true, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+template __global__ void pme_gather_kernel<4, true, true, false, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_gather_kernel<4, true, true, false, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+// clang-format on
\ No newline at end of file
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_EWALD_PME_GATHER_H
#define GMX_EWALD_PME_GATHER_H
+#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
-#include "pme_internal.h"
+class PmeAtomComm;
+struct gmx_pme_t;
+struct splinedata_t;
void gather_f_bsplines(const struct gmx_pme_t* pme,
const real* grid,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
#include "pme_gpu_internal.h"
+#include "pme_gpu_settings.h"
+#include "pme_gpu_timings.h"
+#include "pme_gpu_types_host.h"
#include "pme_grid.h"
#include "pme_internal.h"
#include "pme_solve.h"
+/*! \brief
+ * Finds out if PME is currently running on GPU.
+ *
+ * \todo The GPU module should not be constructed (or at least called)
+ * when it is not active, so there should be no need to check whether
+ * it is active. An assertion that this is true makes sense.
+ *
+ * \param[in] pme The PME structure.
+ * \returns True if PME runs on GPU currently, false otherwise.
+ */
+static inline bool pme_gpu_active(const gmx_pme_t* pme)
+{
+ return (pme != nullptr) && (pme->runMode != PmeRunMode::CPU);
+}
+
void pme_gpu_reset_timings(const gmx_pme_t* pme)
{
if (pme_gpu_active(pme))
}
}
-int pme_gpu_get_padding_size(const gmx_pme_t* pme)
+int pme_gpu_get_block_size(const gmx_pme_t* pme)
{
if (!pme || !pme_gpu_active(pme))
}
else
{
- return pme_gpu_get_atom_data_alignment(pme->gpu);
+ return pme_gpu_get_atom_data_block_size();
}
}
gmx_wallcycle_t wcycle)
{
GMX_ASSERT(gridIndex == 0, "Only single grid supported");
- if (pme_gpu_performs_FFT(pme->gpu))
+ if (pme_gpu_settings(pme->gpu).performGPUFFT)
{
wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
/* The PME computation code split into a few separate functions. */
-void pme_gpu_prepare_computation(gmx_pme_t* pme,
- bool needToUpdateBox,
- const matrix box,
- gmx_wallcycle* wcycle,
- int flags,
- bool useGpuForceReduction)
+void pme_gpu_prepare_computation(gmx_pme_t* pme,
+ const matrix box,
+ gmx_wallcycle* wcycle,
+ const gmx::StepWorkload& stepWork)
{
GMX_ASSERT(pme_gpu_active(pme), "This should be a GPU run of PME but it is not enabled.");
GMX_ASSERT(pme->nnodes > 0, "");
GMX_ASSERT(pme->nnodes == 1 || pme->ndecompdim > 0, "");
- PmeGpu* pmeGpu = pme->gpu;
- pmeGpu->settings.currentFlags = flags;
+ PmeGpu* pmeGpu = pme->gpu;
// TODO these flags are only here to honor the CPU PME code, and probably should be removed
- pmeGpu->settings.useGpuForceReduction = useGpuForceReduction;
+ pmeGpu->settings.useGpuForceReduction = stepWork.useGpuPmeFReduction;
bool shouldUpdateBox = false;
for (int i = 0; i < DIM; ++i)
}
}
- if (needToUpdateBox || shouldUpdateBox) // || is to make the first computation always update
+ if (stepWork.haveDynamicBox || shouldUpdateBox) // || is to make the first computation always update
{
wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
- if (!pme_gpu_performs_solve(pmeGpu))
+ if (!pme_gpu_settings(pmeGpu).performGPUSolve)
{
// TODO remove code duplication and add test coverage
matrix scaledBox;
const unsigned int gridIndex = 0;
real* fftgrid = pme->fftgrid[gridIndex];
- if (pmeGpu->settings.currentFlags & GMX_PME_SPREAD)
- {
- /* Spread the coefficients on a grid */
- const bool computeSplines = true;
- const bool spreadCharges = true;
- wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
- wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
- pme_gpu_spread(pmeGpu, xReadyOnDevice, gridIndex, fftgrid, computeSplines, spreadCharges);
- wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
- wallcycle_stop(wcycle, ewcLAUNCH_GPU);
- }
+ /* Spread the coefficients on a grid */
+ const bool computeSplines = true;
+ const bool spreadCharges = true;
+ wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
+ wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
+ pme_gpu_spread(pmeGpu, xReadyOnDevice, gridIndex, fftgrid, computeSplines, spreadCharges);
+ wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
+ wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
-void pme_gpu_launch_complex_transforms(gmx_pme_t* pme, gmx_wallcycle* wcycle)
+void pme_gpu_launch_complex_transforms(gmx_pme_t* pme, gmx_wallcycle* wcycle, const gmx::StepWorkload& stepWork)
{
- PmeGpu* pmeGpu = pme->gpu;
- const bool computeEnergyAndVirial = (pmeGpu->settings.currentFlags & GMX_PME_CALC_ENER_VIR) != 0;
- const bool performBackFFT = (pmeGpu->settings.currentFlags & (GMX_PME_CALC_F | GMX_PME_CALC_POT)) != 0;
+ PmeGpu* pmeGpu = pme->gpu;
+ const auto& settings = pmeGpu->settings;
const unsigned int gridIndex = 0;
t_complex* cfftgrid = pme->cfftgrid[gridIndex];
-
- if (pmeGpu->settings.currentFlags & GMX_PME_SPREAD)
+ // There's no support for computing energy without virial, or vice versa
+ const bool computeEnergyAndVirial = stepWork.computeEnergy || stepWork.computeVirial;
+ if (!settings.performGPUFFT)
{
- if (!pme_gpu_performs_FFT(pmeGpu))
- {
- wallcycle_start(wcycle, ewcWAIT_GPU_PME_SPREAD);
- pme_gpu_sync_spread_grid(pme->gpu);
- wallcycle_stop(wcycle, ewcWAIT_GPU_PME_SPREAD);
- }
+ wallcycle_start(wcycle, ewcWAIT_GPU_PME_SPREAD);
+ pme_gpu_sync_spread_grid(pme->gpu);
+ wallcycle_stop(wcycle, ewcWAIT_GPU_PME_SPREAD);
}
try
{
- if (pmeGpu->settings.currentFlags & GMX_PME_SOLVE)
- {
- /* do R2C 3D-FFT */
- parallel_3dfft_execute_gpu_wrapper(pme, gridIndex, GMX_FFT_REAL_TO_COMPLEX, wcycle);
+ /* do R2C 3D-FFT */
+ parallel_3dfft_execute_gpu_wrapper(pme, gridIndex, GMX_FFT_REAL_TO_COMPLEX, wcycle);
- /* solve in k-space for our local cells */
- if (pme_gpu_performs_solve(pmeGpu))
- {
- const auto gridOrdering = pme_gpu_uses_dd(pmeGpu) ? GridOrdering::YZX : GridOrdering::XYZ;
- wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
- wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
- pme_gpu_solve(pmeGpu, cfftgrid, gridOrdering, computeEnergyAndVirial);
- wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
- wallcycle_stop(wcycle, ewcLAUNCH_GPU);
- }
- else
- {
- wallcycle_start(wcycle, ewcPME_SOLVE_MIXED_MODE);
+ /* solve in k-space for our local cells */
+ if (settings.performGPUSolve)
+ {
+ // TODO grid ordering should be set up at pme init time.
+ const auto gridOrdering = settings.useDecomposition ? GridOrdering::YZX : GridOrdering::XYZ;
+ wallcycle_start_nocount(wcycle, ewcLAUNCH_GPU);
+ wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
+ pme_gpu_solve(pmeGpu, cfftgrid, gridOrdering, computeEnergyAndVirial);
+ wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
+ wallcycle_stop(wcycle, ewcLAUNCH_GPU);
+ }
+ else
+ {
+ wallcycle_start(wcycle, ewcPME_SOLVE_MIXED_MODE);
#pragma omp parallel for num_threads(pme->nthread) schedule(static)
- for (int thread = 0; thread < pme->nthread; thread++)
- {
- solve_pme_yzx(pme, cfftgrid, pme->boxVolume, computeEnergyAndVirial,
- pme->nthread, thread);
- }
- wallcycle_stop(wcycle, ewcPME_SOLVE_MIXED_MODE);
+ for (int thread = 0; thread < pme->nthread; thread++)
+ {
+ solve_pme_yzx(pme, cfftgrid, pme->boxVolume, computeEnergyAndVirial, pme->nthread, thread);
}
+ wallcycle_stop(wcycle, ewcPME_SOLVE_MIXED_MODE);
}
- if (performBackFFT)
- {
- parallel_3dfft_execute_gpu_wrapper(pme, gridIndex, GMX_FFT_COMPLEX_TO_REAL, wcycle);
- }
+ parallel_3dfft_execute_gpu_wrapper(pme, gridIndex, GMX_FFT_COMPLEX_TO_REAL, wcycle);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-void pme_gpu_launch_gather(const gmx_pme_t* pme, gmx_wallcycle gmx_unused* wcycle, PmeForceOutputHandling forceTreatment)
+void pme_gpu_launch_gather(const gmx_pme_t* pme, gmx_wallcycle gmx_unused* wcycle)
{
GMX_ASSERT(pme_gpu_active(pme), "This should be a GPU run of PME but it is not enabled.");
- if (!pme_gpu_performs_gather(pme->gpu))
+ if (!pme_gpu_settings(pme->gpu).performGPUGather)
{
return;
}
wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_PME);
const unsigned int gridIndex = 0;
real* fftgrid = pme->fftgrid[gridIndex];
- pme_gpu_gather(pme->gpu, forceTreatment, reinterpret_cast<float*>(fftgrid));
+ pme_gpu_gather(pme->gpu, reinterpret_cast<float*>(fftgrid));
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_PME);
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
}
//! Reduce quantities from \c output to \c forceWithVirial and \c enerd.
-static void pme_gpu_reduce_outputs(const int flags,
+static void pme_gpu_reduce_outputs(const bool computeEnergyAndVirial,
const PmeOutput& output,
gmx_wallcycle* wcycle,
gmx::ForceWithVirial* forceWithVirial,
wallcycle_start(wcycle, ewcPME_GPU_F_REDUCTION);
GMX_ASSERT(forceWithVirial, "Invalid force pointer");
- const bool haveComputedEnergyAndVirial = (flags & GMX_PME_CALC_ENER_VIR) != 0;
- if (haveComputedEnergyAndVirial)
+ if (computeEnergyAndVirial)
{
GMX_ASSERT(enerd, "Invalid energy output manager");
forceWithVirial->addVirialContribution(output.coulombVirial_);
wallcycle_stop(wcycle, ewcPME_GPU_F_REDUCTION);
}
-bool pme_gpu_try_finish_task(gmx_pme_t* pme,
- const int flags,
- gmx_wallcycle* wcycle,
- gmx::ForceWithVirial* forceWithVirial,
- gmx_enerdata_t* enerd,
- GpuTaskCompletion completionKind)
+bool pme_gpu_try_finish_task(gmx_pme_t* pme,
+ const gmx::StepWorkload& stepWork,
+ gmx_wallcycle* wcycle,
+ gmx::ForceWithVirial* forceWithVirial,
+ gmx_enerdata_t* enerd,
+ GpuTaskCompletion completionKind)
{
GMX_ASSERT(pme_gpu_active(pme), "This should be a GPU run of PME but it is not enabled.");
GMX_ASSERT(!pme->gpu->settings.useGpuForceReduction,
pme_gpu_synchronize(pme->gpu);
}
pme_gpu_update_timings(pme->gpu);
- PmeOutput output = pme_gpu_getOutput(*pme, flags);
+ // There's no support for computing energy without virial, or vice versa
+ const bool computeEnergyAndVirial = stepWork.computeEnergy || stepWork.computeVirial;
+ PmeOutput output = pme_gpu_getOutput(*pme, computeEnergyAndVirial);
wallcycle_stop(wcycle, ewcWAIT_GPU_PME_GATHER);
GMX_ASSERT(pme->gpu->settings.useGpuForceReduction == !output.haveForceOutput_,
"When forces are reduced on the CPU, there needs to be force output");
- pme_gpu_reduce_outputs(flags, output, wcycle, forceWithVirial, enerd);
+ pme_gpu_reduce_outputs(computeEnergyAndVirial, output, wcycle, forceWithVirial, enerd);
return true;
}
// This is used by PME-only ranks
-PmeOutput pme_gpu_wait_finish_task(gmx_pme_t* pme, const int flags, gmx_wallcycle* wcycle)
+PmeOutput pme_gpu_wait_finish_task(gmx_pme_t* pme, const bool computeEnergyAndVirial, gmx_wallcycle* wcycle)
{
GMX_ASSERT(pme_gpu_active(pme), "This should be a GPU run of PME but it is not enabled.");
// Synchronize the whole PME stream at once, including D2H result transfers
// if there are outputs we need to wait for at this step; we still call getOutputs
// for uniformity and because it sets the PmeOutput.haveForceOutput_.
- const bool haveComputedEnergyAndVirial = (flags & GMX_PME_CALC_ENER_VIR) != 0;
- if (!pme->gpu->settings.useGpuForceReduction || haveComputedEnergyAndVirial)
+ if (!pme->gpu->settings.useGpuForceReduction || computeEnergyAndVirial)
{
pme_gpu_synchronize(pme->gpu);
}
- PmeOutput output = pme_gpu_getOutput(*pme, flags);
+ PmeOutput output = pme_gpu_getOutput(*pme, computeEnergyAndVirial);
wallcycle_stop(wcycle, ewcWAIT_GPU_PME_GATHER);
return output;
}
// This is used when not using the alternate-waiting reduction
-void pme_gpu_wait_and_reduce(gmx_pme_t* pme,
- const int flags,
- gmx_wallcycle* wcycle,
- gmx::ForceWithVirial* forceWithVirial,
- gmx_enerdata_t* enerd)
+void pme_gpu_wait_and_reduce(gmx_pme_t* pme,
+ const gmx::StepWorkload& stepWork,
+ gmx_wallcycle* wcycle,
+ gmx::ForceWithVirial* forceWithVirial,
+ gmx_enerdata_t* enerd)
{
- PmeOutput output = pme_gpu_wait_finish_task(pme, flags, wcycle);
+ // There's no support for computing energy without virial, or vice versa
+ const bool computeEnergyAndVirial = stepWork.computeEnergy || stepWork.computeVirial;
+ PmeOutput output = pme_gpu_wait_finish_task(pme, computeEnergyAndVirial, wcycle);
GMX_ASSERT(pme->gpu->settings.useGpuForceReduction == !output.haveForceOutput_,
"When forces are reduced on the CPU, there needs to be force output");
- pme_gpu_reduce_outputs(flags, output, wcycle, forceWithVirial, enerd);
+ pme_gpu_reduce_outputs(computeEnergyAndVirial, output, wcycle, forceWithVirial, enerd);
}
void pme_gpu_reinit_computation(const gmx_pme_t* pme, gmx_wallcycle* wcycle)
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
-DeviceBuffer<float> pme_gpu_get_device_x(const gmx_pme_t* pme)
-{
- GMX_ASSERT((pme && pme_gpu_active(pme)),
- "PME GPU coordinates buffer was requested from uninitialized PME module");
- return pme_gpu_get_kernelparam_coordinates(pme->gpu);
-}
-
void* pme_gpu_get_device_f(const gmx_pme_t* pme)
{
if (!pme || !pme_gpu_active(pme))
return pme_gpu_get_kernelparam_forces(pme->gpu);
}
-void pme_gpu_set_device_x(const gmx_pme_t* pme, DeviceBuffer<float> d_x)
+void pme_gpu_set_device_x(const gmx_pme_t* pme, DeviceBuffer<gmx::RVec> d_x)
{
GMX_ASSERT(pme != nullptr, "Null pointer is passed as a PME to the set coordinates function.");
GMX_ASSERT(pme_gpu_active(pme), "This should be a GPU run of PME but it is not enabled.");
pme_gpu_set_kernelparam_coordinates(pme->gpu, d_x);
}
-void* pme_gpu_get_device_stream(const gmx_pme_t* pme)
-{
- if (!pme || !pme_gpu_active(pme))
- {
- return nullptr;
- }
- return pme_gpu_get_stream(pme->gpu);
-}
-
-void* pme_gpu_get_device_context(const gmx_pme_t* pme)
-{
- if (!pme || !pme_gpu_active(pme))
- {
- return nullptr;
- }
- return pme_gpu_get_context(pme->gpu);
-}
-
GpuEventSynchronizer* pme_gpu_get_f_ready_synchronizer(const gmx_pme_t* pme)
{
if (!pme || !pme_gpu_active(pme))
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
complexGridSizePadded[i] = kernelParamsPtr->grid.complexGridSizePadded[i];
}
- GMX_RELEASE_ASSERT(!pme_gpu_uses_dd(pmeGpu), "FFT decomposition not implemented");
+ GMX_RELEASE_ASSERT(!pme_gpu_settings(pmeGpu).useDecomposition,
+ "FFT decomposition not implemented");
const int complexGridSizePaddedTotal =
complexGridSizePadded[XX] * complexGridSizePadded[YY] * complexGridSizePadded[ZZ];
realGridSizePaddedTotal, CUFFT_C2R, batch);
handleCufftError(result, "cufftPlanMany C2R plan failure");
- cudaStream_t stream = pmeGpu->archSpecific->pmeStream;
+ cudaStream_t stream = pmeGpu->archSpecific->pmeStream_.stream();
GMX_RELEASE_ASSERT(stream, "Using the default CUDA stream for PME cuFFT");
result = cufftSetStream(planR2C_, stream);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#elif GMX_GPU == GMX_GPU_OPENCL
clfftPlanHandle planR2C_;
clfftPlanHandle planC2R_;
- std::vector<cl_command_queue> commandStreams_;
+ std::vector<cl_command_queue> deviceStreams_;
cl_mem realGrid_;
cl_mem complexGrid_;
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Extracting all the data from PME GPU
std::array<size_t, DIM> realGridSize, realGridSizePadded, complexGridSizePadded;
- GMX_RELEASE_ASSERT(!pme_gpu_uses_dd(pmeGpu), "FFT decomposition not implemented");
+ GMX_RELEASE_ASSERT(!pme_gpu_settings(pmeGpu).useDecomposition,
+ "FFT decomposition not implemented");
PmeGpuKernelParamsBase* kernelParamsPtr = pmeGpu->kernelParams.get();
for (int i = 0; i < DIM; i++)
{
== kernelParamsPtr->grid.complexGridSize[i],
"Complex padding not implemented");
}
- cl_context context = pmeGpu->archSpecific->context;
- commandStreams_.push_back(pmeGpu->archSpecific->pmeStream);
+ cl_context context = pmeGpu->archSpecific->deviceContext_.context();
+ deviceStreams_.push_back(pmeGpu->archSpecific->pmeStream_.stream());
realGrid_ = kernelParamsPtr->grid.d_realGrid;
complexGrid_ = kernelParamsPtr->grid.d_fourierGrid;
const bool performOutOfPlaceFFT = pmeGpu->archSpecific->performOutOfPlaceFFT;
handleClfftError(clfftSetPlanOutStride(planC2R_, dims, realGridStrides.data()),
"clFFT stride setting failure");
- handleClfftError(clfftBakePlan(planR2C_, commandStreams_.size(), commandStreams_.data(), nullptr, nullptr),
+ handleClfftError(clfftBakePlan(planR2C_, deviceStreams_.size(), deviceStreams_.data(), nullptr, nullptr),
"clFFT precompiling failure");
- handleClfftError(clfftBakePlan(planC2R_, commandStreams_.size(), commandStreams_.data(), nullptr, nullptr),
+ handleClfftError(clfftBakePlan(planC2R_, deviceStreams_.size(), deviceStreams_.data(), nullptr, nullptr),
"clFFT precompiling failure");
// TODO: implement solve kernel as R2C FFT callback
GMX_THROW(
gmx::NotImplementedError("The chosen 3D-FFT case is not implemented on GPUs"));
}
- handleClfftError(clfftEnqueueTransform(plan, direction, commandStreams_.size(),
- commandStreams_.data(), waitEvents.size(), waitEvents.data(),
+ handleClfftError(clfftEnqueueTransform(plan, direction, deviceStreams_.size(),
+ deviceStreams_.data(), waitEvents.size(), waitEvents.data(),
timingEvent, inputGrids, outputGrids, tempBuffer),
"clFFT execution failure");
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#ifndef GMX_EWALD_PME_GPU_UTILS_CLH
-#define GMX_EWALD_PME_GPU_UTILS_CLH
+#ifndef GMX_EWALD_PME_GPU_CALCULATE_SPLINES_CLH
+#define GMX_EWALD_PME_GPU_CALCULATE_SPLINES_CLH
/*! \internal \file
- * \brief This file defines the small PME OpenCL inline device functions.
- * This closely mirrors pme_gpu_utils.h (which is used in CUDA and unit tests), except with no templates.
+ * \brief This file defines the PME OpenCL inline device functions for computing splines.
+ * This closely mirrors pme_gpu_calculate_splines.cuh (which is used in CUDA kernels), except with no templates.
* Instead of templated parameters this file expects following defines during compilation:
* - order - PME interpolation order;
* - atomsPerWarp - number of atoms processed by a warp (fixed for spread and gather kernels to be the same);
- * - c_usePadding and c_skipNeutralAtoms - same as in pme_gpu_constants.h.
+ * - c_skipNeutralAtoms - same as in pme_gpu_constants.h.
*
* \author Aleksei Iupinov <a.yupinov@gmail.com>
* \ingroup module_ewald
* \param[in] paramIndexBase Must be result of getSplineParamIndexBase().
* \param[in] dimIndex Dimension index (from 0 to 2)
* \param[in] splineIndex Spline contribution index (from 0 to \p order - 1)
- * \param[in] order PME order
- * \param[in] atomsPerWarp Number of atoms processed by a warp
*
* \returns Index into theta or dtheta array using GPU layout.
*/
return (paramIndexBase + (splineIndex * DIM + dimIndex) * atomsPerWarp);
}
-/*! \brief
- * A function for checking the global atom data indices against the atom data array sizes.
- *
- * \param[in] atomDataIndexGlobal The atom data index.
- * \param[in] nAtomData The atom data array element count.
- * \returns Non-0 if index is within bounds (or PME data padding is enabled), 0 otherwise.
- *
- * This is called from the spline_and_spread and gather PME kernels.
- * The goal is to isolate the global range checks, and allow avoiding them with c_usePadding being true.
- */
-inline int pme_gpu_check_atom_data_index(const size_t atomDataIndex, const size_t nAtomData)
-{
- return c_usePadding ? 1 : (atomDataIndex < nAtomData);
-}
-
/*! \brief
* A function for optionally skipping neutral charges, depending on c_skipNeutralAtoms.
*
*/
inline int pme_gpu_check_atom_charge(const float coefficient)
{
- return c_skipNeutralAtoms ? (coefficient != 0.0f) : 1;
+ assert(isfinite(coefficient));
+ return c_skipNeutralAtoms ? (coefficient != 0.0F) : 1;
}
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/cuda_kernel_utils.cuh"
#include "pme.cuh"
-#include "pme_gpu_utils.h"
#include "pme_grid.h"
+/*! \internal \brief
+ * Gets a base of the unique index to an element in a spline parameter buffer (theta/dtheta),
+ * which is laid out for GPU spread/gather kernels. The base only corresponds to the atom index within the execution block.
+ * Feed the result into getSplineParamIndex() to get a full index.
+ * TODO: it's likely that both parameters can be just replaced with a single atom index, as they are derived from it.
+ * Do that, verifying that the generated code is not bloated, and/or revise the spline indexing scheme.
+ * Removing warp dependency would also be nice (and would probably coincide with removing c_pmeSpreadGatherAtomsPerWarp).
+ *
+ * \tparam order PME order
+ * \tparam atomsPerWarp Number of atoms processed by a warp
+ * \param[in] warpIndex Warp index wrt the block.
+ * \param[in] atomWarpIndex Atom index wrt the warp (from 0 to atomsPerWarp - 1).
+ *
+ * \returns Index into theta or dtheta array using GPU layout.
+ */
+template<int order, int atomsPerWarp>
+int __device__ __forceinline__ getSplineParamIndexBase(int warpIndex, int atomWarpIndex)
+{
+ assert((atomWarpIndex >= 0) && (atomWarpIndex < atomsPerWarp));
+ const int dimIndex = 0;
+ const int splineIndex = 0;
+ // The zeroes are here to preserve the full index formula for reference
+ return (((splineIndex + order * warpIndex) * DIM + dimIndex) * atomsPerWarp + atomWarpIndex);
+}
+
+/*! \internal \brief
+ * Gets a unique index to an element in a spline parameter buffer (theta/dtheta),
+ * which is laid out for GPU spread/gather kernels. The index is wrt to the execution block,
+ * in range(0, atomsPerBlock * order * DIM).
+ * This function consumes result of getSplineParamIndexBase() and adjusts it for \p dimIndex and \p splineIndex.
+ *
+ * \tparam order PME order
+ * \tparam atomsPerWarp Number of atoms processed by a warp
+ * \param[in] paramIndexBase Must be result of getSplineParamIndexBase().
+ * \param[in] dimIndex Dimension index (from 0 to 2)
+ * \param[in] splineIndex Spline contribution index (from 0 to \p order - 1)
+ *
+ * \returns Index into theta or dtheta array using GPU layout.
+ */
+template<int order, int atomsPerWarp>
+int __device__ __forceinline__ getSplineParamIndex(int paramIndexBase, int dimIndex, int splineIndex)
+{
+ assert((dimIndex >= XX) && (dimIndex < DIM));
+ assert((splineIndex >= 0) && (splineIndex < order));
+ return (paramIndexBase + (splineIndex * DIM + dimIndex) * atomsPerWarp);
+}
+
+/*! \internal \brief
+ * An inline CUDA function for skipping the zero-charge atoms.
+ *
+ * \returns Non-0 if atom should be processed, 0 otherwise.
+ * \param[in] coefficient The atom charge.
+ *
+ * This is called from the spline_and_spread and gather PME kernels.
+ */
+int __device__ __forceinline__ pme_gpu_check_atom_charge(const float coefficient)
+{
+ assert(isfinite(coefficient));
+ return c_skipNeutralAtoms ? (coefficient != 0.0f) : 1;
+}
+
//! Controls if the atom and charge data is prefeched into shared memory or loaded per thread from global
static const bool c_useAtomDataPrefetch = true;
+/*! \brief Asserts if the argument is finite.
+ *
+ * The function works for any data type, that can be casted to float. Note that there is also
+ * a specialized implementation for float3 data type.
+ *
+ * \param[in] arg Argument to check.
+ */
+template<typename T>
+__device__ inline void assertIsFinite(T arg);
+
+template<>
+__device__ inline void assertIsFinite(float3 arg)
+{
+ assert(isfinite(float(arg.x)));
+ assert(isfinite(float(arg.y)));
+ assert(isfinite(float(arg.z)));
+}
+
+template<typename T>
+__device__ inline void assertIsFinite(T arg)
+{
+ assert(isfinite(float(arg)));
+}
+
/*! \brief
* General purpose function for loading atom-related data from global to shared memory.
*
* \tparam[in] T Data type (float/int/...)
- * \tparam[in] atomsPerBlock Number of atoms processed by a block - should be accounted for in the size of the shared memory array.
- * \tparam[in] dataCountPerAtom Number of data elements per single atom (e.g. DIM for an rvec coordinates array).
- * \param[in] kernelParams Input PME CUDA data in constant memory.
+ * \tparam[in] atomsPerBlock Number of atoms processed by a block - should be
+ * accounted for in the size of the shared memory array.
+ * \tparam[in] dataCountPerAtom Number of data elements per single atom (e.g. DIM for
+ * an rvec coordinates array).
* \param[out] sm_destination Shared memory array for output.
* \param[in] gm_source Global memory array for input.
*/
-template<typename T, const int atomsPerBlock, const int dataCountPerAtom>
-__device__ __forceinline__ void pme_gpu_stage_atom_data(const PmeGpuCudaKernelParams kernelParams,
- T* __restrict__ sm_destination,
+template<typename T, int atomsPerBlock, int dataCountPerAtom>
+__device__ __forceinline__ void pme_gpu_stage_atom_data(T* __restrict__ sm_destination,
const T* __restrict__ gm_source)
{
- static_assert(c_usePadding,
- "With padding disabled, index checking should be fixed to account for spline "
- "theta/dtheta pr-warp alignment");
const int blockIndex = blockIdx.y * gridDim.x + blockIdx.x;
const int threadLocalIndex = ((threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x) + threadIdx.x;
const int localIndex = threadLocalIndex;
const int globalIndexBase = blockIndex * atomsPerBlock * dataCountPerAtom;
const int globalIndex = globalIndexBase + localIndex;
- const int globalCheck =
- pme_gpu_check_atom_data_index(globalIndex, kernelParams.atoms.nAtoms * dataCountPerAtom);
- if ((localIndex < atomsPerBlock * dataCountPerAtom) & globalCheck)
+ if (localIndex < atomsPerBlock * dataCountPerAtom)
{
- assert(isfinite(float(gm_source[globalIndex])));
+ assertIsFinite(gm_source[globalIndex]);
sm_destination[localIndex] = gm_source[globalIndex];
}
}
* \param[out] sm_gridlineIndices Atom gridline indices in the shared memory.
*/
-template<const int order, const int atomsPerBlock, const int atomsPerWarp, const bool writeSmDtheta, const bool writeGlobal>
+template<int order, int atomsPerBlock, int atomsPerWarp, bool writeSmDtheta, bool writeGlobal>
__device__ __forceinline__ void calculate_splines(const PmeGpuCudaKernelParams kernelParams,
const int atomIndexOffset,
const float3 atomX,
/* Atom index w.r.t. block/shared memory */
const int atomIndexLocal = warpIndex * atomsPerWarp + atomWarpIndex;
- /* Atom index w.r.t. global memory */
- const int atomIndexGlobal = atomIndexOffset + atomIndexLocal;
/* Spline contribution index in one dimension */
const int threadLocalIdXY = (threadIdx.y * blockDim.x) + threadIdx.x;
const int orderIndex = threadLocalIdXY / DIM;
float splineData[order];
const int localCheck = (dimIndex < DIM) && (orderIndex < 1);
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
/* we have 4 threads per atom, but can only use 3 here for the dimensions */
- if (localCheck && globalCheck)
+ if (localCheck)
{
/* Indices interpolation */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \ingroup module_ewald
*/
-#include "config.h"
-
#include <cassert>
-#include "pme_gpu_constants.h"
+#include "gromacs/math/vectypes.h"
-//! A macro for inline GPU functions.
-#if GMX_GPU == GMX_GPU_CUDA
-# define INLINE_EVERYWHERE __host__ __device__ __forceinline__
-#else
-# define INLINE_EVERYWHERE inline
-#endif
+struct PmeGpu;
/*! \internal \brief
* Gets a base of the unique index to an element in a spline parameter buffer (theta/dtheta),
* \returns Index into theta or dtheta array using GPU layout.
*/
template<int order, int atomsPerWarp>
-int INLINE_EVERYWHERE getSplineParamIndexBase(int warpIndex, int atomWarpIndex)
+int inline getSplineParamIndexBase(int warpIndex, int atomWarpIndex)
{
assert((atomWarpIndex >= 0) && (atomWarpIndex < atomsPerWarp));
const int dimIndex = 0;
* \returns Index into theta or dtheta array using GPU layout.
*/
template<int order, int atomsPerWarp>
-int INLINE_EVERYWHERE getSplineParamIndex(int paramIndexBase, int dimIndex, int splineIndex)
+int inline getSplineParamIndex(int paramIndexBase, int dimIndex, int splineIndex)
{
assert((dimIndex >= XX) && (dimIndex < DIM));
assert((splineIndex >= 0) && (splineIndex < order));
return (paramIndexBase + (splineIndex * DIM + dimIndex) * atomsPerWarp);
}
-#if GMX_GPU == GMX_GPU_CUDA
-// CUDA device code helpers below
-
-/*! \internal \brief
- * An inline CUDA function for checking the global atom data indices against the atom data array sizes.
- *
- * \param[in] atomDataIndex The atom data index.
- * \param[in] nAtomData The atom data array element count.
- * \returns Non-0 if index is within bounds (or PME data padding is enabled), 0 otherwise.
- *
- * This is called from the spline_and_spread and gather PME kernels.
- * The goal is to isolate the global range checks, and allow avoiding them with c_usePadding enabled.
- */
-int __device__ __forceinline__ pme_gpu_check_atom_data_index(const int atomDataIndex, const int nAtomData)
-{
- return c_usePadding ? 1 : (atomDataIndex < nAtomData);
-}
-
-/*! \internal \brief
- * An inline CUDA function for skipping the zero-charge atoms.
- *
- * \returns Non-0 if atom should be processed, 0 otherwise.
- * \param[in] coefficient The atom charge.
- *
- * This is called from the spline_and_spread and gather PME kernels.
- */
-int __device__ __forceinline__ pme_gpu_check_atom_charge(const float coefficient)
-{
- assert(isfinite(coefficient));
- return c_skipNeutralAtoms ? (coefficient != 0.0f) : 1;
-}
-
-#endif
-
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \todo The values are currently common to both CUDA and OpenCL
* implementations, but should be reconsidered when we tune the OpenCL
- * implementation. See Redmine #2528.
+ * implementation. See Issue #2528.
*
* \author Aleksei Iupinov <a.yupinov@gmail.com>
* \ingroup module_ewald
/* General settings for PME GPU behaviour */
-/*! \brief
- * false: The atom data GPU buffers are sized precisely according to the number of atoms.
- * (Except GPU spline data layout which is regardless intertwined for 2 atoms per warp).
- * The atom index checks in the spread/gather code potentially hinder the performance.
- * true: The atom data GPU buffers are padded with zeroes so that the possible number of atoms
- * fitting in is divisible by c_pmeAtomDataAlignment.
- * The atom index checks are not performed. There should be a performance win, but how big is it, remains to be seen.
- * Additional cudaMemsetAsync calls are done occasionally (only charges/coordinates; spline data is always recalculated now).
- * \todo Estimate performance differences
- */
-constexpr bool c_usePadding = true;
-
/*! \brief
* false: Atoms with zero charges are processed by PME. Could introduce some overhead.
* true: Atoms with zero charges are not processed by PME. Adds branching to the spread/gather.
*/
constexpr int c_pmeGpuOrder = 4;
-/*! \brief
- * The number of GPU threads used for computing spread/gather contributions of a single atom as function of the PME order.
- * The assumption is currently that any thread processes only a single atom's contributions.
- * TODO: this assumption leads to minimum execution width of 16. See Redmine #2516
- */
-constexpr int c_pmeSpreadGatherThreadsPerAtom = c_pmeGpuOrder * c_pmeGpuOrder;
-
-//! Number of threads per atom when order threads are used
-constexpr int c_pmeSpreadGatherThreadsPerAtom4ThPerAtom = c_pmeGpuOrder;
-
-/*! \brief Minimum execution width of the PME spread and gather kernels.
+/*! \brief The number of GPU threads used for computing spread/gather
+ * contributions of a single atom, which relates to the PME order.
*
- * Due to the one thread per atom and order=4 implementation constraints, order^2 threads
- * should execute without synchronization needed. See c_pmeSpreadGatherThreadsPerAtom
- */
-constexpr int c_pmeSpreadGatherMinWarpSize = c_pmeSpreadGatherThreadsPerAtom;
-
-//! Minimum warp size if order threads pera atom are used instead of order^2
-constexpr int c_pmeSpreadGatherMinWarpSize4ThPerAtom = c_pmeSpreadGatherThreadsPerAtom4ThPerAtom;
-
-/*! \brief
- * Atom data alignment (in terms of number of atoms).
- * This is the least common multiple of number of atoms processed by
- * a single block/workgroup of the spread and gather kernels.
- * If the GPU atom data buffers are padded (c_usePadding == true),
- * Then the numbers of atoms which would fit in the padded GPU buffers have to be divisible by this.
- * There are debug asserts for this divisibility in pme_gpu_spread() and pme_gpu_gather().
+ * TODO: this assumption leads to minimum execution width of 16. See Issue #2516
*/
-constexpr int c_pmeAtomDataAlignment = 64;
+enum class ThreadsPerAtom : int
+{
+ /*! \brief Use a number of threads equal to the PME order (ie. 4)
+ *
+ * Only CUDA implements this. See Issue #2516 */
+ Order,
+ //! Use a number of threads equal to the square of the PME order (ie. 16)
+ OrderSquared,
+ //! Size of the enumeration
+ Count
+};
/*
* The execution widths for PME GPU kernels, used both on host and device for correct scheduling.
* TODO: those were tuned for CUDA with assumption of warp size 32; specialize those for OpenCL
- * (Redmine #2528).
+ * (Issue #2528).
* As noted below, these are very approximate maximum sizes; in run time we might have to use
* smaller block/workgroup sizes, depending on device capabilities.
*/
//! Gathering max block width in warps - picked empirically among 2, 4, 8, 16 for max. occupancy and min. runtime
constexpr int c_gatherMaxWarpsPerBlock = 4;
-
#if GMX_GPU == GMX_GPU_CUDA
-
-/* All the guys below are dependent on warp_size and should ideally be removed from the host-side code,
- * as we have to do that for OpenCL already.
- * They also express maximum desired block/workgroup sizes, while both with CUDA and OpenCL we have to treat
- * the device runtime limitations gracefully as well.
- */
-
-/*! \brief
- * The number of atoms processed by a single warp in spread/gather.
- * This macro depends on the templated order parameter (2 atoms per warp for order 4 and warp_size
- * of 32). It is mostly used for spline data layout tweaked for coalesced access.
+/* All the fields below are dependent on warp_size and should
+ * ideally be removed from the device-side code, as we have to
+ * do that for OpenCL already.
+ *
+ * They also express maximum desired block/workgroup sizes,
+ * while both with CUDA and OpenCL we have to treat the device
+ * runtime limitations gracefully as well.
*/
-constexpr int c_pmeSpreadGatherAtomsPerWarp = (warp_size / c_pmeSpreadGatherThreadsPerAtom);
-
-//! number of atoms per warp when order threads are used per atom
-constexpr int c_pmeSpreadGatherAtomsPerWarp4ThPerAtom =
- (warp_size / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom);
//! Spreading max block size in threads
-constexpr int c_spreadMaxThreadsPerBlock = c_spreadMaxWarpsPerBlock * warp_size;
+static constexpr int c_spreadMaxThreadsPerBlock = c_spreadMaxWarpsPerBlock * warp_size;
//! Solving kernel max block size in threads
-constexpr int c_solveMaxThreadsPerBlock = (c_solveMaxWarpsPerBlock * warp_size);
+static constexpr int c_solveMaxThreadsPerBlock = c_solveMaxWarpsPerBlock * warp_size;
//! Gathering max block size in threads
-constexpr int c_gatherMaxThreadsPerBlock = c_gatherMaxWarpsPerBlock * warp_size;
+static constexpr int c_gatherMaxThreadsPerBlock = c_gatherMaxWarpsPerBlock * warp_size;
//! Gathering min blocks per CUDA multiprocessor
-constexpr int c_gatherMinBlocksPerMP = GMX_CUDA_MAX_THREADS_PER_MP / c_gatherMaxThreadsPerBlock;
+static constexpr int c_gatherMinBlocksPerMP = GMX_CUDA_MAX_THREADS_PER_MP / c_gatherMaxThreadsPerBlock;
#endif // GMX_GPU == GMX_GPU_CUDA
#include <string>
#include "gromacs/ewald/ewald_utils.h"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/units.h"
#include "gromacs/ewald/pme.h"
#include "pme_gpu_3dfft.h"
+#include "pme_gpu_calculate_splines.h"
#include "pme_gpu_constants.h"
#include "pme_gpu_program_impl.h"
#include "pme_gpu_timings.h"
#include "pme_gpu_types.h"
#include "pme_gpu_types_host.h"
#include "pme_gpu_types_host_impl.h"
-#include "pme_gpu_utils.h"
#include "pme_grid.h"
#include "pme_internal.h"
#include "pme_solve.h"
return kernelParamsPtr;
}
-int pme_gpu_get_atom_data_alignment(const PmeGpu* /*unused*/)
-{
- // TODO: this can be simplified, as c_pmeAtomDataAlignment is now constant
- if (c_usePadding)
- {
- return c_pmeAtomDataAlignment;
- }
- else
- {
- return 0;
- }
-}
+/*! \brief
+ * Atom data block size (in terms of number of atoms).
+ * This is the least common multiple of number of atoms processed by
+ * a single block/workgroup of the spread and gather kernels.
+ * The GPU atom data buffers must be padded, which means that
+ * the numbers of atoms used for determining the size of the memory
+ * allocation must be divisible by this.
+ */
+constexpr int c_pmeAtomDataBlockSize = 64;
-int pme_gpu_get_atoms_per_warp(const PmeGpu* pmeGpu)
+int pme_gpu_get_atom_data_block_size()
{
- if (pmeGpu->settings.useOrderThreadsPerAtom)
- {
- return pmeGpu->programHandle_->impl_->warpSize / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom;
- }
- else
- {
- return pmeGpu->programHandle_->impl_->warpSize / c_pmeSpreadGatherThreadsPerAtom;
- }
+ return c_pmeAtomDataBlockSize;
}
void pme_gpu_synchronize(const PmeGpu* pmeGpu)
{
- gpuStreamSynchronize(pmeGpu->archSpecific->pmeStream);
+ pmeGpu->archSpecific->pmeStream_.synchronize();
}
void pme_gpu_alloc_energy_virial(PmeGpu* pmeGpu)
{
const size_t energyAndVirialSize = c_virialAndEnergyCount * sizeof(float);
allocateDeviceBuffer(&pmeGpu->kernelParams->constants.d_virialAndEnergy, c_virialAndEnergyCount,
- pmeGpu->archSpecific->context);
+ pmeGpu->archSpecific->deviceContext_);
pmalloc(reinterpret_cast<void**>(&pmeGpu->staging.h_virialAndEnergy), energyAndVirialSize);
}
void pme_gpu_clear_energy_virial(const PmeGpu* pmeGpu)
{
clearDeviceBufferAsync(&pmeGpu->kernelParams->constants.d_virialAndEnergy, 0,
- c_virialAndEnergyCount, pmeGpu->archSpecific->pmeStream);
+ c_virialAndEnergyCount, pmeGpu->archSpecific->pmeStream_);
}
void pme_gpu_realloc_and_copy_bspline_values(PmeGpu* pmeGpu)
const bool shouldRealloc = (newSplineValuesSize > pmeGpu->archSpecific->splineValuesSize);
reallocateDeviceBuffer(&pmeGpu->kernelParams->grid.d_splineModuli, newSplineValuesSize,
&pmeGpu->archSpecific->splineValuesSize,
- &pmeGpu->archSpecific->splineValuesSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->splineValuesSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
if (shouldRealloc)
{
/* Reallocate the host buffer */
}
/* TODO: pin original buffer instead! */
copyToDeviceBuffer(&pmeGpu->kernelParams->grid.d_splineModuli, pmeGpu->staging.h_splineModuli,
- 0, newSplineValuesSize, pmeGpu->archSpecific->pmeStream,
+ 0, newSplineValuesSize, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
const size_t newForcesSize = pmeGpu->nAtomsAlloc * DIM;
GMX_ASSERT(newForcesSize > 0, "Bad number of atoms in PME GPU");
reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_forces, newForcesSize,
- &pmeGpu->archSpecific->forcesSize,
- &pmeGpu->archSpecific->forcesSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->forcesSize, &pmeGpu->archSpecific->forcesSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
pmeGpu->staging.h_forces.reserveWithPadding(pmeGpu->nAtomsAlloc);
pmeGpu->staging.h_forces.resizeWithPadding(pmeGpu->kernelParams->atoms.nAtoms);
}
GMX_ASSERT(pmeGpu->kernelParams->atoms.nAtoms > 0, "Bad number of atoms in PME GPU");
float* h_forcesFloat = reinterpret_cast<float*>(pmeGpu->staging.h_forces.data());
copyToDeviceBuffer(&pmeGpu->kernelParams->atoms.d_forces, h_forcesFloat, 0,
- DIM * pmeGpu->kernelParams->atoms.nAtoms, pmeGpu->archSpecific->pmeStream,
+ DIM * pmeGpu->kernelParams->atoms.nAtoms, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
GMX_ASSERT(pmeGpu->kernelParams->atoms.nAtoms > 0, "Bad number of atoms in PME GPU");
float* h_forcesFloat = reinterpret_cast<float*>(pmeGpu->staging.h_forces.data());
copyFromDeviceBuffer(h_forcesFloat, &pmeGpu->kernelParams->atoms.d_forces, 0,
- DIM * pmeGpu->kernelParams->atoms.nAtoms, pmeGpu->archSpecific->pmeStream,
+ DIM * pmeGpu->kernelParams->atoms.nAtoms, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
-void pme_gpu_realloc_coordinates(const PmeGpu* pmeGpu)
-{
- const size_t newCoordinatesSize = pmeGpu->nAtomsAlloc * DIM;
- GMX_ASSERT(newCoordinatesSize > 0, "Bad number of atoms in PME GPU");
- reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_coordinates, newCoordinatesSize,
- &pmeGpu->archSpecific->coordinatesSize,
- &pmeGpu->archSpecific->coordinatesSizeAlloc, pmeGpu->archSpecific->context);
- if (c_usePadding)
- {
- const size_t paddingIndex = DIM * pmeGpu->kernelParams->atoms.nAtoms;
- const size_t paddingCount = DIM * pmeGpu->nAtomsAlloc - paddingIndex;
- if (paddingCount > 0)
- {
- clearDeviceBufferAsync(&pmeGpu->kernelParams->atoms.d_coordinates, paddingIndex,
- paddingCount, pmeGpu->archSpecific->pmeStream);
- }
- }
-}
-
-void pme_gpu_free_coordinates(const PmeGpu* pmeGpu)
-{
- freeDeviceBuffer(&pmeGpu->kernelParams->atoms.d_coordinates);
-}
-
-void pme_gpu_realloc_and_copy_input_coefficients(const PmeGpu* pmeGpu, const float* h_coefficients)
+void pme_gpu_realloc_and_copy_input_coefficients(PmeGpu* pmeGpu, const float* h_coefficients)
{
GMX_ASSERT(h_coefficients, "Bad host-side charge buffer in PME GPU");
const size_t newCoefficientsSize = pmeGpu->nAtomsAlloc;
GMX_ASSERT(newCoefficientsSize > 0, "Bad number of atoms in PME GPU");
reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_coefficients, newCoefficientsSize,
&pmeGpu->archSpecific->coefficientsSize,
- &pmeGpu->archSpecific->coefficientsSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->coefficientsSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
copyToDeviceBuffer(&pmeGpu->kernelParams->atoms.d_coefficients,
const_cast<float*>(h_coefficients), 0, pmeGpu->kernelParams->atoms.nAtoms,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
- if (c_usePadding)
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
+
+ const size_t paddingIndex = pmeGpu->kernelParams->atoms.nAtoms;
+ const size_t paddingCount = pmeGpu->nAtomsAlloc - paddingIndex;
+ if (paddingCount > 0)
{
- const size_t paddingIndex = pmeGpu->kernelParams->atoms.nAtoms;
- const size_t paddingCount = pmeGpu->nAtomsAlloc - paddingIndex;
- if (paddingCount > 0)
- {
- clearDeviceBufferAsync(&pmeGpu->kernelParams->atoms.d_coefficients, paddingIndex,
- paddingCount, pmeGpu->archSpecific->pmeStream);
- }
+ clearDeviceBufferAsync(&pmeGpu->kernelParams->atoms.d_coefficients, paddingIndex,
+ paddingCount, pmeGpu->archSpecific->pmeStream_);
}
}
void pme_gpu_realloc_spline_data(PmeGpu* pmeGpu)
{
- const int order = pmeGpu->common->pme_order;
- const int alignment = pme_gpu_get_atoms_per_warp(pmeGpu);
- const size_t nAtomsPadded = ((pmeGpu->nAtomsAlloc + alignment - 1) / alignment) * alignment;
- const int newSplineDataSize = DIM * order * nAtomsPadded;
+ const int order = pmeGpu->common->pme_order;
+ const int newSplineDataSize = DIM * order * pmeGpu->nAtomsAlloc;
GMX_ASSERT(newSplineDataSize > 0, "Bad number of atoms in PME GPU");
/* Two arrays of the same size */
const bool shouldRealloc = (newSplineDataSize > pmeGpu->archSpecific->splineDataSize);
int currentSizeTemp = pmeGpu->archSpecific->splineDataSize;
int currentSizeTempAlloc = pmeGpu->archSpecific->splineDataSizeAlloc;
- reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_theta, newSplineDataSize,
- ¤tSizeTemp, ¤tSizeTempAlloc, pmeGpu->archSpecific->context);
+ reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_theta, newSplineDataSize, ¤tSizeTemp,
+ ¤tSizeTempAlloc, pmeGpu->archSpecific->deviceContext_);
reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_dtheta, newSplineDataSize,
- &pmeGpu->archSpecific->splineDataSize,
- &pmeGpu->archSpecific->splineDataSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->splineDataSize, &pmeGpu->archSpecific->splineDataSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
// the host side reallocation
if (shouldRealloc)
{
GMX_ASSERT(newIndicesSize > 0, "Bad number of atoms in PME GPU");
reallocateDeviceBuffer(&pmeGpu->kernelParams->atoms.d_gridlineIndices, newIndicesSize,
&pmeGpu->archSpecific->gridlineIndicesSize,
- &pmeGpu->archSpecific->gridlineIndicesSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->gridlineIndicesSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
pfree(pmeGpu->staging.h_gridlineIndices);
pmalloc(reinterpret_cast<void**>(&pmeGpu->staging.h_gridlineIndices), newIndicesSize * sizeof(int));
}
/* 2 separate grids */
reallocateDeviceBuffer(&kernelParamsPtr->grid.d_fourierGrid, newComplexGridSize,
&pmeGpu->archSpecific->complexGridSize,
- &pmeGpu->archSpecific->complexGridSizeAlloc, pmeGpu->archSpecific->context);
- reallocateDeviceBuffer(&kernelParamsPtr->grid.d_realGrid, newRealGridSize,
- &pmeGpu->archSpecific->realGridSize,
- &pmeGpu->archSpecific->realGridSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->complexGridSizeAlloc,
+ pmeGpu->archSpecific->deviceContext_);
+ reallocateDeviceBuffer(
+ &kernelParamsPtr->grid.d_realGrid, newRealGridSize, &pmeGpu->archSpecific->realGridSize,
+ &pmeGpu->archSpecific->realGridSizeAlloc, pmeGpu->archSpecific->deviceContext_);
}
else
{
const int newGridsSize = std::max(newRealGridSize, newComplexGridSize);
reallocateDeviceBuffer(
&kernelParamsPtr->grid.d_realGrid, newGridsSize, &pmeGpu->archSpecific->realGridSize,
- &pmeGpu->archSpecific->realGridSizeAlloc, pmeGpu->archSpecific->context);
+ &pmeGpu->archSpecific->realGridSizeAlloc, pmeGpu->archSpecific->deviceContext_);
kernelParamsPtr->grid.d_fourierGrid = kernelParamsPtr->grid.d_realGrid;
pmeGpu->archSpecific->complexGridSize = pmeGpu->archSpecific->realGridSize;
// the size might get used later for copying the grid
void pme_gpu_clear_grids(const PmeGpu* pmeGpu)
{
clearDeviceBufferAsync(&pmeGpu->kernelParams->grid.d_realGrid, 0,
- pmeGpu->archSpecific->realGridSize, pmeGpu->archSpecific->pmeStream);
+ pmeGpu->archSpecific->realGridSize, pmeGpu->archSpecific->pmeStream_);
}
void pme_gpu_realloc_and_copy_fract_shifts(PmeGpu* pmeGpu)
const int newFractShiftsSize = cellCount * (nx + ny + nz);
-#if GMX_GPU == GMX_GPU_CUDA
- initParamLookupTable(kernelParamsPtr->grid.d_fractShiftsTable, kernelParamsPtr->fractShiftsTableTexture,
- pmeGpu->common->fsh.data(), newFractShiftsSize);
+ initParamLookupTable(&kernelParamsPtr->grid.d_fractShiftsTable,
+ &kernelParamsPtr->fractShiftsTableTexture, pmeGpu->common->fsh.data(),
+ newFractShiftsSize, pmeGpu->archSpecific->deviceContext_);
- initParamLookupTable(kernelParamsPtr->grid.d_gridlineIndicesTable,
- kernelParamsPtr->gridlineIndicesTableTexture, pmeGpu->common->nn.data(),
- newFractShiftsSize);
-#elif GMX_GPU == GMX_GPU_OPENCL
- // No dedicated texture routines....
- allocateDeviceBuffer(&kernelParamsPtr->grid.d_fractShiftsTable, newFractShiftsSize,
- pmeGpu->archSpecific->context);
- allocateDeviceBuffer(&kernelParamsPtr->grid.d_gridlineIndicesTable, newFractShiftsSize,
- pmeGpu->archSpecific->context);
- copyToDeviceBuffer(&kernelParamsPtr->grid.d_fractShiftsTable, pmeGpu->common->fsh.data(), 0,
- newFractShiftsSize, pmeGpu->archSpecific->pmeStream,
- GpuApiCallBehavior::Async, nullptr);
- copyToDeviceBuffer(&kernelParamsPtr->grid.d_gridlineIndicesTable, pmeGpu->common->nn.data(), 0,
- newFractShiftsSize, pmeGpu->archSpecific->pmeStream,
- GpuApiCallBehavior::Async, nullptr);
-#endif
+ initParamLookupTable(&kernelParamsPtr->grid.d_gridlineIndicesTable,
+ &kernelParamsPtr->gridlineIndicesTableTexture, pmeGpu->common->nn.data(),
+ newFractShiftsSize, pmeGpu->archSpecific->deviceContext_);
}
void pme_gpu_free_fract_shifts(const PmeGpu* pmeGpu)
{
auto* kernelParamsPtr = pmeGpu->kernelParams.get();
#if GMX_GPU == GMX_GPU_CUDA
- destroyParamLookupTable(kernelParamsPtr->grid.d_fractShiftsTable,
+ destroyParamLookupTable(&kernelParamsPtr->grid.d_fractShiftsTable,
kernelParamsPtr->fractShiftsTableTexture);
- destroyParamLookupTable(kernelParamsPtr->grid.d_gridlineIndicesTable,
+ destroyParamLookupTable(&kernelParamsPtr->grid.d_gridlineIndicesTable,
kernelParamsPtr->gridlineIndicesTableTexture);
#elif GMX_GPU == GMX_GPU_OPENCL
freeDeviceBuffer(&kernelParamsPtr->grid.d_fractShiftsTable);
bool pme_gpu_stream_query(const PmeGpu* pmeGpu)
{
- return haveStreamTasksCompleted(pmeGpu->archSpecific->pmeStream);
+ return haveStreamTasksCompleted(pmeGpu->archSpecific->pmeStream_);
}
void pme_gpu_copy_input_gather_grid(const PmeGpu* pmeGpu, float* h_grid)
{
copyToDeviceBuffer(&pmeGpu->kernelParams->grid.d_realGrid, h_grid, 0, pmeGpu->archSpecific->realGridSize,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
}
void pme_gpu_copy_output_spread_grid(const PmeGpu* pmeGpu, float* h_grid)
{
copyFromDeviceBuffer(h_grid, &pmeGpu->kernelParams->grid.d_realGrid, 0,
- pmeGpu->archSpecific->realGridSize, pmeGpu->archSpecific->pmeStream,
+ pmeGpu->archSpecific->realGridSize, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
- pmeGpu->archSpecific->syncSpreadGridD2H.markEvent(pmeGpu->archSpecific->pmeStream);
+ pmeGpu->archSpecific->syncSpreadGridD2H.markEvent(pmeGpu->archSpecific->pmeStream_);
}
void pme_gpu_copy_output_spread_atom_data(const PmeGpu* pmeGpu)
{
- const int alignment = pme_gpu_get_atoms_per_warp(pmeGpu);
- const size_t nAtomsPadded = ((pmeGpu->nAtomsAlloc + alignment - 1) / alignment) * alignment;
- const size_t splinesCount = DIM * nAtomsPadded * pmeGpu->common->pme_order;
+ const size_t splinesCount = DIM * pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order;
auto* kernelParamsPtr = pmeGpu->kernelParams.get();
copyFromDeviceBuffer(pmeGpu->staging.h_dtheta, &kernelParamsPtr->atoms.d_dtheta, 0, splinesCount,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
copyFromDeviceBuffer(pmeGpu->staging.h_theta, &kernelParamsPtr->atoms.d_theta, 0, splinesCount,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
copyFromDeviceBuffer(pmeGpu->staging.h_gridlineIndices, &kernelParamsPtr->atoms.d_gridlineIndices,
- 0, kernelParamsPtr->atoms.nAtoms * DIM, pmeGpu->archSpecific->pmeStream,
+ 0, kernelParamsPtr->atoms.nAtoms * DIM, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
void pme_gpu_copy_input_gather_atom_data(const PmeGpu* pmeGpu)
{
- const int alignment = pme_gpu_get_atoms_per_warp(pmeGpu);
- const size_t nAtomsPadded = ((pmeGpu->nAtomsAlloc + alignment - 1) / alignment) * alignment;
- const size_t splinesCount = DIM * nAtomsPadded * pmeGpu->common->pme_order;
+ const size_t splinesCount = DIM * pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order;
auto* kernelParamsPtr = pmeGpu->kernelParams.get();
- if (c_usePadding)
- {
- // TODO: could clear only the padding and not the whole thing, but this is a test-exclusive code anyway
- clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_gridlineIndices, 0,
- pmeGpu->nAtomsAlloc * DIM, pmeGpu->archSpecific->pmeStream);
- clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_dtheta, 0,
- pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order * DIM,
- pmeGpu->archSpecific->pmeStream);
- clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_theta, 0,
- pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order * DIM,
- pmeGpu->archSpecific->pmeStream);
- }
+
+ // TODO: could clear only the padding and not the whole thing, but this is a test-exclusive code anyway
+ clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_gridlineIndices, 0, pmeGpu->nAtomsAlloc * DIM,
+ pmeGpu->archSpecific->pmeStream_);
+ clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_dtheta, 0,
+ pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order * DIM,
+ pmeGpu->archSpecific->pmeStream_);
+ clearDeviceBufferAsync(&kernelParamsPtr->atoms.d_theta, 0,
+ pmeGpu->nAtomsAlloc * pmeGpu->common->pme_order * DIM,
+ pmeGpu->archSpecific->pmeStream_);
+
copyToDeviceBuffer(&kernelParamsPtr->atoms.d_dtheta, pmeGpu->staging.h_dtheta, 0, splinesCount,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
copyToDeviceBuffer(&kernelParamsPtr->atoms.d_theta, pmeGpu->staging.h_theta, 0, splinesCount,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
copyToDeviceBuffer(&kernelParamsPtr->atoms.d_gridlineIndices, pmeGpu->staging.h_gridlineIndices,
- 0, kernelParamsPtr->atoms.nAtoms * DIM, pmeGpu->archSpecific->pmeStream,
+ 0, kernelParamsPtr->atoms.nAtoms * DIM, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
pmeGpu->archSpecific->syncSpreadGridD2H.waitForEvent();
}
-void pme_gpu_init_internal(PmeGpu* pmeGpu)
+/*! \brief Internal GPU initialization for PME.
+ *
+ * \param[in] pmeGpu GPU PME data.
+ * \param[in] deviceContext GPU context.
+ * \param[in] deviceStream GPU stream.
+ */
+static void pme_gpu_init_internal(PmeGpu* pmeGpu, const DeviceContext& deviceContext, const DeviceStream& deviceStream)
{
#if GMX_GPU == GMX_GPU_CUDA
// Prepare to use the device that this PME task was assigned earlier.
// Other entities, such as CUDA timing events, are known to implicitly use the device context.
- CU_RET_ERR(cudaSetDevice(pmeGpu->deviceInfo->id), "Switching to PME CUDA device");
+ CU_RET_ERR(cudaSetDevice(deviceContext.deviceInfo().id), "Switching to PME CUDA device");
#endif
/* Allocate the target-specific structures */
- pmeGpu->archSpecific.reset(new PmeGpuSpecific());
+ pmeGpu->archSpecific.reset(new PmeGpuSpecific(deviceContext, deviceStream));
pmeGpu->kernelParams.reset(new PmeGpuKernelParams());
pmeGpu->archSpecific->performOutOfPlaceFFT = true;
* TODO: PME could also try to pick up nice grid sizes (with factors of 2, 3, 5, 7).
*/
- // TODO: this is just a convenient reuse because programHandle_ currently is in charge of creating context
- pmeGpu->archSpecific->context = pmeGpu->programHandle_->impl_->context;
-
- // timing enabling - TODO put this in gpu_utils (even though generally this is just option handling?) and reuse in NB
- if (GMX_GPU == GMX_GPU_CUDA)
- {
- /* WARNING: CUDA timings are incorrect with multiple streams.
- * This is the main reason why they are disabled by default.
- */
- // TODO: Consider turning on by default when we can detect nr of streams.
- pmeGpu->archSpecific->useTiming = (getenv("GMX_ENABLE_GPU_TIMING") != nullptr);
- }
- else if (GMX_GPU == GMX_GPU_OPENCL)
- {
- pmeGpu->archSpecific->useTiming = (getenv("GMX_DISABLE_GPU_TIMING") == nullptr);
- }
-
#if GMX_GPU == GMX_GPU_CUDA
- pmeGpu->maxGridWidthX = pmeGpu->deviceInfo->prop.maxGridSize[0];
+ pmeGpu->maxGridWidthX = deviceContext.deviceInfo().prop.maxGridSize[0];
#elif GMX_GPU == GMX_GPU_OPENCL
pmeGpu->maxGridWidthX = INT32_MAX / 2;
// TODO: is there no really global work size limit in OpenCL?
#endif
-
- /* Creating a PME GPU stream:
- * - default high priority with CUDA
- * - no priorities implemented yet with OpenCL; see #2532
- */
-#if GMX_GPU == GMX_GPU_CUDA
- cudaError_t stat;
- int highest_priority, lowest_priority;
- stat = cudaDeviceGetStreamPriorityRange(&lowest_priority, &highest_priority);
- CU_RET_ERR(stat, "PME cudaDeviceGetStreamPriorityRange failed");
- stat = cudaStreamCreateWithPriority(&pmeGpu->archSpecific->pmeStream,
- cudaStreamDefault, // cudaStreamNonBlocking,
- highest_priority);
- CU_RET_ERR(stat, "cudaStreamCreateWithPriority on the PME stream failed");
-#elif GMX_GPU == GMX_GPU_OPENCL
- cl_command_queue_properties queueProperties =
- pmeGpu->archSpecific->useTiming ? CL_QUEUE_PROFILING_ENABLE : 0;
- cl_device_id device_id = pmeGpu->deviceInfo->ocl_gpu_id.ocl_device_id;
- cl_int clError;
- pmeGpu->archSpecific->pmeStream =
- clCreateCommandQueue(pmeGpu->archSpecific->context, device_id, queueProperties, &clError);
- if (clError != CL_SUCCESS)
- {
- GMX_THROW(gmx::InternalError("Failed to create PME command queue"));
- }
-#endif
-}
-
-void pme_gpu_destroy_specific(const PmeGpu* pmeGpu)
-{
-#if GMX_GPU == GMX_GPU_CUDA
- /* Destroy the CUDA stream */
- cudaError_t stat = cudaStreamDestroy(pmeGpu->archSpecific->pmeStream);
- CU_RET_ERR(stat, "PME cudaStreamDestroy error");
-#elif GMX_GPU == GMX_GPU_OPENCL
- cl_int clError = clReleaseCommandQueue(pmeGpu->archSpecific->pmeStream);
- if (clError != CL_SUCCESS)
- {
- gmx_warning("Failed to destroy PME command queue");
- }
-#endif
}
void pme_gpu_reinit_3dfft(const PmeGpu* pmeGpu)
{
- if (pme_gpu_performs_FFT(pmeGpu))
+ if (pme_gpu_settings(pmeGpu).performGPUFFT)
{
pmeGpu->archSpecific->fftSetup.resize(0);
for (int i = 0; i < pmeGpu->common->ngrids; i++)
pmeGpu->archSpecific->fftSetup.resize(0);
}
-int getSplineParamFullIndex(int order, int splineIndex, int dimIndex, int atomIndex, int atomsPerWarp)
-{
- if (order != c_pmeGpuOrder)
- {
- throw order;
- }
- constexpr int fixedOrder = c_pmeGpuOrder;
- GMX_UNUSED_VALUE(fixedOrder);
-
- const int atomWarpIndex = atomIndex % atomsPerWarp;
- const int warpIndex = atomIndex / atomsPerWarp;
- int indexBase, result;
- switch (atomsPerWarp)
- {
- case 1:
- indexBase = getSplineParamIndexBase<fixedOrder, 1>(warpIndex, atomWarpIndex);
- result = getSplineParamIndex<fixedOrder, 1>(indexBase, dimIndex, splineIndex);
- break;
-
- case 2:
- indexBase = getSplineParamIndexBase<fixedOrder, 2>(warpIndex, atomWarpIndex);
- result = getSplineParamIndex<fixedOrder, 2>(indexBase, dimIndex, splineIndex);
- break;
-
- case 4:
- indexBase = getSplineParamIndexBase<fixedOrder, 4>(warpIndex, atomWarpIndex);
- result = getSplineParamIndex<fixedOrder, 4>(indexBase, dimIndex, splineIndex);
- break;
-
- case 8:
- indexBase = getSplineParamIndexBase<fixedOrder, 8>(warpIndex, atomWarpIndex);
- result = getSplineParamIndex<fixedOrder, 8>(indexBase, dimIndex, splineIndex);
- break;
-
- default:
- GMX_THROW(gmx::NotImplementedError(
- gmx::formatString("Test function call not unrolled for atomsPerWarp = %d in "
- "getSplineParamFullIndex",
- atomsPerWarp)));
- }
- return result;
-}
-
void pme_gpu_getEnergyAndVirial(const gmx_pme_t& pme, PmeOutput* output)
{
const PmeGpu* pmeGpu = pme.gpu;
}
}
-PmeOutput pme_gpu_getOutput(const gmx_pme_t& pme, const int flags)
+PmeOutput pme_gpu_getOutput(const gmx_pme_t& pme, const bool computeEnergyAndVirial)
{
- PmeGpu* pmeGpu = pme.gpu;
- const bool haveComputedEnergyAndVirial = (flags & GMX_PME_CALC_ENER_VIR) != 0;
+ PmeGpu* pmeGpu = pme.gpu;
PmeOutput output;
pme_gpu_getForceOutput(pmeGpu, &output);
- // The caller knows from the flags that the energy and the virial are not usable
- // on the else branch
- if (haveComputedEnergyAndVirial)
+ if (computeEnergyAndVirial)
{
- if (pme_gpu_performs_solve(pmeGpu))
+ if (pme_gpu_settings(pmeGpu).performGPUSolve)
{
pme_gpu_getEnergyAndVirial(pme, &output);
}
kernelParamsPtr->grid.complexGridSizePadded[i] = kernelParamsPtr->grid.realGridSize[i];
}
/* FFT: n real elements correspond to (n / 2 + 1) complex elements in minor dimension */
- if (!pme_gpu_performs_FFT(pmeGpu))
+ if (!pme_gpu_settings(pmeGpu).performGPUFFT)
{
// This allows for GPU spreading grid and CPU fftgrid to have the same layout, so that we can copy the data directly
kernelParamsPtr->grid.realGridSizePadded[ZZ] =
{
if (pmeGpu->kernelParams->atoms.nAtoms > c_pmeGpuPerformanceAtomLimit && (GMX_GPU == GMX_GPU_CUDA))
{
- pmeGpu->settings.useOrderThreadsPerAtom = true;
- pmeGpu->settings.recalculateSplines = true;
+ pmeGpu->settings.threadsPerAtom = ThreadsPerAtom::Order;
+ pmeGpu->settings.recalculateSplines = true;
}
else
{
- pmeGpu->settings.useOrderThreadsPerAtom = false;
- pmeGpu->settings.recalculateSplines = false;
+ pmeGpu->settings.threadsPerAtom = ThreadsPerAtom::OrderSquared;
+ pmeGpu->settings.recalculateSplines = false;
}
}
* TODO: this should become PmeGpu::PmeGpu()
*
* \param[in,out] pme The PME structure.
- * \param[in,out] gpuInfo The GPU information structure.
- * \param[in] pmeGpuProgram The handle to the program/kernel data created outside (e.g. in unit tests/runner)
+ * \param[in] deviceContext The GPU context.
+ * \param[in] deviceStream The GPU stream.
+ * \param[in,out] pmeGpuProgram The handle to the program/kernel data created outside (e.g. in unit tests/runner)
*/
-static void pme_gpu_init(gmx_pme_t* pme, const gmx_device_info_t* gpuInfo, PmeGpuProgramHandle pmeGpuProgram)
+static void pme_gpu_init(gmx_pme_t* pme,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ const PmeGpuProgram* pmeGpuProgram)
{
pme->gpu = new PmeGpu();
PmeGpu* pmeGpu = pme->gpu;
/* These settings are set here for the whole run; dynamic ones are set in pme_gpu_reinit() */
/* A convenience variable. */
- pmeGpu->settings.useDecomposition = (pme->nnodes == 1);
+ pmeGpu->settings.useDecomposition = (pme->nnodes != 1);
/* TODO: CPU gather with GPU spread is broken due to different theta/dtheta layout. */
pmeGpu->settings.performGPUGather = true;
// By default GPU-side reduction is off (explicitly set here for tests, otherwise reset per-step)
pme_gpu_set_testing(pmeGpu, false);
- pmeGpu->deviceInfo = gpuInfo;
GMX_ASSERT(pmeGpuProgram != nullptr, "GPU kernels must be already compiled");
pmeGpu->programHandle_ = pmeGpuProgram;
pmeGpu->initializedClfftLibrary_ = std::make_unique<gmx::ClfftInitializer>();
- pme_gpu_init_internal(pmeGpu);
+ pme_gpu_init_internal(pmeGpu, deviceContext, deviceStream);
pme_gpu_alloc_energy_virial(pmeGpu);
pme_gpu_copy_common_data_from(pme);
kernelParamsPtr->constants.elFactor = ONE_4PI_EPS0 / pmeGpu->common->epsilon_r;
}
-void pme_gpu_transform_spline_atom_data(const PmeGpu* pmeGpu,
- const PmeAtomComm* atc,
- PmeSplineDataType type,
- int dimIndex,
- PmeLayoutTransform transform)
-{
- // The GPU atom spline data is laid out in a different way currently than the CPU one.
- // This function converts the data from GPU to CPU layout (in the host memory).
- // It is only intended for testing purposes so far.
- // Ideally we should use similar layouts on CPU and GPU if we care about mixed modes and their
- // performance (e.g. spreading on GPU, gathering on CPU).
- GMX_RELEASE_ASSERT(atc->nthread == 1, "Only the serial PME data layout is supported");
- const uintmax_t threadIndex = 0;
- const auto atomCount = pme_gpu_get_kernel_params_base_ptr(pmeGpu)->atoms.nAtoms;
- const auto atomsPerWarp = pme_gpu_get_atoms_per_warp(pmeGpu);
- const auto pmeOrder = pmeGpu->common->pme_order;
- GMX_ASSERT(pmeOrder == c_pmeGpuOrder, "Only PME order 4 is implemented");
-
- real* cpuSplineBuffer;
- float* h_splineBuffer;
- switch (type)
- {
- case PmeSplineDataType::Values:
- cpuSplineBuffer = atc->spline[threadIndex].theta.coefficients[dimIndex];
- h_splineBuffer = pmeGpu->staging.h_theta;
- break;
-
- case PmeSplineDataType::Derivatives:
- cpuSplineBuffer = atc->spline[threadIndex].dtheta.coefficients[dimIndex];
- h_splineBuffer = pmeGpu->staging.h_dtheta;
- break;
-
- default: GMX_THROW(gmx::InternalError("Unknown spline data type"));
- }
-
- for (auto atomIndex = 0; atomIndex < atomCount; atomIndex++)
- {
- for (auto orderIndex = 0; orderIndex < pmeOrder; orderIndex++)
- {
- const auto gpuValueIndex =
- getSplineParamFullIndex(pmeOrder, orderIndex, dimIndex, atomIndex, atomsPerWarp);
- const auto cpuValueIndex = atomIndex * pmeOrder + orderIndex;
- GMX_ASSERT(cpuValueIndex < atomCount * pmeOrder,
- "Atom spline data index out of bounds (while transforming GPU data layout "
- "for host)");
- switch (transform)
- {
- case PmeLayoutTransform::GpuToHost:
- cpuSplineBuffer[cpuValueIndex] = h_splineBuffer[gpuValueIndex];
- break;
-
- case PmeLayoutTransform::HostToGpu:
- h_splineBuffer[gpuValueIndex] = cpuSplineBuffer[cpuValueIndex];
- break;
-
- default: GMX_THROW(gmx::InternalError("Unknown layout transform"));
- }
- }
- }
-}
-
void pme_gpu_get_real_grid_sizes(const PmeGpu* pmeGpu, gmx::IVec* gridSize, gmx::IVec* paddedGridSize)
{
GMX_ASSERT(gridSize != nullptr, "");
}
}
-void pme_gpu_reinit(gmx_pme_t* pme, const gmx_device_info_t* gpuInfo, PmeGpuProgramHandle pmeGpuProgram)
+void pme_gpu_reinit(gmx_pme_t* pme,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram)
{
- if (!pme_gpu_active(pme))
- {
- return;
- }
+ GMX_ASSERT(pme != nullptr, "Need valid PME object");
if (!pme->gpu)
{
+ GMX_RELEASE_ASSERT(deviceContext != nullptr,
+ "Device context can not be nullptr when setting up PME on GPU.");
+ GMX_RELEASE_ASSERT(deviceStream != nullptr,
+ "Device stream can not be nullptr when setting up PME on GPU.");
/* First-time initialization */
- pme_gpu_init(pme, gpuInfo, pmeGpuProgram);
+ pme_gpu_init(pme, *deviceContext, *deviceStream, pmeGpuProgram);
}
else
{
}
/* GPU FFT will only get used for a single rank.*/
pme->gpu->settings.performGPUFFT =
- (pme->gpu->common->runMode == PmeRunMode::GPU) && !pme_gpu_uses_dd(pme->gpu);
+ (pme->gpu->common->runMode == PmeRunMode::GPU) && !pme->gpu->settings.useDecomposition;
pme->gpu->settings.performGPUSolve = (pme->gpu->common->runMode == PmeRunMode::GPU);
/* Reinit active timers */
pme_gpu_destroy_3dfft(pmeGpu);
- /* Free the GPU-framework specific data last */
- pme_gpu_destroy_specific(pmeGpu);
-
delete pmeGpu;
}
{
auto* kernelParamsPtr = pme_gpu_get_kernel_params_base_ptr(pmeGpu);
kernelParamsPtr->atoms.nAtoms = nAtoms;
- const int alignment = pme_gpu_get_atom_data_alignment(pmeGpu);
- pmeGpu->nAtomsPadded = ((nAtoms + alignment - 1) / alignment) * alignment;
- const int nAtomsAlloc = c_usePadding ? pmeGpu->nAtomsPadded : nAtoms;
- const bool haveToRealloc =
- (pmeGpu->nAtomsAlloc < nAtomsAlloc); /* This check might be redundant, but is logical */
- pmeGpu->nAtomsAlloc = nAtomsAlloc;
+ const int block_size = pme_gpu_get_atom_data_block_size();
+ const int nAtomsNewPadded = ((nAtoms + block_size - 1) / block_size) * block_size;
+ const bool haveToRealloc = (pmeGpu->nAtomsAlloc < nAtomsNewPadded);
+ pmeGpu->nAtomsAlloc = nAtomsNewPadded;
#if GMX_DOUBLE
GMX_RELEASE_ASSERT(false, "Only single precision supported");
pme_gpu_select_best_performing_pme_spreadgather_kernels(pmeGpu);
}
+/*! \internal \brief
+ * Returns raw timing event from the corresponding GpuRegionTimer (if timings are enabled).
+ * In CUDA result can be nullptr stub, per GpuRegionTimer implementation.
+ *
+ * \param[in] pmeGpu The PME GPU data structure.
+ * \param[in] PMEStageId The PME GPU stage gtPME_ index from the enum in src/gromacs/timing/gpu_timing.h
+ */
+static CommandEvent* pme_gpu_fetch_timing_event(const PmeGpu* pmeGpu, size_t PMEStageId)
+{
+ CommandEvent* timingEvent = nullptr;
+ if (pme_gpu_timings_enabled(pmeGpu))
+ {
+ GMX_ASSERT(PMEStageId < pmeGpu->archSpecific->timingEvents.size(),
+ "Wrong PME GPU timing event index");
+ timingEvent = pmeGpu->archSpecific->timingEvents[PMEStageId].fetchNextEvent();
+ }
+ return timingEvent;
+}
+
void pme_gpu_3dfft(const PmeGpu* pmeGpu, gmx_fft_direction dir, int grid_index)
{
int timerId = (dir == GMX_FFT_REAL_TO_COMPLEX) ? gtPME_FFT_R2C : gtPME_FFT_C2R;
* Returns a pointer to appropriate spline and spread kernel based on the input bool values
*
* \param[in] pmeGpu The PME GPU structure.
- * \param[in] useOrderThreadsPerAtom bool controlling if we should use order or order*order threads per atom
+ * \param[in] threadsPerAtom Controls whether we should use order or order*order threads per atom
* \param[in] writeSplinesToGlobal bool controlling if we should write spline data to global memory
*
* \return Pointer to CUDA kernel
*/
-static auto selectSplineAndSpreadKernelPtr(const PmeGpu* pmeGpu, bool useOrderThreadsPerAtom, bool writeSplinesToGlobal)
+static auto selectSplineAndSpreadKernelPtr(const PmeGpu* pmeGpu, ThreadsPerAtom threadsPerAtom, bool writeSplinesToGlobal)
{
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
if (writeSplinesToGlobal)
{
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
kernelPtr = pmeGpu->programHandle_->impl_->splineAndSpreadKernelWriteSplinesThPerAtom4;
}
}
else
{
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
kernelPtr = pmeGpu->programHandle_->impl_->splineAndSpreadKernelThPerAtom4;
}
* Returns a pointer to appropriate spline kernel based on the input bool values
*
* \param[in] pmeGpu The PME GPU structure.
- * \param[in] useOrderThreadsPerAtom bool controlling if we should use order or order*order threads per atom
+ * \param[in] threadsPerAtom Controls whether we should use order or order*order threads per atom
* \param[in] writeSplinesToGlobal bool controlling if we should write spline data to global memory
*
* \return Pointer to CUDA kernel
*/
-static auto selectSplineKernelPtr(const PmeGpu* pmeGpu, bool useOrderThreadsPerAtom, bool gmx_unused writeSplinesToGlobal)
+static auto selectSplineKernelPtr(const PmeGpu* pmeGpu,
+ ThreadsPerAtom threadsPerAtom,
+ bool gmx_unused writeSplinesToGlobal)
{
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
GMX_ASSERT(
writeSplinesToGlobal,
"Spline data should always be written to global memory when just calculating splines");
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
kernelPtr = pmeGpu->programHandle_->impl_->splineKernelThPerAtom4;
}
* Returns a pointer to appropriate spread kernel based on the input bool values
*
* \param[in] pmeGpu The PME GPU structure.
- * \param[in] useOrderThreadsPerAtom bool controlling if we should use order or order*order threads per atom
+ * \param[in] threadsPerAtom Controls whether we should use order or order*order threads per atom
* \param[in] writeSplinesToGlobal bool controlling if we should write spline data to global memory
*
* \return Pointer to CUDA kernel
*/
-static auto selectSpreadKernelPtr(const PmeGpu* pmeGpu, bool useOrderThreadsPerAtom, bool writeSplinesToGlobal)
+static auto selectSpreadKernelPtr(const PmeGpu* pmeGpu, ThreadsPerAtom threadsPerAtom, bool writeSplinesToGlobal)
{
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
if (writeSplinesToGlobal)
{
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
kernelPtr = pmeGpu->programHandle_->impl_->spreadKernelThPerAtom4;
}
{
/* if we are not saving the spline data we need to recalculate it
using the spline and spread Kernel */
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
kernelPtr = pmeGpu->programHandle_->impl_->splineAndSpreadKernelThPerAtom4;
}
const int order = pmeGpu->common->pme_order;
GMX_ASSERT(order == c_pmeGpuOrder, "Only PME order 4 is implemented");
- const bool writeGlobal = pmeGpu->settings.copyAllOutputs;
- const bool useOrderThreadsPerAtom = pmeGpu->settings.useOrderThreadsPerAtom;
- const bool recalculateSplines = pmeGpu->settings.recalculateSplines;
+ const bool writeGlobal = pmeGpu->settings.copyAllOutputs;
+ const int threadsPerAtom =
+ (pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::Order ? order : order * order);
+ const bool recalculateSplines = pmeGpu->settings.recalculateSplines;
#if GMX_GPU == GMX_GPU_OPENCL
- GMX_ASSERT(!useOrderThreadsPerAtom, "Only 16 threads per atom supported in OpenCL");
+ GMX_ASSERT(pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::OrderSquared,
+ "Only 16 threads per atom supported in OpenCL");
GMX_ASSERT(!recalculateSplines, "Recalculating splines not supported in OpenCL");
#endif
- const int atomsPerBlock = useOrderThreadsPerAtom ? blockSize / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom
- : blockSize / c_pmeSpreadGatherThreadsPerAtom;
+ const int atomsPerBlock = blockSize / threadsPerAtom;
// TODO: pick smaller block size in runtime if needed
// (e.g. on 660 Ti where 50% occupancy is ~25% faster than 100% occupancy with RNAse (~17.8k atoms))
// TODO: test varying block sizes on modern arch-s as well
// TODO: also consider using cudaFuncSetCacheConfig() for preferring shared memory on older architectures
//(for spline data mostly)
- GMX_ASSERT(!c_usePadding || !(c_pmeAtomDataAlignment % atomsPerBlock),
+ GMX_ASSERT(!(c_pmeAtomDataBlockSize % atomsPerBlock),
"inconsistent atom data padding vs. spreading block size");
// Ensure that coordinates are ready on the device before launching spread;
// only needed with CUDA on PP+PME ranks, not on separate PME ranks, in unit tests
// nor in OpenCL as these cases use a single stream (hence xReadyOnDevice == nullptr).
GMX_ASSERT(xReadyOnDevice != nullptr || (GMX_GPU != GMX_GPU_CUDA)
- || pmeGpu->common->isRankPmeOnly || pme_gpu_is_testing(pmeGpu),
+ || pmeGpu->common->isRankPmeOnly || pme_gpu_settings(pmeGpu).copyAllOutputs,
"Need a valid coordinate synchronizer on PP+PME ranks with CUDA.");
if (xReadyOnDevice)
{
- xReadyOnDevice->enqueueWaitEvent(pmeGpu->archSpecific->pmeStream);
+ xReadyOnDevice->enqueueWaitEvent(pmeGpu->archSpecific->pmeStream_);
}
- const int blockCount = pmeGpu->nAtomsPadded / atomsPerBlock;
+ const int blockCount = pmeGpu->nAtomsAlloc / atomsPerBlock;
auto dimGrid = pmeGpuCreateGrid(pmeGpu, blockCount);
KernelLaunchConfig config;
config.blockSize[0] = order;
- config.blockSize[1] = useOrderThreadsPerAtom ? 1 : order;
+ config.blockSize[1] = (pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::Order ? 1 : order);
config.blockSize[2] = atomsPerBlock;
config.gridSize[0] = dimGrid.first;
config.gridSize[1] = dimGrid.second;
- config.stream = pmeGpu->archSpecific->pmeStream;
int timingId;
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
if (spreadCharges)
{
timingId = gtPME_SPLINEANDSPREAD;
- kernelPtr = selectSplineAndSpreadKernelPtr(pmeGpu, useOrderThreadsPerAtom,
+ kernelPtr = selectSplineAndSpreadKernelPtr(pmeGpu, pmeGpu->settings.threadsPerAtom,
writeGlobal || (!recalculateSplines));
}
else
{
timingId = gtPME_SPLINE;
- kernelPtr = selectSplineKernelPtr(pmeGpu, useOrderThreadsPerAtom,
+ kernelPtr = selectSplineKernelPtr(pmeGpu, pmeGpu->settings.threadsPerAtom,
writeGlobal || (!recalculateSplines));
}
}
else
{
timingId = gtPME_SPREAD;
- kernelPtr = selectSpreadKernelPtr(pmeGpu, useOrderThreadsPerAtom,
+ kernelPtr = selectSpreadKernelPtr(pmeGpu, pmeGpu->settings.threadsPerAtom,
writeGlobal || (!recalculateSplines));
}
&kernelParamsPtr->atoms.d_coordinates);
#endif
- launchGpuKernel(kernelPtr, config, timingEvent, "PME spline/spread", kernelArgs);
+ launchGpuKernel(kernelPtr, config, pmeGpu->archSpecific->pmeStream_, timingEvent,
+ "PME spline/spread", kernelArgs);
pme_gpu_stop_timing(pmeGpu, timingId);
- const bool copyBackGrid =
- spreadCharges && (pme_gpu_is_testing(pmeGpu) || !pme_gpu_performs_FFT(pmeGpu));
+ const auto& settings = pmeGpu->settings;
+ const bool copyBackGrid = spreadCharges && (!settings.performGPUFFT || settings.copyAllOutputs);
if (copyBackGrid)
{
pme_gpu_copy_output_spread_grid(pmeGpu, h_grid);
}
const bool copyBackAtomData =
- computeSplines && (pme_gpu_is_testing(pmeGpu) || !pme_gpu_performs_gather(pmeGpu));
+ computeSplines && (!settings.performGPUGather || settings.copyAllOutputs);
if (copyBackAtomData)
{
pme_gpu_copy_output_spread_atom_data(pmeGpu);
void pme_gpu_solve(const PmeGpu* pmeGpu, t_complex* h_grid, GridOrdering gridOrdering, bool computeEnergyAndVirial)
{
- const bool copyInputAndOutputGrid = pme_gpu_is_testing(pmeGpu) || !pme_gpu_performs_FFT(pmeGpu);
+ const auto& settings = pmeGpu->settings;
+ const bool copyInputAndOutputGrid = !settings.performGPUFFT || settings.copyAllOutputs;
auto* kernelParamsPtr = pmeGpu->kernelParams.get();
if (copyInputAndOutputGrid)
{
copyToDeviceBuffer(&kernelParamsPtr->grid.d_fourierGrid, h_gridFloat, 0,
- pmeGpu->archSpecific->complexGridSize, pmeGpu->archSpecific->pmeStream,
+ pmeGpu->archSpecific->complexGridSize, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
{
cellsPerBlock = (gridLineSize + blocksPerGridLine - 1) / blocksPerGridLine;
}
- const int warpSize = pmeGpu->programHandle_->impl_->warpSize;
+ const int warpSize = pmeGpu->programHandle_->warpSize();
const int blockSize = (cellsPerBlock + warpSize - 1) / warpSize * warpSize;
static_assert(GMX_GPU != GMX_GPU_CUDA || c_solveMaxWarpsPerBlock / 2 >= 4,
config.gridSize[1] = (pmeGpu->kernelParams->grid.complexGridSize[middleDim] + gridLinesPerBlock - 1)
/ gridLinesPerBlock;
config.gridSize[2] = pmeGpu->kernelParams->grid.complexGridSize[majorDim];
- config.stream = pmeGpu->archSpecific->pmeStream;
int timingId = gtPME_SOLVE;
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
kernelPtr, config, kernelParamsPtr, &kernelParamsPtr->grid.d_splineModuli,
&kernelParamsPtr->constants.d_virialAndEnergy, &kernelParamsPtr->grid.d_fourierGrid);
#endif
- launchGpuKernel(kernelPtr, config, timingEvent, "PME solve", kernelArgs);
+ launchGpuKernel(kernelPtr, config, pmeGpu->archSpecific->pmeStream_, timingEvent, "PME solve",
+ kernelArgs);
pme_gpu_stop_timing(pmeGpu, timingId);
if (computeEnergyAndVirial)
{
copyFromDeviceBuffer(pmeGpu->staging.h_virialAndEnergy,
&kernelParamsPtr->constants.d_virialAndEnergy, 0, c_virialAndEnergyCount,
- pmeGpu->archSpecific->pmeStream, pmeGpu->settings.transferKind, nullptr);
+ pmeGpu->archSpecific->pmeStream_, pmeGpu->settings.transferKind, nullptr);
}
if (copyInputAndOutputGrid)
{
copyFromDeviceBuffer(h_gridFloat, &kernelParamsPtr->grid.d_fourierGrid, 0,
- pmeGpu->archSpecific->complexGridSize, pmeGpu->archSpecific->pmeStream,
+ pmeGpu->archSpecific->complexGridSize, pmeGpu->archSpecific->pmeStream_,
pmeGpu->settings.transferKind, nullptr);
}
}
* Returns a pointer to appropriate gather kernel based on the inputvalues
*
* \param[in] pmeGpu The PME GPU structure.
- * \param[in] useOrderThreadsPerAtom bool controlling if we should use order or order*order threads per atom
+ * \param[in] threadsPerAtom Controls whether we should use order or order*order threads per atom
* \param[in] readSplinesFromGlobal bool controlling if we should write spline data to global memory
- * \param[in] forceTreatment Controls if the forces from the gather should increment or replace the input forces.
*
* \return Pointer to CUDA kernel
*/
-inline auto selectGatherKernelPtr(const PmeGpu* pmeGpu,
- bool useOrderThreadsPerAtom,
- bool readSplinesFromGlobal,
- PmeForceOutputHandling forceTreatment)
+inline auto selectGatherKernelPtr(const PmeGpu* pmeGpu, ThreadsPerAtom threadsPerAtom, bool readSplinesFromGlobal)
{
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = nullptr;
if (readSplinesFromGlobal)
{
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
- kernelPtr = (forceTreatment == PmeForceOutputHandling::Set)
- ? pmeGpu->programHandle_->impl_->gatherKernelReadSplinesThPerAtom4
- : pmeGpu->programHandle_->impl_->gatherReduceWithInputKernelReadSplinesThPerAtom4;
+ kernelPtr = pmeGpu->programHandle_->impl_->gatherKernelReadSplinesThPerAtom4;
}
else
{
- kernelPtr = (forceTreatment == PmeForceOutputHandling::Set)
- ? pmeGpu->programHandle_->impl_->gatherKernelReadSplines
- : pmeGpu->programHandle_->impl_->gatherReduceWithInputKernelReadSplines;
+ kernelPtr = pmeGpu->programHandle_->impl_->gatherKernelReadSplines;
}
}
else
{
- if (useOrderThreadsPerAtom)
+ if (threadsPerAtom == ThreadsPerAtom::Order)
{
- kernelPtr = (forceTreatment == PmeForceOutputHandling::Set)
- ? pmeGpu->programHandle_->impl_->gatherKernelThPerAtom4
- : pmeGpu->programHandle_->impl_->gatherReduceWithInputKernelThPerAtom4;
+ kernelPtr = pmeGpu->programHandle_->impl_->gatherKernelThPerAtom4;
}
else
{
- kernelPtr = (forceTreatment == PmeForceOutputHandling::Set)
- ? pmeGpu->programHandle_->impl_->gatherKernel
- : pmeGpu->programHandle_->impl_->gatherReduceWithInputKernel;
+ kernelPtr = pmeGpu->programHandle_->impl_->gatherKernel;
}
}
return kernelPtr;
}
-void pme_gpu_gather(PmeGpu* pmeGpu, PmeForceOutputHandling forceTreatment, const float* h_grid)
+void pme_gpu_gather(PmeGpu* pmeGpu, const float* h_grid)
{
- /* Copying the input CPU forces for reduction */
- if (forceTreatment != PmeForceOutputHandling::Set)
- {
- pme_gpu_copy_input_forces(pmeGpu);
- }
-
- if (!pme_gpu_performs_FFT(pmeGpu) || pme_gpu_is_testing(pmeGpu))
+ const auto& settings = pmeGpu->settings;
+ if (!settings.performGPUFFT || settings.copyAllOutputs)
{
pme_gpu_copy_input_gather_grid(pmeGpu, const_cast<float*>(h_grid));
}
- if (pme_gpu_is_testing(pmeGpu))
+ if (settings.copyAllOutputs)
{
pme_gpu_copy_input_gather_atom_data(pmeGpu);
}
/* Set if we have unit tests */
- const bool readGlobal = pmeGpu->settings.copyAllOutputs;
- const size_t blockSize = pmeGpu->programHandle_->impl_->gatherWorkGroupSize;
- const bool useOrderThreadsPerAtom = pmeGpu->settings.useOrderThreadsPerAtom;
- const bool recalculateSplines = pmeGpu->settings.recalculateSplines;
+ const bool readGlobal = pmeGpu->settings.copyAllOutputs;
+ const size_t blockSize = pmeGpu->programHandle_->impl_->gatherWorkGroupSize;
+ const int order = pmeGpu->common->pme_order;
+ GMX_ASSERT(order == c_pmeGpuOrder, "Only PME order 4 is implemented");
+ const int threadsPerAtom =
+ (pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::Order ? order : order * order);
+ const bool recalculateSplines = pmeGpu->settings.recalculateSplines;
#if GMX_GPU == GMX_GPU_OPENCL
- GMX_ASSERT(!useOrderThreadsPerAtom, "Only 16 threads per atom supported in OpenCL");
+ GMX_ASSERT(pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::OrderSquared,
+ "Only 16 threads per atom supported in OpenCL");
GMX_ASSERT(!recalculateSplines, "Recalculating splines not supported in OpenCL");
#endif
- const int atomsPerBlock = useOrderThreadsPerAtom ? blockSize / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom
- : blockSize / c_pmeSpreadGatherThreadsPerAtom;
+ const int atomsPerBlock = blockSize / threadsPerAtom;
- GMX_ASSERT(!c_usePadding || !(c_pmeAtomDataAlignment % atomsPerBlock),
+ GMX_ASSERT(!(c_pmeAtomDataBlockSize % atomsPerBlock),
"inconsistent atom data padding vs. gathering block size");
- const int blockCount = pmeGpu->nAtomsPadded / atomsPerBlock;
+ const int blockCount = pmeGpu->nAtomsAlloc / atomsPerBlock;
auto dimGrid = pmeGpuCreateGrid(pmeGpu, blockCount);
- const int order = pmeGpu->common->pme_order;
- GMX_ASSERT(order == c_pmeGpuOrder, "Only PME order 4 is implemented");
-
KernelLaunchConfig config;
config.blockSize[0] = order;
- config.blockSize[1] = useOrderThreadsPerAtom ? 1 : order;
+ config.blockSize[1] = (pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::Order ? 1 : order);
config.blockSize[2] = atomsPerBlock;
config.gridSize[0] = dimGrid.first;
config.gridSize[1] = dimGrid.second;
- config.stream = pmeGpu->archSpecific->pmeStream;
// TODO test different cache configs
int timingId = gtPME_GATHER;
PmeGpuProgramImpl::PmeKernelHandle kernelPtr = selectGatherKernelPtr(
- pmeGpu, useOrderThreadsPerAtom, readGlobal || (!recalculateSplines), forceTreatment);
+ pmeGpu, pmeGpu->settings.threadsPerAtom, readGlobal || (!recalculateSplines));
// TODO design kernel selection getters and make PmeGpu a friend of PmeGpuProgramImpl
pme_gpu_start_timing(pmeGpu, timingId);
&kernelParamsPtr->atoms.d_dtheta, &kernelParamsPtr->atoms.d_gridlineIndices,
&kernelParamsPtr->atoms.d_forces);
#endif
- launchGpuKernel(kernelPtr, config, timingEvent, "PME gather", kernelArgs);
+ launchGpuKernel(kernelPtr, config, pmeGpu->archSpecific->pmeStream_, timingEvent, "PME gather",
+ kernelArgs);
pme_gpu_stop_timing(pmeGpu, timingId);
if (pmeGpu->settings.useGpuForceReduction)
{
- pmeGpu->archSpecific->pmeForcesReady.markEvent(pmeGpu->archSpecific->pmeStream);
+ pmeGpu->archSpecific->pmeForcesReady.markEvent(pmeGpu->archSpecific->pmeStream_);
}
else
{
}
}
-DeviceBuffer<float> pme_gpu_get_kernelparam_coordinates(const PmeGpu* pmeGpu)
-{
- GMX_ASSERT(pmeGpu && pmeGpu->kernelParams,
- "PME GPU device buffer was requested in non-GPU build or before the GPU PME was "
- "initialized.");
-
- return pmeGpu->kernelParams->atoms.d_coordinates;
-}
-
void* pme_gpu_get_kernelparam_forces(const PmeGpu* pmeGpu)
{
if (pmeGpu && pmeGpu->kernelParams)
}
}
-/*! \brief Check the validity of the device buffer.
- *
- * Checks if the buffer is not nullptr and, when possible, if it is big enough.
- *
- * \todo Split and move this function to gpu_utils.
- *
- * \param[in] buffer Device buffer to be checked.
- * \param[in] requiredSize Number of elements that the buffer will have to accommodate.
- *
- * \returns If the device buffer can be set.
- */
-template<typename T>
-static bool checkDeviceBuffer(gmx_unused DeviceBuffer<T> buffer, gmx_unused int requiredSize)
-{
-#if GMX_GPU == GMX_GPU_CUDA
- GMX_ASSERT(buffer != nullptr, "The device pointer is nullptr");
- return buffer != nullptr;
-#elif GMX_GPU == GMX_GPU_OPENCL
- size_t size;
- int retval = clGetMemObjectInfo(buffer, CL_MEM_SIZE, sizeof(size), &size, nullptr);
- GMX_ASSERT(retval == CL_SUCCESS,
- gmx::formatString("clGetMemObjectInfo failed with error code #%d", retval).c_str());
- GMX_ASSERT(static_cast<int>(size) >= requiredSize,
- "Number of atoms in device buffer is smaller then required size.");
- return retval == CL_SUCCESS && static_cast<int>(size) >= requiredSize;
-#elif GMX_GPU == GMX_GPU_NONE
- GMX_ASSERT(false, "Setter for device-side coordinates was called in non-GPU build.");
- return false;
-#endif
-}
-
-void pme_gpu_set_kernelparam_coordinates(const PmeGpu* pmeGpu, DeviceBuffer<float> d_x)
+void pme_gpu_set_kernelparam_coordinates(const PmeGpu* pmeGpu, DeviceBuffer<gmx::RVec> d_x)
{
GMX_ASSERT(pmeGpu && pmeGpu->kernelParams,
"PME GPU device buffer can not be set in non-GPU builds or before the GPU PME was "
pmeGpu->kernelParams->atoms.d_coordinates = d_x;
}
-void* pme_gpu_get_stream(const PmeGpu* pmeGpu)
-{
- if (pmeGpu)
- {
- return static_cast<void*>(&pmeGpu->archSpecific->pmeStream);
- }
- else
- {
- return nullptr;
- }
-}
-
-void* pme_gpu_get_context(const PmeGpu* pmeGpu)
-{
- if (pmeGpu)
- {
- return static_cast<void*>(&pmeGpu->archSpecific->context);
- }
- else
- {
- return nullptr;
- }
-}
-
GpuEventSynchronizer* pme_gpu_get_forces_ready_synchronizer(const PmeGpu* pmeGpu)
{
if (pmeGpu && pmeGpu->kernelParams)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_EWALD_PME_GPU_INTERNAL_H
#define GMX_EWALD_PME_GPU_INTERNAL_H
-#include "gromacs/fft/fft.h" // for the gmx_fft_direction enum
+#include "gromacs/fft/fft.h" // for the gmx_fft_direction enum
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gpu_macros.h" // for the GPU_FUNC_ macros
#include "gromacs/utility/arrayref.h"
-#include "pme_gpu_types_host.h" // for the inline functions accessing PmeGpu members
+#include "pme_gpu_types_host.h"
+#include "pme_output.h"
+class DeviceContext;
+struct DeviceInformation;
+class DeviceStream;
+class GpuEventSynchronizer;
struct gmx_hw_info_t;
struct gmx_gpu_opt_t;
struct gmx_pme_t; // only used in pme_gpu_reinit
-struct gmx_wallclock_gpu_pme_t;
+struct gmx_wallcycle;
class PmeAtomComm;
+enum class PmeForceOutputHandling;
+struct PmeGpu;
+class PmeGpuProgram;
+struct PmeGpuStaging;
+struct PmeGpuSettings;
struct t_complex;
namespace gmx
{
class MDLogger;
-}
+} // namespace gmx
//! Type of spline data
enum class PmeSplineDataType
};
/*! \libinternal \brief
- * Returns the number of atoms per chunk in the atom charges/coordinates data layout.
- * Depends on CUDA-specific block sizes, needed for the atom data padding.
+ * Returns the size of the block size requirement
*
- * \param[in] pmeGpu The PME GPU structure.
- * \returns Number of atoms in a single GPU atom data chunk.
- */
-int pme_gpu_get_atom_data_alignment(const PmeGpu* pmeGpu);
-
-/*! \libinternal \brief
- * Returns the number of atoms per chunk in the atom spline theta/dtheta data layout.
+ * The GPU version of PME requires that the coordinates array have a
+ * size divisible by the returned number.
*
- * \param[in] pmeGpu The PME GPU structure.
- * \returns Number of atoms in a single GPU atom spline data chunk.
+ * \returns Number of atoms in a single GPU atom data chunk, which
+ * determines a minimum divisior of the size of the memory allocated.
*/
-int pme_gpu_get_atoms_per_warp(const PmeGpu* pmeGpu);
+int pme_gpu_get_atom_data_block_size();
/*! \libinternal \brief
* Synchronizes the current computation, waiting for the GPU kernels/transfers to finish.
*/
bool pme_gpu_stream_query(const PmeGpu* pmeGpu);
-/*! \libinternal \brief
- * Reallocates the input coordinates buffer on the GPU (and clears the padded part if needed).
- *
- * \param[in] pmeGpu The PME GPU structure.
- *
- * Needs to be called on every DD step/in the beginning.
- */
-void pme_gpu_realloc_coordinates(const PmeGpu* pmeGpu);
-
-/*! \libinternal \brief
- * Frees the coordinates on the GPU.
- *
- * \param[in] pmeGpu The PME GPU structure.
- */
-void pme_gpu_free_coordinates(const PmeGpu* pmeGpu);
-
/*! \libinternal \brief
* Reallocates the buffer on the GPU and copies the charges/coefficients from the CPU buffer.
* Clears the padded part if needed.
* Does not need to be done for every PME computation, only whenever the local charges change.
* (So, in the beginning of the run, or on DD step).
*/
-void pme_gpu_realloc_and_copy_input_coefficients(const PmeGpu* pmeGpu, const float* h_coefficients);
+void pme_gpu_realloc_and_copy_input_coefficients(PmeGpu* pmeGpu, const float* h_coefficients);
/*! \libinternal \brief
* Frees the charges/coefficients on the GPU.
*/
void pme_gpu_sync_spread_grid(const PmeGpu* pmeGpu);
-/*! \libinternal \brief
- * Does the one-time GPU-framework specific PME initialization.
- * For CUDA, the PME stream is created with the highest priority.
- *
- * \param[in] pmeGpu The PME GPU structure.
- */
-void pme_gpu_init_internal(PmeGpu* pmeGpu);
-
-/*! \libinternal \brief
- * Destroys the PME GPU-framework specific data.
- * Should be called last in the PME GPU destructor.
- *
- * \param[in] pmeGpu The PME GPU structure.
- */
-void pme_gpu_destroy_specific(const PmeGpu* pmeGpu);
-
/*! \libinternal \brief
* Initializes the CUDA FFT structures.
*
*/
void pme_gpu_destroy_3dfft(const PmeGpu* pmeGpu);
-/* Several GPU event-based timing functions that live in pme_gpu_timings.cpp */
-
-/*! \libinternal \brief
- * Finalizes all the active PME GPU stage timings for the current computation. Should be called at the end of every computation.
- *
- * \param[in] pmeGpu The PME GPU structure.
- */
-void pme_gpu_update_timings(const PmeGpu* pmeGpu);
-
-/*! \libinternal \brief
- * Updates the internal list of active PME GPU stages (if timings are enabled).
- *
- * \param[in] pmeGpu The PME GPU data structure.
- */
-void pme_gpu_reinit_timings(const PmeGpu* pmeGpu);
-
-/*! \brief
- * Resets the PME GPU timings. To be called at the reset MD step.
- *
- * \param[in] pmeGpu The PME GPU structure.
- */
-void pme_gpu_reset_timings(const PmeGpu* pmeGpu);
-
-/*! \libinternal \brief
- * Copies the PME GPU timings to the gmx_wallclock_gpu_t structure (for log output). To be called at the run end.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \param[in] timings The gmx_wallclock_gpu_pme_t structure.
- */
-void pme_gpu_get_timings(const PmeGpu* pmeGpu, gmx_wallclock_gpu_pme_t* timings);
-
/* The PME stages themselves */
/*! \libinternal \brief
* \param[in] pmeGpu The PME GPU structure.
* \param[in,out] h_grid The host-side input and output Fourier grid buffer (used only with testing or host-side FFT)
* \param[in] gridOrdering Specifies the dimenion ordering of the complex grid. TODO: store this information?
- * \param[in] computeEnergyAndVirial Tells if the energy and virial computation should also be performed.
+ * \param[in] computeEnergyAndVirial Tells if the energy and virial computation should be performed.
*/
GPU_FUNC_QUALIFIER void pme_gpu_solve(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu),
t_complex* GPU_FUNC_ARGUMENT(h_grid),
* A GPU force gathering function.
*
* \param[in] pmeGpu The PME GPU structure.
- * \param[in] forceTreatment Tells how data in h_forces should be treated.
- * TODO: determine efficiency/balance of host/device-side
* reductions. \param[in] h_grid The host-side grid buffer (used only in testing mode)
*/
-GPU_FUNC_QUALIFIER void pme_gpu_gather(PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu),
- PmeForceOutputHandling GPU_FUNC_ARGUMENT(forceTreatment),
+GPU_FUNC_QUALIFIER void pme_gpu_gather(PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu),
const float* GPU_FUNC_ARGUMENT(h_grid)) GPU_FUNC_TERM;
-/*! \brief Return pointer to device copy of coordinate data.
- * \param[in] pmeGpu The PME GPU structure.
- * \returns Pointer to coordinate data
- */
-GPU_FUNC_QUALIFIER DeviceBuffer<float> pme_gpu_get_kernelparam_coordinates(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu))
- GPU_FUNC_TERM_WITH_RETURN(DeviceBuffer<float>{});
-
/*! \brief Sets the device pointer to coordinate data
* \param[in] pmeGpu The PME GPU structure.
* \param[in] d_x Pointer to coordinate data
*/
GPU_FUNC_QUALIFIER void pme_gpu_set_kernelparam_coordinates(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu),
- DeviceBuffer<float> GPU_FUNC_ARGUMENT(d_x)) GPU_FUNC_TERM;
+ DeviceBuffer<gmx::RVec> GPU_FUNC_ARGUMENT(d_x)) GPU_FUNC_TERM;
/*! \brief Return pointer to device copy of force data.
* \param[in] pmeGpu The PME GPU structure.
GPU_FUNC_QUALIFIER void* pme_gpu_get_kernelparam_forces(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu))
GPU_FUNC_TERM_WITH_RETURN(nullptr);
-/*! \brief Return pointer to GPU stream.
- * \param[in] pmeGpu The PME GPU structure.
- * \returns Pointer to stream object.
- */
-GPU_FUNC_QUALIFIER void* pme_gpu_get_stream(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu))
- GPU_FUNC_TERM_WITH_RETURN(nullptr);
-
-/*! \brief Return pointer to GPU context (for OpenCL builds).
- * \param[in] pmeGpu The PME GPU structure.
- * \returns Pointer to context object.
- */
-GPU_FUNC_QUALIFIER void* pme_gpu_get_context(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu))
- GPU_FUNC_TERM_WITH_RETURN(nullptr);
-
/*! \brief Return pointer to the sync object triggered after the PME force calculation completion
* \param[in] pmeGpu The PME GPU structure.
* \returns Pointer to sync object
GPU_FUNC_QUALIFIER GpuEventSynchronizer* pme_gpu_get_forces_ready_synchronizer(
const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu)) GPU_FUNC_TERM_WITH_RETURN(nullptr);
-/* The inlined convenience PME GPU status getters */
-
/*! \libinternal \brief
- * Tells if PME runs on multiple GPUs with the decomposition.
+ * Returns the PME GPU settings
*
* \param[in] pmeGpu The PME GPU structure.
- * \returns True if PME runs on multiple GPUs, false otherwise.
+ * \returns The settings for PME on GPU
*/
-inline bool pme_gpu_uses_dd(const PmeGpu* pmeGpu)
+inline const PmeGpuSettings& pme_gpu_settings(const PmeGpu* pmeGpu)
{
- return !pmeGpu->settings.useDecomposition;
+ return pmeGpu->settings;
}
/*! \libinternal \brief
- * Tells if PME performs the gathering stage on GPU.
+ * Returns the PME GPU staging object
*
* \param[in] pmeGpu The PME GPU structure.
- * \returns True if the gathering is performed on GPU, false otherwise.
+ * \returns The staging object for PME on GPU
*/
-inline bool pme_gpu_performs_gather(const PmeGpu* pmeGpu)
+inline const PmeGpuStaging& pme_gpu_staging(const PmeGpu* pmeGpu)
{
- return pmeGpu->settings.performGPUGather;
+ return pmeGpu->staging;
}
/*! \libinternal \brief
- * Tells if PME performs the FFT stages on GPU.
+ * Sets whether the PME module is running in testing mode
*
* \param[in] pmeGpu The PME GPU structure.
- * \returns True if FFT is performed on GPU, false otherwise.
- */
-inline bool pme_gpu_performs_FFT(const PmeGpu* pmeGpu)
-{
- return pmeGpu->settings.performGPUFFT;
-}
-
-/*! \libinternal \brief
- * Tells if PME performs the grid (un-)wrapping on GPU.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \returns True if (un-)wrapping is performed on GPU, false otherwise.
- */
-inline bool pme_gpu_performs_wrapping(const PmeGpu* pmeGpu)
-{
- return pmeGpu->settings.useDecomposition;
-}
-
-/*! \libinternal \brief
- * Tells if PME performs the grid solving on GPU.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \returns True if solving is performed on GPU, false otherwise.
- */
-inline bool pme_gpu_performs_solve(const PmeGpu* pmeGpu)
-{
- return pmeGpu->settings.performGPUSolve;
-}
-
-/*! \libinternal \brief
- * Enables or disables the testing mode.
- * Testing mode only implies copying all the outputs, even the intermediate ones, to the host,
- * and also makes the copies synchronous.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \param[in] testing Should the testing mode be enabled, or disabled.
+ * \param[in] testing Whether testing mode is on.
*/
inline void pme_gpu_set_testing(PmeGpu* pmeGpu, bool testing)
{
}
}
-/*! \libinternal \brief
- * Tells if PME is in the testing mode.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \returns true if testing mode is enabled, false otherwise.
- */
-inline bool pme_gpu_is_testing(const PmeGpu* pmeGpu)
-{
- return pmeGpu->settings.copyAllOutputs;
-}
-
/* A block of C++ functions that live in pme_gpu_internal.cpp */
/*! \libinternal \brief
/*! \libinternal \brief
* Returns the GPU outputs (forces, energy and virial)
*
- * \param[in] pme The PME structure.
- * \param[in] flags The combination of flags that affected this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
- * \returns The output object.
+ * \param[in] pme The PME structure.
+ * \param[in] computeEnergyAndVirial Whether the energy and virial are being computed
+ * \returns The output object.
*/
GPU_FUNC_QUALIFIER PmeOutput pme_gpu_getOutput(const gmx_pme_t& GPU_FUNC_ARGUMENT(pme),
- int GPU_FUNC_ARGUMENT(flags))
+ bool GPU_FUNC_ARGUMENT(computeEnergyAndVirial))
GPU_FUNC_TERM_WITH_RETURN(PmeOutput{});
/*! \libinternal \brief
*/
void pme_gpu_finish_computation(const PmeGpu* pmeGpu);
-//! A binary enum for spline data layout transformation
-enum class PmeLayoutTransform
-{
- GpuToHost,
- HostToGpu
-};
-
-/*! \libinternal \brief
- * Rearranges the atom spline data between the GPU and host layouts.
- * Only used for test purposes so far, likely to be horribly slow.
- *
- * \param[in] pmeGpu The PME GPU structure.
- * \param[out] atc The PME CPU atom data structure (with a single-threaded layout).
- * \param[in] type The spline data type (values or derivatives).
- * \param[in] dimIndex Dimension index.
- * \param[in] transform Layout transform type
- */
-GPU_FUNC_QUALIFIER void pme_gpu_transform_spline_atom_data(const PmeGpu* GPU_FUNC_ARGUMENT(pmeGpu),
- const PmeAtomComm* GPU_FUNC_ARGUMENT(atc),
- PmeSplineDataType GPU_FUNC_ARGUMENT(type),
- int GPU_FUNC_ARGUMENT(dimIndex),
- PmeLayoutTransform GPU_FUNC_ARGUMENT(transform)) GPU_FUNC_TERM;
-
-/*! \libinternal \brief
- * Gets a unique index to an element in a spline parameter buffer (theta/dtheta),
- * which is laid out for GPU spread/gather kernels. The index is wrt the execution block,
- * in range(0, atomsPerBlock * order * DIM).
- * This is a wrapper, only used in unit tests.
- * \param[in] order PME order
- * \param[in] splineIndex Spline contribution index (from 0 to \p order - 1)
- * \param[in] dimIndex Dimension index (from 0 to 2)
- * \param[in] atomIndex Atom index wrt the block.
- * \param[in] atomsPerWarp Number of atoms processed by a warp.
- *
- * \returns Index into theta or dtheta array using GPU layout.
- */
-int getSplineParamFullIndex(int order, int splineIndex, int dimIndex, int atomIndex, int atomsPerWarp);
-
/*! \libinternal \brief
* Get the normal/padded grid dimensions of the real-space PME grid on GPU. Only used in tests.
*
/*! \libinternal \brief
* (Re-)initializes the PME GPU data at the beginning of the run or on DLB.
*
- * \param[in,out] pme The PME structure.
- * \param[in] gpuInfo The GPU information structure.
- * \param[in] pmeGpuProgram The PME GPU program data
+ * \param[in,out] pme The PME structure.
+ * \param[in] deviceContext The GPU context.
+ * \param[in] deviceStream The GPU stream.
+ * \param[in,out] pmeGpuProgram The handle to the program/kernel data created outside (e.g. in unit tests/runner)
+ *
* \throws gmx::NotImplementedError if this generally valid PME structure is not valid for GPU runs.
*/
-GPU_FUNC_QUALIFIER void pme_gpu_reinit(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- const gmx_device_info_t* GPU_FUNC_ARGUMENT(gpuInfo),
- PmeGpuProgramHandle GPU_FUNC_ARGUMENT(pmeGpuProgram)) GPU_FUNC_TERM;
+GPU_FUNC_QUALIFIER void pme_gpu_reinit(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ const DeviceContext* GPU_FUNC_ARGUMENT(deviceContext),
+ const DeviceStream* GPU_FUNC_ARGUMENT(deviceStream),
+ const PmeGpuProgram* GPU_FUNC_ARGUMENT(pmeGpuProgram)) GPU_FUNC_TERM;
/*! \libinternal \brief
* Destroys the PME GPU data at the end of the run.
* Blocks until PME GPU tasks are completed, and gets the output forces and virial/energy
* (if they were to be computed).
*
- * \param[in] pme The PME data structure.
- * \param[in] flags The combination of flags to affect this PME computation.
- * The flags are the GMX_PME_ flags from pme.h.
- * \param[out] wcycle The wallclock counter.
- * \return The output forces, energy and virial
+ * \param[in] pme The PME data structure.
+ * \param[in] computeEnergyAndVirial Tells if the energy and virial computation should be performed.
+ * \param[out] wcycle The wallclock counter.
+ * \return The output forces, energy and virial
*/
-GPU_FUNC_QUALIFIER PmeOutput pme_gpu_wait_finish_task(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
- int GPU_FUNC_ARGUMENT(flags),
+GPU_FUNC_QUALIFIER PmeOutput pme_gpu_wait_finish_task(gmx_pme_t* GPU_FUNC_ARGUMENT(pme),
+ bool GPU_FUNC_ARGUMENT(computeEnergyAndVirial),
gmx_wallcycle* GPU_FUNC_ARGUMENT(wcycle))
GPU_FUNC_TERM_WITH_RETURN(PmeOutput{});
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
+#include "gromacs/utility/gmxassert.h"
+
#include "pme_gpu_program_impl.h"
-PmeGpuProgram::PmeGpuProgram(const gmx_device_info_t* deviceInfo) :
- impl_(std::make_unique<PmeGpuProgramImpl>(deviceInfo))
+PmeGpuProgram::PmeGpuProgram(const DeviceContext& deviceContext) :
+ impl_(std::make_unique<PmeGpuProgramImpl>(deviceContext))
{
}
PmeGpuProgram::~PmeGpuProgram() = default;
-PmeGpuProgramStorage buildPmeGpuProgram(const gmx_device_info_t* deviceInfo)
+int PmeGpuProgram::warpSize() const
+{
+ return impl_->warpSize();
+}
+
+PmeGpuProgramStorage buildPmeGpuProgram(const DeviceContext& deviceContext)
{
- if (!deviceInfo)
- {
- // This workaround is only needed for CodePath::CPU dummy in testhardwarecontexts.cpp
- return nullptr;
- }
- return std::make_unique<PmeGpuProgram>(deviceInfo);
+ return std::make_unique<PmeGpuProgram>(deviceContext);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \libinternal \file
* \brief
- * Declares PmeGpuProgram, which wrap arounds PmeGpuProgramImpl
- * to store permanent PME GPU context-derived data,
- * such as (compiled) kernel handles.
+ * Declares PmeGpuProgram
+ * to store data derived from the GPU context or devices for
+ * PME, such as (compiled) kernel handles and the warp sizes
+ * they work with.
*
* \author Aleksei Iupinov <a.yupinov@gmail.com>
* \ingroup module_ewald
#include <memory>
+class DeviceContext;
+
struct PmeGpuProgramImpl;
-struct gmx_device_info_t;
+struct DeviceInformation;
+/*! \libinternal
+ * \brief Stores PME data derived from the GPU context or devices.
+ *
+ * This includes compiled kernel handles and the warp sizes they
+ * work with.
+ */
class PmeGpuProgram
{
public:
- explicit PmeGpuProgram(const gmx_device_info_t* deviceInfo);
+ /*! \brief Construct a PME GPU program.
+ *
+ * \param[in] deviceContext GPU context.
+ */
+ explicit PmeGpuProgram(const DeviceContext& deviceContext);
+ //! Destructor
~PmeGpuProgram();
- // TODO: design getters for information inside, if needed for PME, and make this private?
+ //! Return the warp size for which the kernels were compiled
+ int warpSize() const;
+
+ // TODO: design more getters for information inside, if needed for PME, and make this private?
+ //! Private impl class
std::unique_ptr<PmeGpuProgramImpl> impl_;
};
*/
using PmeGpuProgramStorage = std::unique_ptr<PmeGpuProgram>;
-/*! \brief This is a handle for passing references to PME GPU program data.
- * TODO: it should be a const reference, but for that the PmeGpu types need to be C++
- */
-using PmeGpuProgramHandle = const PmeGpuProgram*;
-
/*! \brief
* Factory function used to build persistent PME GPU program for the device at once.
*/
-PmeGpuProgramStorage buildPmeGpuProgram(const gmx_device_info_t* /*deviceInfo*/);
+PmeGpuProgramStorage buildPmeGpuProgram(const DeviceContext& /* deviceContext */);
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "pme_gpu_program_impl.h"
-PmeGpuProgramImpl::PmeGpuProgramImpl(const gmx_device_info_t* /*unused*/) :
- warpSize(0),
+PmeGpuProgramImpl::PmeGpuProgramImpl(const DeviceContext& deviceContext) :
+ deviceContext_(deviceContext),
+ warpSize_(0),
spreadWorkGroupSize(0),
gatherWorkGroupSize(0),
solveMaxWorkGroupSize(0)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
constexpr bool c_wrapY = true;
//! PME CUDA kernels forward declarations. Kernels are documented in their respective files.
-template<const int order, const bool computeSplines, const bool spreadCharges, const bool wrapX, const bool wrapY, const bool writeGlobal, const bool orderThreads>
+template<int order, bool computeSplines, bool spreadCharges, bool wrapX, bool wrapY, bool writeGlobal, ThreadsPerAtom threadsPerAtom>
void pme_spline_and_spread_kernel(const PmeGpuCudaKernelParams kernelParams);
// Add extern declarations to inform that there will be a definition
// provided in another translation unit.
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, true>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, false>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, true>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, false>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, true>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, false>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, true>(
- const PmeGpuCudaKernelParams);
-extern template void pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, false>(
- const PmeGpuCudaKernelParams);
+// clang-format off
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void
+pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+// clang-format on
template<GridOrdering gridOrdering, bool computeEnergyAndVirial>
void pme_solve_kernel(const PmeGpuCudaKernelParams kernelParams);
// Add extern declarations to inform that there will be a definition
// provided in another translation unit.
+// clang-format off
extern template void pme_solve_kernel<GridOrdering::XYZ, false>(const PmeGpuCudaKernelParams);
-extern template void pme_solve_kernel<GridOrdering::XYZ, true>(const PmeGpuCudaKernelParams);
+extern template void pme_solve_kernel<GridOrdering::XYZ, true> (const PmeGpuCudaKernelParams);
extern template void pme_solve_kernel<GridOrdering::YZX, false>(const PmeGpuCudaKernelParams);
-extern template void pme_solve_kernel<GridOrdering::YZX, true>(const PmeGpuCudaKernelParams);
+extern template void pme_solve_kernel<GridOrdering::YZX, true> (const PmeGpuCudaKernelParams);
+// clang-format on
-template<const int order, const bool overwriteForces, const bool wrapX, const bool wrapY, const bool readGlobal, const bool orderThreads>
+template<int order, bool wrapX, bool wrapY, bool readGlobal, ThreadsPerAtom threadsPerAtom>
void pme_gather_kernel(const PmeGpuCudaKernelParams kernelParams);
// Add extern declarations to inform that there will be a definition
// provided in another translation unit.
-extern template void pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, true, true>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, false, true>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, true, true>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, false, true>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, true, false>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, false, false>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, true, false>(const PmeGpuCudaKernelParams);
-extern template void pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, false, false>(const PmeGpuCudaKernelParams);
+// clang-format off
+extern template void pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, false, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+extern template void pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+extern template void pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, false, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+// clang-format on
-PmeGpuProgramImpl::PmeGpuProgramImpl(const gmx_device_info_t*)
+PmeGpuProgramImpl::PmeGpuProgramImpl(const DeviceContext& deviceContext) :
+ deviceContext_(deviceContext)
{
// kernel parameters
- warpSize = warp_size;
+ warpSize_ = warp_size;
spreadWorkGroupSize = c_spreadMaxThreadsPerBlock;
solveMaxWorkGroupSize = c_solveMaxThreadsPerBlock;
gatherWorkGroupSize = c_gatherMaxThreadsPerBlock;
- /*!
- * Not all combinations of the splineAndSpread, spline and Spread kernels are required
+ /* Not all combinations of the splineAndSpread, spline and Spread kernels are required
* If only the spline (without the spread) then it does not make sense not to write the data to global memory
* Similarly the spread kernel (without the spline) implies that we should read the spline data from global memory
*/
- splineAndSpreadKernel =
- pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, false>;
- splineAndSpreadKernelThPerAtom4 =
- pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, true>;
- splineAndSpreadKernelWriteSplines =
- pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, false>;
- splineAndSpreadKernelWriteSplinesThPerAtom4 =
- pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, true>;
- splineKernel = pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, false>;
- splineKernelThPerAtom4 =
- pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, true>;
- spreadKernel = pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, false>;
- spreadKernelThPerAtom4 =
- pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, true>;
- gatherKernel = pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, false, false>;
- gatherKernelThPerAtom4 = pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, false, true>;
- gatherKernelReadSplines = pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, true, false>;
- gatherKernelReadSplinesThPerAtom4 = pme_gather_kernel<c_pmeOrder, true, c_wrapX, c_wrapY, true, true>;
- gatherReduceWithInputKernel = pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, false, false>;
- gatherReduceWithInputKernelThPerAtom4 =
- pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, false, true>;
- gatherReduceWithInputKernelReadSplines =
- pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, true, false>;
- gatherReduceWithInputKernelReadSplinesThPerAtom4 =
- pme_gather_kernel<c_pmeOrder, false, c_wrapX, c_wrapY, true, true>;
- solveXYZKernel = pme_solve_kernel<GridOrdering::XYZ, false>;
- solveXYZEnergyKernel = pme_solve_kernel<GridOrdering::XYZ, true>;
- solveYZXKernel = pme_solve_kernel<GridOrdering::YZX, false>;
- solveYZXEnergyKernel = pme_solve_kernel<GridOrdering::YZX, true>;
+ // clang-format off
+ splineAndSpreadKernel = pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, ThreadsPerAtom::OrderSquared>;
+ splineAndSpreadKernelThPerAtom4 = pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, false, ThreadsPerAtom::Order>;
+ splineAndSpreadKernelWriteSplines = pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>;
+ splineAndSpreadKernelWriteSplinesThPerAtom4 = pme_spline_and_spread_kernel<c_pmeOrder, true, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order>;
+ splineKernel = pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>;
+ splineKernelThPerAtom4 = pme_spline_and_spread_kernel<c_pmeOrder, true, false, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order>;
+ spreadKernel = pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>;
+ spreadKernelThPerAtom4 = pme_spline_and_spread_kernel<c_pmeOrder, false, true, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order>;
+ gatherKernel = pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, false, ThreadsPerAtom::OrderSquared>;
+ gatherKernelThPerAtom4 = pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, false, ThreadsPerAtom::Order>;
+ gatherKernelReadSplines = pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, true, ThreadsPerAtom::OrderSquared>;
+ gatherKernelReadSplinesThPerAtom4 = pme_gather_kernel<c_pmeOrder, c_wrapX, c_wrapY, true, ThreadsPerAtom::Order>;
+ solveXYZKernel = pme_solve_kernel<GridOrdering::XYZ, false>;
+ solveXYZEnergyKernel = pme_solve_kernel<GridOrdering::XYZ, true>;
+ solveYZXKernel = pme_solve_kernel<GridOrdering::YZX, false>;
+ solveYZXEnergyKernel = pme_solve_kernel<GridOrdering::YZX, true>;
+ // clang-format on
}
PmeGpuProgramImpl::~PmeGpuProgramImpl() {}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits.h"
#include "gromacs/utility/classhelpers.h"
-struct gmx_device_info_t;
+class DeviceContext;
+struct DeviceInformation;
/*! \internal
* \brief
* This also doesn't manage cuFFT/clFFT kernels, which depend on the PME grid dimensions.
*
* TODO: pass cl_context to the constructor and not create it inside.
- * See also Redmine #2522.
+ * See also Issue #2522.
*/
struct PmeGpuProgramImpl
{
/*! \brief
* This is a handle to the GPU context, which is just a dummy in CUDA,
* but is created/destroyed by this class in OpenCL.
- * TODO: Later we want to be able to own the context at a higher level and not here,
- * but this class would still need the non-owning context handle to build the kernels.
*/
- DeviceContext context;
+ const DeviceContext& deviceContext_;
//! Conveniently all the PME kernels use the same single argument type
#if GMX_GPU == GMX_GPU_CUDA
* For CUDA, this is a static value that comes from gromacs/gpu_utils/cuda_arch_utils.cuh;
* for OpenCL, we have to query it dynamically.
*/
- size_t warpSize;
+ size_t warpSize_;
//@{
/**
*/
size_t gatherWorkGroupSize;
- PmeKernelHandle gatherReduceWithInputKernel;
- PmeKernelHandle gatherReduceWithInputKernelThPerAtom4;
PmeKernelHandle gatherKernel;
PmeKernelHandle gatherKernelThPerAtom4;
- PmeKernelHandle gatherReduceWithInputKernelReadSplines;
- PmeKernelHandle gatherReduceWithInputKernelReadSplinesThPerAtom4;
PmeKernelHandle gatherKernelReadSplines;
PmeKernelHandle gatherKernelReadSplinesThPerAtom4;
//@}
PmeGpuProgramImpl() = delete;
//! Constructor for the given device
- explicit PmeGpuProgramImpl(const gmx_device_info_t* deviceInfo);
+ explicit PmeGpuProgramImpl(const DeviceContext& deviceContext);
~PmeGpuProgramImpl();
GMX_DISALLOW_COPY_AND_ASSIGN(PmeGpuProgramImpl);
+ //! Return the warp size for which the kernels were compiled
+ int warpSize() const { return warpSize_; }
+
private:
// Compiles kernels, if supported. Called by the constructor.
- void compileKernels(const gmx_device_info_t* deviceInfo);
+ void compileKernels(const DeviceInformation& deviceInfo);
};
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "pme_gpu_types_host.h"
#include "pme_grid.h"
-PmeGpuProgramImpl::PmeGpuProgramImpl(const gmx_device_info_t* deviceInfo)
+PmeGpuProgramImpl::PmeGpuProgramImpl(const DeviceContext& deviceContext) :
+ deviceContext_(deviceContext)
{
- // Context creation (which should happen outside of this class: #2522)
- cl_platform_id platformId = deviceInfo->ocl_gpu_id.ocl_platform_id;
- cl_device_id deviceId = deviceInfo->ocl_gpu_id.ocl_device_id;
- cl_context_properties contextProperties[3];
- contextProperties[0] = CL_CONTEXT_PLATFORM;
- contextProperties[1] = reinterpret_cast<cl_context_properties>(platformId);
- contextProperties[2] = 0; /* Terminates the list of properties */
-
- cl_int clError;
- context = clCreateContext(contextProperties, 1, &deviceId, nullptr, nullptr, &clError);
- if (clError != CL_SUCCESS)
- {
- const std::string errorString = gmx::formatString(
- "Failed to create context for PME on GPU #%s:\n OpenCL error %d: %s",
- deviceInfo->device_name, clError, ocl_get_error_string(clError).c_str());
- GMX_THROW(gmx::InternalError(errorString));
- }
-
+ const DeviceInformation& deviceInfo = deviceContext.deviceInfo();
// kernel parameters
- warpSize = gmx::ocl::getDeviceWarpSize(context, deviceId);
+ warpSize_ = gmx::ocl::getDeviceWarpSize(deviceContext_.context(), deviceInfo.oclDeviceId);
// TODO: for Intel ideally we'd want to set these based on the compiler warp size
// but given that we've done no tuning for Intel iGPU, this is as good as anything.
- spreadWorkGroupSize = std::min(c_spreadMaxWarpsPerBlock * warpSize, deviceInfo->maxWorkGroupSize);
- solveMaxWorkGroupSize = std::min(c_solveMaxWarpsPerBlock * warpSize, deviceInfo->maxWorkGroupSize);
- gatherWorkGroupSize = std::min(c_gatherMaxWarpsPerBlock * warpSize, deviceInfo->maxWorkGroupSize);
+ spreadWorkGroupSize = std::min(c_spreadMaxWarpsPerBlock * warpSize_, deviceInfo.maxWorkGroupSize);
+ solveMaxWorkGroupSize = std::min(c_solveMaxWarpsPerBlock * warpSize_, deviceInfo.maxWorkGroupSize);
+ gatherWorkGroupSize = std::min(c_gatherMaxWarpsPerBlock * warpSize_, deviceInfo.maxWorkGroupSize);
compileKernels(deviceInfo);
}
stat |= clReleaseKernel(splineKernel);
stat |= clReleaseKernel(spreadKernel);
stat |= clReleaseKernel(gatherKernel);
- stat |= clReleaseKernel(gatherReduceWithInputKernel);
stat |= clReleaseKernel(solveXYZKernel);
stat |= clReleaseKernel(solveXYZEnergyKernel);
stat |= clReleaseKernel(solveYZXKernel);
stat |= clReleaseKernel(solveYZXEnergyKernel);
- stat |= clReleaseContext(context);
GMX_ASSERT(stat == CL_SUCCESS,
gmx::formatString("Failed to release PME OpenCL resources %d: %s", stat,
ocl_get_error_string(stat).c_str())
* On Intel the exec width/warp is decided at compile-time and can be
* smaller than the minimum order^2 required in spread/gather ATM which
* we need to check for.
+ *
+ * Due to the one thread per atom and order=4 implementation
+ * constraints, order^2 threads should execute without synchronization
+ * needed.
*/
-static void checkRequiredWarpSize(cl_kernel kernel, const char* kernelName, const gmx_device_info_t* deviceInfo)
+static void checkRequiredWarpSize(cl_kernel kernel, const char* kernelName, const DeviceInformation& deviceInfo)
{
- if (deviceInfo->vendor_e == OCL_VENDOR_INTEL)
+ if (deviceInfo.deviceVendor == DeviceVendor::Intel)
{
- size_t kernelWarpSize = gmx::ocl::getKernelWarpSize(kernel, deviceInfo->ocl_gpu_id.ocl_device_id);
-
- if (kernelWarpSize < c_pmeSpreadGatherMinWarpSize)
+ int kernelWarpSize = gmx::ocl::getKernelWarpSize(kernel, deviceInfo.oclDeviceId);
+ const int minKernelWarpSize = c_pmeGpuOrder * c_pmeGpuOrder;
+ if (kernelWarpSize < minKernelWarpSize)
{
const std::string errorString = gmx::formatString(
"PME OpenCL kernels require >=%d execution width, but the %s kernel "
- "has been compiled for the device %s to a %zu width and therefore it can not "
+ "has been compiled for the device %s to a %d width and therefore it can not "
"execute correctly.",
- c_pmeSpreadGatherMinWarpSize, kernelName, deviceInfo->device_name, kernelWarpSize);
+ minKernelWarpSize, kernelName, deviceInfo.device_name, kernelWarpSize);
GMX_THROW(gmx::InternalError(errorString));
}
}
}
-void PmeGpuProgramImpl::compileKernels(const gmx_device_info_t* deviceInfo)
+void PmeGpuProgramImpl::compileKernels(const DeviceInformation& deviceInfo)
{
// We might consider storing program as a member variable if it's needed later
cl_program program = nullptr;
const std::string commonDefines = gmx::formatString(
"-Dwarp_size=%zd "
"-Dorder=%d "
- "-DatomsPerWarp=%zd "
"-DthreadsPerAtom=%d "
// forwarding from pme_grid.h, used for spline computation table sizes only
"-Dc_pmeMaxUnitcellShift=%f "
// forwarding PME behavior constants from pme_gpu_constants.h
- "-Dc_usePadding=%d "
"-Dc_skipNeutralAtoms=%d "
"-Dc_virialAndEnergyCount=%d "
// forwarding kernel work sizes
"-DDIM=%d -DXX=%d -DYY=%d -DZZ=%d "
// decomposition parameter placeholders
"-DwrapX=true -DwrapY=true ",
- warpSize, c_pmeGpuOrder, warpSize / c_pmeSpreadGatherThreadsPerAtom,
- c_pmeSpreadGatherThreadsPerAtom, static_cast<float>(c_pmeMaxUnitcellShift),
- static_cast<int>(c_usePadding), static_cast<int>(c_skipNeutralAtoms), c_virialAndEnergyCount,
- spreadWorkGroupSize, solveMaxWorkGroupSize, gatherWorkGroupSize, DIM, XX, YY, ZZ);
+ warpSize_, c_pmeGpuOrder, c_pmeGpuOrder * c_pmeGpuOrder,
+ static_cast<float>(c_pmeMaxUnitcellShift), static_cast<int>(c_skipNeutralAtoms),
+ c_virialAndEnergyCount, spreadWorkGroupSize, solveMaxWorkGroupSize,
+ gatherWorkGroupSize, DIM, XX, YY, ZZ);
try
{
/* TODO when we have a proper MPI-aware logging module,
the log output here should be written there */
- program = gmx::ocl::compileProgram(stderr, "gromacs/ewald", "pme_program.cl", commonDefines,
- context, deviceInfo->ocl_gpu_id.ocl_device_id,
- deviceInfo->vendor_e);
+ program = gmx::ocl::compileProgram(stderr, "gromacs/ewald", "pme_program.cl",
+ commonDefines, deviceContext_.context(),
+ deviceInfo.oclDeviceId, deviceInfo.deviceVendor);
}
catch (gmx::GromacsException& e)
{
e.prependContext(gmx::formatString("Failed to compile PME kernels for GPU #%s\n",
- deviceInfo->device_name));
+ deviceInfo.device_name));
throw;
}
}
{
const std::string errorString = gmx::formatString(
"Failed to create kernels for PME on GPU #%s:\n OpenCL error %d: %s",
- deviceInfo->device_name, clError, ocl_get_error_string(clError).c_str());
+ deviceInfo.device_name, clError, ocl_get_error_string(clError).c_str());
GMX_THROW(gmx::InternalError(errorString));
}
kernels.resize(actualKernelCount);
{
const std::string errorString = gmx::formatString(
"Failed to parse kernels for PME on GPU #%s:\n OpenCL error %d: %s",
- deviceInfo->device_name, clError, ocl_get_error_string(clError).c_str());
+ deviceInfo.device_name, clError, ocl_get_error_string(clError).c_str());
GMX_THROW(gmx::InternalError(errorString));
}
gatherKernelReadSplines = kernel;
checkRequiredWarpSize(gatherKernel, kernelNamesBuffer.data(), deviceInfo);
}
- else if (!strcmp(kernelNamesBuffer.data(), "pmeGatherReduceWithInputKernel"))
- {
- gatherReduceWithInputKernel = kernel;
- gatherReduceWithInputKernelReadSplines = kernel;
- checkRequiredWarpSize(gatherReduceWithInputKernel, kernelNamesBuffer.data(), deviceInfo);
- }
else if (!strcmp(kernelNamesBuffer.data(), "pmeSolveYZXKernel"))
{
solveYZXKernel = kernel;
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \libinternal \file
+ * \brief Defines the PME GPU settings data structures.
+ * \todo Some renaming/refactoring, which does not impair the performance:
+ * -- PmeGpuSettings -> PmeGpuTasks
+ *
+ * \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_ewald
+ */
+
+#ifndef GMX_EWALD_PME_GPU_SETTINGS_H
+#define GMX_EWALD_PME_GPU_SETTINGS_H
+
+#include "gromacs/gpu_utils/gpu_utils.h" // for GpuApiCallBehavior
+
+enum class ThreadsPerAtom : int;
+
+/*! \internal \brief
+ * The PME GPU settings structure, included in the main PME GPU structure by value.
+ */
+struct PmeGpuSettings
+{
+ /* Permanent settings set on initialization */
+ /*! \brief A boolean which tells if the solving is performed on GPU. Currently always true */
+ bool performGPUSolve;
+ /*! \brief A boolean which tells if the gathering is performed on GPU. Currently always true */
+ bool performGPUGather;
+ /*! \brief A boolean which tells if the FFT is performed on GPU. Currently true for a single MPI rank. */
+ bool performGPUFFT;
+ /*! \brief A convenience boolean which tells if PME decomposition is used. */
+ bool useDecomposition;
+ /*! \brief True if PME forces are reduced on-GPU, false if reduction is done on the CPU;
+ * in the former case transfer does not need to happen.
+ *
+ * Note that this flag may change per-step.
+ */
+ bool useGpuForceReduction;
+
+ /*! \brief A boolean which tells if any PME GPU stage should copy all of its outputs to the
+ * host. Only intended to be used by the test framework.
+ */
+ bool copyAllOutputs;
+ /*! \brief An enum which tells whether most PME GPU D2H/H2D data transfers should be synchronous. */
+ GpuApiCallBehavior transferKind;
+ /*! \brief
+ * Controls whether we use order (i.e. 4) threads per atom for the GPU
+ * or order*order (i.e. 16) threads per atom.
+ *
+ * Currently ThreadsPerAtom::Order is only supported by CUDA.
+ */
+ ThreadsPerAtom threadsPerAtom;
+ /*! \brief
+ * Currently only supported by CUDA.
+ * Controls if we should recalculate the splines in the gather or
+ * save the values in the spread and reload in the gather.
+ */
+ bool recalculateSplines;
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \libinternal \file
+ * \brief Defines the host-side PME GPU data structures.
+ * \todo Some renaming/refactoring, which does not impair the performance:
+ * -- bringing the function names up to guidelines
+ * -- PmeGpuSettings -> PmeGpuTasks
+ * -- refining GPU notation application (#2053)
+ * -- renaming coefficients to charges (?)
+ *
+ * \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_ewald
+ */
+
+#ifndef GMX_EWALD_PME_GPU_STAGING_H
+#define GMX_EWALD_PME_GPU_STAGING_H
+
+#include <vector>
+
+#include "gromacs/gpu_utils/hostallocator.h"
+#include "gromacs/math/vectypes.h"
+
+/*! \internal \brief
+ * The PME GPU intermediate buffers structure, included in the main PME GPU structure by value.
+ * Buffers are managed by the PME GPU module.
+ */
+struct PmeGpuStaging
+{
+ //! Host-side force buffer
+ gmx::PaddedHostVector<gmx::RVec> h_forces;
+
+ /*! \brief Virial and energy intermediate host-side buffer. Size is PME_GPU_VIRIAL_AND_ENERGY_COUNT. */
+ float* h_virialAndEnergy;
+ /*! \brief B-spline values intermediate host-side buffer. */
+ float* h_splineModuli;
+
+ /*! \brief Pointer to the host memory with B-spline values. Only used for host-side gather, or unit tests */
+ float* h_theta;
+ /*! \brief Pointer to the host memory with B-spline derivative values. Only used for host-side gather, or unit tests */
+ float* h_dtheta;
+ /*! \brief Pointer to the host memory with ivec atom gridline indices. Only used for host-side gather, or unit tests */
+ int* h_gridlineIndices;
+};
+
+#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "pme_gpu_types_host.h"
#include "pme_gpu_types_host_impl.h"
-/*! \brief
- * Tells if CUDA-based performance tracking is enabled for PME.
- *
- * \param[in] pmeGpu The PME GPU data structure.
- * \returns True if timings are enabled, false otherwise.
- */
-inline bool pme_gpu_timings_enabled(const PmeGpu* pmeGpu)
+bool pme_gpu_timings_enabled(const PmeGpu* pmeGpu)
{
return pmeGpu->archSpecific->useTiming;
}
{
GMX_ASSERT(PMEStageId < pmeGpu->archSpecific->timingEvents.size(),
"Wrong PME GPU timing event index");
- pmeGpu->archSpecific->timingEvents[PMEStageId].openTimingRegion(pmeGpu->archSpecific->pmeStream);
- }
-}
-
-CommandEvent* pme_gpu_fetch_timing_event(const PmeGpu* pmeGpu, size_t PMEStageId)
-{
- CommandEvent* timingEvent = nullptr;
- if (pme_gpu_timings_enabled(pmeGpu))
- {
- GMX_ASSERT(PMEStageId < pmeGpu->archSpecific->timingEvents.size(),
- "Wrong PME GPU timing event index");
- timingEvent = pmeGpu->archSpecific->timingEvents[PMEStageId].fetchNextEvent();
+ pmeGpu->archSpecific->timingEvents[PMEStageId].openTimingRegion(pmeGpu->archSpecific->pmeStream_);
}
- return timingEvent;
}
void pme_gpu_stop_timing(const PmeGpu* pmeGpu, size_t PMEStageId)
{
GMX_ASSERT(PMEStageId < pmeGpu->archSpecific->timingEvents.size(),
"Wrong PME GPU timing event index");
- pmeGpu->archSpecific->timingEvents[PMEStageId].closeTimingRegion(pmeGpu->archSpecific->pmeStream);
+ pmeGpu->archSpecific->timingEvents[PMEStageId].closeTimingRegion(pmeGpu->archSpecific->pmeStream_);
}
}
{
pmeGpu->archSpecific->activeTimers.clear();
pmeGpu->archSpecific->activeTimers.insert(gtPME_SPLINEANDSPREAD);
+ const auto& settings = pme_gpu_settings(pmeGpu);
// TODO: no separate gtPME_SPLINE and gtPME_SPREAD as they are not used currently
- if (pme_gpu_performs_FFT(pmeGpu))
+ if (settings.performGPUFFT)
{
pmeGpu->archSpecific->activeTimers.insert(gtPME_FFT_C2R);
pmeGpu->archSpecific->activeTimers.insert(gtPME_FFT_R2C);
}
- if (pme_gpu_performs_solve(pmeGpu))
+ if (settings.performGPUSolve)
{
pmeGpu->archSpecific->activeTimers.insert(gtPME_SOLVE);
}
- if (pme_gpu_performs_gather(pmeGpu))
+ if (settings.performGPUGather)
{
pmeGpu->archSpecific->activeTimers.insert(gtPME_GATHER);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_EWALD_PME_GPU_TIMINGS_H
#define GMX_EWALD_PME_GPU_TIMINGS_H
-#include "config.h"
-
-#if GMX_GPU == GMX_GPU_CUDA
-# include "gromacs/gpu_utils/gputraits.cuh"
-#elif GMX_GPU == GMX_GPU_OPENCL
-# include "gromacs/gpu_utils/gputraits_ocl.h"
-#endif
+#include <cstddef>
+struct gmx_wallclock_gpu_pme_t;
struct PmeGpu;
/*! \libinternal \brief
void pme_gpu_start_timing(const PmeGpu* pmeGpu, size_t PMEStageId);
/*! \libinternal \brief
- * Returns raw timing event from the corresponding GpuRegionTimer (if timings are enabled).
- * In CUDA result can be nullptr stub, per GpuRegionTimer implementation.
+ * Stops timing the certain PME GPU stage during a single computation (if timings are enabled).
*
* \param[in] pmeGpu The PME GPU data structure.
* \param[in] PMEStageId The PME GPU stage gtPME_ index from the enum in src/gromacs/timing/gpu_timing.h
*/
-CommandEvent* pme_gpu_fetch_timing_event(const PmeGpu* pmeGpu, size_t PMEStageId);
+void pme_gpu_stop_timing(const PmeGpu* pmeGpu, size_t PMEStageId);
+
+/*! \brief
+ * Tells if CUDA-based performance tracking is enabled for PME.
+ *
+ * \param[in] pmeGpu The PME GPU data structure.
+ * \returns True if timings are enabled, false otherwise.
+ */
+bool pme_gpu_timings_enabled(const PmeGpu* pmeGpu);
/*! \libinternal \brief
- * Stops timing the certain PME GPU stage during a single computation (if timings are enabled).
+ * Finalizes all the active PME GPU stage timings for the current computation. Should be called at the end of every computation.
+ *
+ * \param[in] pmeGpu The PME GPU structure.
+ */
+void pme_gpu_update_timings(const PmeGpu* pmeGpu);
+
+/*! \libinternal \brief
+ * Updates the internal list of active PME GPU stages (if timings are enabled).
*
* \param[in] pmeGpu The PME GPU data structure.
- * \param[in] PMEStageId The PME GPU stage gtPME_ index from the enum in src/gromacs/timing/gpu_timing.h
*/
-void pme_gpu_stop_timing(const PmeGpu* pmeGpu, size_t PMEStageId);
+void pme_gpu_reinit_timings(const PmeGpu* pmeGpu);
+
+/*! \brief
+ * Resets the PME GPU timings. To be called at the reset MD step.
+ *
+ * \param[in] pmeGpu The PME GPU structure.
+ */
+void pme_gpu_reset_timings(const PmeGpu* pmeGpu);
+
+/*! \libinternal \brief
+ * Copies the PME GPU timings to the gmx_wallclock_gpu_t structure (for log output). To be called at the run end.
+ *
+ * \param[in] pmeGpu The PME GPU structure.
+ * \param[in] timings The gmx_wallclock_gpu_pme_t structure.
+ */
+void pme_gpu_get_timings(const PmeGpu* pmeGpu, gmx_wallclock_gpu_pme_t* timings);
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
/*! \brief Electrostatics coefficient = ONE_4PI_EPS0 / pme->epsilon_r */
float elFactor;
- /*! \brief Virial and energy GPU array. Size is PME_GPU_ENERGY_AND_VIRIAL_COUNT (7) floats.
+ /*! \brief Virial and energy GPU array. Size is c_virialAndEnergyCount (7) floats.
* The element order is virxx, viryy, virzz, virxy, virxz, viryz, energy. */
HIDE_FROM_OPENCL_COMPILER(DeviceBuffer<float>) d_virialAndEnergy;
};
* The coordinates themselves change and need to be copied to the GPU for every PME computation,
* but reallocation happens only at DD.
*/
- HIDE_FROM_OPENCL_COMPILER(DeviceBuffer<float>) d_coordinates;
+ HIDE_FROM_OPENCL_COMPILER(DeviceBuffer<gmx::RVec>) d_coordinates;
/*! \brief Global GPU memory array handle with input atom charges.
* The charges only need to be reallocated and copied to the GPU at DD step.
*/
};
/*! \internal \brief
- * A single structure encompassing almost all the PME data used in GPU kernels on device.
- * This is inherited by the GPU framework-specific structure
- * (PmeGpuCudaKernelParams in pme.cuh).
- * This way, most code preparing the kernel parameters can be GPU-agnostic by casting
- * the kernel parameter data pointer to PmeGpuKernelParamsBase.
+ * A single structure encompassing all the PME data used in GPU kernels on device.
+ * To extend the list with platform-specific parameters, this can be inherited by the
+ * GPU framework-specific structure.
*/
struct PmeGpuKernelParamsBase
{
* before launching spreading.
*/
struct PmeGpuDynamicParams current;
+ /* These texture objects are only used in CUDA and are related to the grid size. */
+ /*! \brief Texture object for accessing grid.d_fractShiftsTable */
+ HIDE_FROM_OPENCL_COMPILER(DeviceTexture) fractShiftsTableTexture;
+ /*! \brief Texture object for accessing grid.d_gridlineIndicesTable */
+ HIDE_FROM_OPENCL_COMPILER(DeviceTexture) gridlineIndicesTableTexture;
};
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_gpu_program.h"
#include "gromacs/gpu_utils/clfftinitializer.h"
-#include "gromacs/gpu_utils/gpu_utils.h" // for GpuApiCallBehavior
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/math/vectypes.h"
+#include "pme_gpu_settings.h"
+#include "pme_gpu_staging.h"
+
+namespace gmx
+{
+class PmeDeviceBuffers;
+} // namespace gmx
+
#if GMX_GPU != GMX_GPU_NONE
struct PmeGpuSpecific;
#else
typedef int PmeGpuKernelParams;
#endif
-struct gmx_device_info_t;
-
-/*! \internal \brief
- * The PME GPU settings structure, included in the main PME GPU structure by value.
- */
-struct PmeGpuSettings
-{
- /* Permanent settings set on initialization */
- /*! \brief A boolean which tells if the solving is performed on GPU. Currently always true */
- bool performGPUSolve;
- /*! \brief A boolean which tells if the gathering is performed on GPU. Currently always true */
- bool performGPUGather;
- /*! \brief A boolean which tells if the FFT is performed on GPU. Currently true for a single MPI rank. */
- bool performGPUFFT;
- /*! \brief A convenience boolean which tells if PME decomposition is used. */
- bool useDecomposition;
- /*! \brief True if PME forces are reduced on-GPU, false if reduction is done on the CPU;
- * in the former case transfer does not need to happen.
- *
- * Note that this flag may change per-step.
- */
- bool useGpuForceReduction;
-
- /*! \brief A boolean which tells if any PME GPU stage should copy all of its outputs to the
- * host. Only intended to be used by the test framework.
- */
- bool copyAllOutputs;
- /*! \brief An enum which tells whether most PME GPU D2H/H2D data transfers should be synchronous. */
- GpuApiCallBehavior transferKind;
- /*! \brief Various flags for the current PME computation, corresponding to the GMX_PME_ flags in pme.h. */
- int currentFlags;
- /*! \brief
- * Currently only supported by CUDA.
- * Controls if we should use order (i.e. 4) threads per atom for the GPU
- * or order*order (i.e. 16) threads per atom.
- */
- bool useOrderThreadsPerAtom;
- /*! \brief
- * Currently only supported by CUDA.
- * Controls if we should recalculate the splines in the gather or
- * save the values in the spread and reload in the gather.
- */
- bool recalculateSplines;
-};
-
-// TODO There's little value in computing the Coulomb and LJ virial
-// separately, so we should simplify that.
-// TODO The matrices might be best as a view, but not currently
-// possible. Use mdspan?
-struct PmeOutput
-{
- gmx::ArrayRef<gmx::RVec> forces_; //!< Host staging area for PME forces
- bool haveForceOutput_ =
- false; //!< True if forces have been staged other false (when forces are reduced on the GPU).
- real coulombEnergy_ = 0; //!< Host staging area for PME coulomb energy
- matrix coulombVirial_ = { { 0 } }; //!< Host staging area for PME coulomb virial contributions
- real lennardJonesEnergy_ = 0; //!< Host staging area for PME LJ energy
- matrix lennardJonesVirial_ = { { 0 } }; //!< Host staging area for PME LJ virial contributions
-};
-
-/*! \internal \brief
- * The PME GPU intermediate buffers structure, included in the main PME GPU structure by value.
- * Buffers are managed by the PME GPU module.
- */
-struct PmeGpuStaging
-{
- //! Host-side force buffer
- gmx::PaddedHostVector<gmx::RVec> h_forces;
-
- /*! \brief Virial and energy intermediate host-side buffer. Size is PME_GPU_VIRIAL_AND_ENERGY_COUNT. */
- float* h_virialAndEnergy;
- /*! \brief B-spline values intermediate host-side buffer. */
- float* h_splineModuli;
-
- /*! \brief Pointer to the host memory with B-spline values. Only used for host-side gather, or unit tests */
- float* h_theta;
- /*! \brief Pointer to the host memory with B-spline derivative values. Only used for host-side gather, or unit tests */
- float* h_dtheta;
- /*! \brief Pointer to the host memory with ivec atom gridline indices. Only used for host-side gather, or unit tests */
- int* h_gridlineIndices;
-};
+struct DeviceInformation;
/*! \internal \brief
* The PME GPU structure for all the data copied directly from the CPU PME structure.
std::shared_ptr<PmeShared> common; // TODO: make the CPU structure use the same type
//! A handle to the program created by buildPmeGpuProgram()
- PmeGpuProgramHandle programHandle_;
+ const PmeGpuProgram* programHandle_;
//! Handle that ensures the clFFT library has been initialized once per process.
std::unique_ptr<gmx::ClfftInitializer> initializedClfftLibrary_;
PmeGpuStaging staging;
/*! \brief Number of local atoms, padded to be divisible by c_pmeAtomDataAlignment.
- * Used for kernel scheduling.
- * kernelParams.atoms.nAtoms is the actual atom count to be used for data copying.
- * TODO: this and the next member represent a memory allocation/padding properties -
- * what a container type should do ideally.
- */
- int nAtomsPadded;
- /*! \brief Number of local atoms, padded to be divisible by c_pmeAtomDataAlignment
- * if c_usePadding is true.
+ *
* Used only as a basic size for almost all the atom data allocations
* (spline parameter data is also aligned by PME_SPREADGATHER_PARTICLES_PER_WARP).
- * This should be the same as (c_usePadding ? nAtomsPadded : kernelParams.atoms.nAtoms).
* kernelParams.atoms.nAtoms is the actual atom count to be used for most data copying.
+ *
+ * TODO: memory allocation/padding properties should be handled by
+ * something like a container
*/
int nAtomsAlloc;
- /*! \brief A pointer to the device used during the execution. */
- const gmx_device_info_t* deviceInfo;
-
/*! \brief Kernel scheduling grid width limit in X - derived from deviceinfo compute capability in CUDA.
* Declared as very large int to make it useful in computations with type promotion, to avoid overflows.
* OpenCL seems to not have readily available global work size limit, so we just assign a large arbitrary constant to this instead.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/timing/gpu_timing.h" // for gtPME_EVENT_COUNT
+#include "pme_gpu_3dfft.h"
+
class GpuParallel3dFft;
/*! \internal \brief
*/
struct PmeGpuSpecific
{
- /*! \brief The GPU stream where everything related to the PME happens. */
- CommandStream pmeStream;
+ /*! \brief Constructor
+ *
+ * \param[in] deviceContext GPU device context
+ * \param[in] pmeStream GPU pme stream.
+ */
+ PmeGpuSpecific(const DeviceContext& deviceContext, const DeviceStream& pmeStream) :
+ deviceContext_(deviceContext),
+ pmeStream_(pmeStream)
+ {
+ }
/*! \brief
* A handle to the GPU context.
* but should be a constructor parameter to PmeGpu, as well as PmeGpuProgram,
* managed by high-level code.
*/
- DeviceContext context;
+ const DeviceContext& deviceContext_;
+
+ /*! \brief The GPU stream where everything related to the PME happens. */
+ const DeviceStream& pmeStream_;
/* Synchronization events */
/*! \brief Triggered after the PME Force Calculations have been completed */
/* Settings which are set at the start of the run */
/*! \brief A boolean which tells whether the complex and real grids for cu/clFFT are different or same. Currenty true. */
- bool performOutOfPlaceFFT;
+ bool performOutOfPlaceFFT = false;
/*! \brief A boolean which tells if the GPU timing events are enabled.
* False by default, can be enabled by setting the environment variable GMX_ENABLE_GPU_TIMING.
* Note: will not be reliable when multiple GPU tasks are running concurrently on the same
* device context, as CUDA events on multiple streams are untrustworthy.
*/
- bool useTiming;
+ bool useTiming = false;
//! Vector of FFT setups
std::vector<std::unique_ptr<GpuParallel3dFft>> fftSetup;
* TODO: these should live in a clean buffered container type, and be refactored in the NB/cudautils as well.
*/
/*! \brief The kernelParams.atoms.coordinates float element count (actual)*/
- int coordinatesSize;
+ int coordinatesSize = 0;
/*! \brief The kernelParams.atoms.coordinates float element count (reserved) */
- int coordinatesSizeAlloc;
+ int coordinatesSizeAlloc = 0;
/*! \brief The kernelParams.atoms.forces float element count (actual) */
- int forcesSize;
+ int forcesSize = 0;
/*! \brief The kernelParams.atoms.forces float element count (reserved) */
- int forcesSizeAlloc;
+ int forcesSizeAlloc = 0;
/*! \brief The kernelParams.atoms.gridlineIndices int element count (actual) */
- int gridlineIndicesSize;
+ int gridlineIndicesSize = 0;
/*! \brief The kernelParams.atoms.gridlineIndices int element count (reserved) */
- int gridlineIndicesSizeAlloc;
+ int gridlineIndicesSizeAlloc = 0;
/*! \brief Both the kernelParams.atoms.theta and kernelParams.atoms.dtheta float element count (actual) */
- int splineDataSize;
+ int splineDataSize = 0;
/*! \brief Both the kernelParams.atoms.theta and kernelParams.atoms.dtheta float element count (reserved) */
- int splineDataSizeAlloc;
+ int splineDataSizeAlloc = 0;
/*! \brief The kernelParams.atoms.coefficients float element count (actual) */
- int coefficientsSize;
+ int coefficientsSize = 0;
/*! \brief The kernelParams.atoms.coefficients float element count (reserved) */
- int coefficientsSizeAlloc;
+ int coefficientsSizeAlloc = 0;
/*! \brief The kernelParams.grid.splineValuesArray float element count (actual) */
- int splineValuesSize;
+ int splineValuesSize = 0;
/*! \brief The kernelParams.grid.splineValuesArray float element count (reserved) */
- int splineValuesSizeAlloc;
+ int splineValuesSizeAlloc = 0;
/*! \brief The kernelParams.grid.realGrid float element count (actual) */
- int realGridSize;
+ int realGridSize = 0;
/*! \brief The kernelParams.grid.realGrid float element count (reserved) */
- int realGridSizeAlloc;
+ int realGridSizeAlloc = 0;
/*! \brief The kernelParams.grid.fourierGrid float (not float2!) element count (actual) */
- int complexGridSize;
+ int complexGridSize = 0;
/*! \brief The kernelParams.grid.fourierGrid float (not float2!) element count (reserved) */
- int complexGridSizeAlloc;
+ int complexGridSizeAlloc = 0;
};
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
+#include <vector>
+
#include "gromacs/math/gmxcomplex.h"
+#include "gromacs/utility/alignedallocator.h"
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/defaultinitializationallocator.h"
#include "gromacs/utility/gmxmpi.h"
-#include "gromacs/utility/smalloc.h"
-#include "pme_gpu_types_host.h"
+#include "spline_vectors.h"
//! A repeat of typedef from parallel_3dfft.h
typedef struct gmx_parallel_3dfft* gmx_parallel_3dfft_t;
struct t_inputrec;
struct PmeGpu;
+enum class PmeRunMode;
+
//@{
//! Grid indices for A state for charge and Lennard-Jones C6
#define PME_GRID_QA 0
*/
#define PME_ORDER_MAX 12
-/*! \brief As gmx_pme_init, but takes most settings, except the grid/Ewald coefficients, from
- * pme_src. This is only called when the PME cut-off/grid size changes.
- */
-void gmx_pme_reinit(struct gmx_pme_t** pmedata,
- const t_commrec* cr,
- struct gmx_pme_t* pme_src,
- const t_inputrec* ir,
- const ivec grid_size,
- real ewaldcoeff_q,
- real ewaldcoeff_lj);
-
/* Temporary suppression until these structs become opaque and don't live in
* a header that is included by other headers. Also, until then I have no
FastVector<int> i;
};
-/*! \brief Helper typedef for spline vectors */
-typedef real* splinevec[DIM];
-
/*! \internal
* \brief Coefficients for theta or dtheta
*/
//! @endcond
-/*! \brief
- * Finds out if PME is currently running on GPU.
- * TODO: should this be removed eventually?
- *
- * \param[in] pme The PME structure.
- * \returns True if PME runs on GPU currently, false otherwise.
- */
-inline bool pme_gpu_active(const gmx_pme_t* pme)
-{
- return (pme != nullptr) && (pme->runMode != PmeRunMode::CPU);
-}
-
-/*! \brief Tell our PME-only node to switch to a new grid size */
-void gmx_pme_send_switchgrid(const t_commrec* cr, ivec grid_size, real ewaldcoeff_q, real ewaldcoeff_lj);
-
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
- * Copyright (c) 2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/dispersioncorrection.h"
#include "gromacs/mdlib/forcerec.h"
#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/nbnxm/nbnxm.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/timing/wallcycle.h"
+#include "gromacs/timing/walltime_accounting.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/strconvert.h"
#include "pme_internal.h"
+#include "pme_pp.h"
/*! \brief Parameters and settings for one PP-PME setup */
struct pme_setup_t
pme_lb->elimited = epmelblimMAXSCALING;
}
- if (OK && ir.ePBC != epbcNONE)
+ if (OK && ir.pbcType != PbcType::No)
{
- OK = (gmx::square(pme_lb->setup[pme_lb->cur + 1].rlistOuter) <= max_cutoff2(ir.ePBC, box));
+ OK = (gmx::square(pme_lb->setup[pme_lb->cur + 1].rlistOuter)
+ <= max_cutoff2(ir.pbcType, box));
if (!OK)
{
pme_lb->elimited = epmelblimBOX;
}
/* We always re-initialize the tables whether they are used or not */
- init_interaction_const_tables(nullptr, ic);
+ init_interaction_const_tables(nullptr, ic, ir.tabext);
Nbnxm::gpu_pme_loadbal_update_param(nbv, ic);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_EWALD_PME_LOAD_BALANCING_H
#define GMX_EWALD_PME_LOAD_BALANCING_H
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/interaction_const.h"
+#include "gromacs/math/vectypes.h"
#include "gromacs/timing/wallcycle.h"
struct nonbonded_verlet_t;
struct t_commrec;
+struct t_forcerec;
struct t_inputrec;
+struct interaction_const_t;
+struct gmx_pme_t;
class t_state;
namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gmxpre.h"
+#include "pme_only.h"
+
#include "config.h"
#include <cassert>
#include "gromacs/fileio/pdbio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/math/gmxcomplex.h"
#include "gromacs/math/units.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/mdtypes/state_propagator_data_gpu.h"
#include "gromacs/timing/cyclecounter.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/utility/smalloc.h"
#include "pme_gpu_internal.h"
-#include "pme_internal.h"
+#include "pme_output.h"
#include "pme_pp_communication.h"
/*! \brief environment variable to enable GPU P2P communication */
for (auto& pme : *pmedata)
{
GMX_ASSERT(pme, "Bad PME tuning list element pointer");
- if (pme->nkx == grid_size[XX] && pme->nky == grid_size[YY] && pme->nkz == grid_size[ZZ])
+ if (gmx_pme_grid_matches(*pme, grid_size))
{
/* Here we have found an existing PME data structure that suits us.
* However, in the GPU case, we have to reinitialize it - there's only one GPU structure.
/*! \brief Called by PME-only ranks to receive coefficients and coordinates
*
- * \param[in] pme PME data structure.
- * \param[in,out] pme_pp PME-PP communication structure.
- * \param[out] natoms Number of received atoms.
- * \param[out] box System box, if received.
- * \param[out] maxshift_x Maximum shift in X direction, if received.
- * \param[out] maxshift_y Maximum shift in Y direction, if received.
- * \param[out] lambda_q Free-energy lambda for electrostatics, if received.
- * \param[out] lambda_lj Free-energy lambda for Lennard-Jones, if received.
- * \param[out] bEnerVir Set to true if this is an energy/virial calculation step, otherwise
- * set to false. \param[out] step MD integration step number. \param[out] grid_size PME
- * grid size, if received. \param[out] ewaldcoeff_q Ewald cut-off parameter for
- * electrostatics, if received. \param[out] ewaldcoeff_lj Ewald cut-off parameter for
- * Lennard-Jones, if received. \param[in] useGpuForPme flag on whether PME is on GPU \param[in]
- * stateGpu GPU state propagator object \param[in] runMode PME run mode
+ * \param[in] pme PME data structure.
+ * \param[in,out] pme_pp PME-PP communication structure.
+ * \param[out] natoms Number of received atoms.
+ * \param[out] box System box, if received.
+ * \param[out] maxshift_x Maximum shift in X direction, if received.
+ * \param[out] maxshift_y Maximum shift in Y direction, if received.
+ * \param[out] lambda_q Free-energy lambda for electrostatics, if received.
+ * \param[out] lambda_lj Free-energy lambda for Lennard-Jones, if received.
+ * \param[out] computeEnergyAndVirial Set to true if this is an energy/virial calculation
+ * step, otherwise set to false.
+ * \param[out] step MD integration step number.
+ * \param[out] grid_size PME grid size, if received.
+ * \param[out] ewaldcoeff_q Ewald cut-off parameter for electrostatics, if received.
+ * \param[out] ewaldcoeff_lj Ewald cut-off parameter for Lennard-Jones, if received.
+ * \param[in] useGpuForPme Flag on whether PME is on GPU.
+ * \param[in] stateGpu GPU state propagator object.
+ * \param[in] runMode PME run mode.
*
- * \retval pmerecvqxX All parameters were set, chargeA and chargeB can be NULL.
- * \retval pmerecvqxFINISH No parameters were set.
- * \retval pmerecvqxSWITCHGRID Only grid_size and *ewaldcoeff were set.
- * \retval pmerecvqxRESETCOUNTERS *step was set.
+ * \retval pmerecvqxX All parameters were set, chargeA and chargeB can be NULL.
+ * \retval pmerecvqxFINISH No parameters were set.
+ * \retval pmerecvqxSWITCHGRID Only grid_size and *ewaldcoeff were set.
+ * \retval pmerecvqxRESETCOUNTERS *step was set.
*/
static int gmx_pme_recv_coeffs_coords(struct gmx_pme_t* pme,
gmx_pme_pp* pme_pp,
int* maxshift_y,
real* lambda_q,
real* lambda_lj,
- gmx_bool* bEnerVir,
+ gmx_bool* computeEnergyAndVirial,
int64_t* step,
ivec* grid_size,
real* ewaldcoeff_q,
"but PME run mode is not PmeRunMode::GPU\n");
// This rank will have its data accessed directly by PP rank, so needs to send the remote addresses.
- rvec* d_x = nullptr;
- rvec* d_f = nullptr;
-# if (GMX_GPU == GMX_GPU_CUDA) // avoid invalid cast for OpenCL
- d_x = reinterpret_cast<rvec*>(pme_gpu_get_device_x(pme));
- d_f = reinterpret_cast<rvec*>(pme_gpu_get_device_f(pme));
-# endif
- pme_pp->pmeCoordinateReceiverGpu->sendCoordinateBufferAddressToPpRanks(d_x);
- pme_pp->pmeForceSenderGpu->sendForceBufferAddressToPpRanks(d_f);
+ pme_pp->pmeCoordinateReceiverGpu->sendCoordinateBufferAddressToPpRanks(
+ stateGpu->getCoordinates());
+ pme_pp->pmeForceSenderGpu->sendForceBufferAddressToPpRanks(
+ reinterpret_cast<rvec*>(pme_gpu_get_device_f(pme)));
}
}
/* The box, FE flag and lambda are sent along with the coordinates
* */
copy_mat(cnb.box, box);
- *lambda_q = cnb.lambda_q;
- *lambda_lj = cnb.lambda_lj;
- *bEnerVir = ((cnb.flags & PP_PME_ENER_VIR) != 0U);
- *step = cnb.step;
+ *lambda_q = cnb.lambda_q;
+ *lambda_lj = cnb.lambda_lj;
+ *computeEnergyAndVirial = ((cnb.flags & PP_PME_ENER_VIR) != 0U);
+ *step = cnb.step;
/* Receive the coordinates in place */
nat = 0;
GMX_UNUSED_VALUE(maxshift_y);
GMX_UNUSED_VALUE(lambda_q);
GMX_UNUSED_VALUE(lambda_lj);
- GMX_UNUSED_VALUE(bEnerVir);
+ GMX_UNUSED_VALUE(computeEnergyAndVirial);
GMX_UNUSED_VALUE(step);
GMX_UNUSED_VALUE(grid_size);
GMX_UNUSED_VALUE(ewaldcoeff_q);
#endif
}
-int gmx_pmeonly(struct gmx_pme_t* pme,
- const t_commrec* cr,
- t_nrnb* mynrnb,
- gmx_wallcycle* wcycle,
- gmx_walltime_accounting_t walltime_accounting,
- t_inputrec* ir,
- PmeRunMode runMode)
+int gmx_pmeonly(struct gmx_pme_t* pme,
+ const t_commrec* cr,
+ t_nrnb* mynrnb,
+ gmx_wallcycle* wcycle,
+ gmx_walltime_accounting_t walltime_accounting,
+ t_inputrec* ir,
+ PmeRunMode runMode,
+ const gmx::DeviceStreamManager* deviceStreamManager)
{
- int ret;
- int natoms = 0;
- matrix box;
- real lambda_q = 0;
- real lambda_lj = 0;
- int maxshift_x = 0, maxshift_y = 0;
- real dvdlambda_q, dvdlambda_lj;
- float cycles;
- int count;
- gmx_bool bEnerVir = FALSE;
- int64_t step;
+ int ret;
+ int natoms = 0;
+ matrix box;
+ real lambda_q = 0;
+ real lambda_lj = 0;
+ int maxshift_x = 0, maxshift_y = 0;
+ real dvdlambda_q, dvdlambda_lj;
+ float cycles;
+ int count;
+ bool computeEnergyAndVirial = false;
+ int64_t step;
/* This data will only use with PME tuning, i.e. switching PME grids */
std::vector<gmx_pme_t*> pmedata;
pmedata.push_back(pme);
auto pme_pp = gmx_pme_pp_init(cr);
+
+ std::unique_ptr<gmx::StatePropagatorDataGpu> stateGpu;
// TODO the variable below should be queried from the task assignment info
- const bool useGpuForPme = (runMode == PmeRunMode::GPU) || (runMode == PmeRunMode::Mixed);
- const void* commandStream = useGpuForPme ? pme_gpu_get_device_stream(pme) : nullptr;
- const void* deviceContext = useGpuForPme ? pme_gpu_get_device_context(pme) : nullptr;
- const int paddingSize = pme_gpu_get_padding_size(pme);
+ const bool useGpuForPme = (runMode == PmeRunMode::GPU) || (runMode == PmeRunMode::Mixed);
if (useGpuForPme)
{
+ GMX_RELEASE_ASSERT(
+ deviceStreamManager != nullptr,
+ "Device stream manager can not be nullptr when using GPU in PME-only rank.");
+ GMX_RELEASE_ASSERT(deviceStreamManager->streamIsValid(gmx::DeviceStreamType::Pme),
+ "Device stream can not be nullptr when using GPU in PME-only rank");
changePinningPolicy(&pme_pp->chargeA, pme_get_pinning_policy());
changePinningPolicy(&pme_pp->x, pme_get_pinning_policy());
if (c_enableGpuPmePpComms)
{
pme_pp->pmeCoordinateReceiverGpu = std::make_unique<gmx::PmeCoordinateReceiverGpu>(
- pme_gpu_get_device_stream(pme), pme_pp->mpi_comm_mysim, pme_pp->ppRanks);
+ deviceStreamManager->stream(gmx::DeviceStreamType::Pme), pme_pp->mpi_comm_mysim,
+ pme_pp->ppRanks);
pme_pp->pmeForceSenderGpu = std::make_unique<gmx::PmeForceSenderGpu>(
- pme_gpu_get_device_stream(pme), pme_pp->mpi_comm_mysim, pme_pp->ppRanks);
+ deviceStreamManager->stream(gmx::DeviceStreamType::Pme), pme_pp->mpi_comm_mysim,
+ pme_pp->ppRanks);
}
- }
-
- std::unique_ptr<gmx::StatePropagatorDataGpu> stateGpu;
- if (useGpuForPme)
- {
// TODO: Special PME-only constructor is used here. There is no mechanism to prevent from using the other constructor here.
// This should be made safer.
stateGpu = std::make_unique<gmx::StatePropagatorDataGpu>(
- commandStream, deviceContext, GpuApiCallBehavior::Async, paddingSize, wcycle);
+ &deviceStreamManager->stream(gmx::DeviceStreamType::Pme), deviceStreamManager->context(),
+ GpuApiCallBehavior::Async, pme_gpu_get_block_size(pme), wcycle);
}
-
clear_nrnb(mynrnb);
count = 0;
/* Domain decomposition */
ivec newGridSize;
real ewaldcoeff_q = 0, ewaldcoeff_lj = 0;
- ret = gmx_pme_recv_coeffs_coords(pme, pme_pp.get(), &natoms, box, &maxshift_x,
- &maxshift_y, &lambda_q, &lambda_lj, &bEnerVir, &step,
+ ret = gmx_pme_recv_coeffs_coords(pme, pme_pp.get(), &natoms, box, &maxshift_x, &maxshift_y,
+ &lambda_q, &lambda_lj, &computeEnergyAndVirial, &step,
&newGridSize, &ewaldcoeff_q, &ewaldcoeff_lj,
useGpuForPme, stateGpu.get(), runMode);
// of pme_pp (maybe box, energy and virial, too; and likewise
// from mdatoms for the other call to gmx_pme_do), so we have
// fewer lines of code and less parameter passing.
- const int pmeFlags = GMX_PME_DO_ALL_F | (bEnerVir ? GMX_PME_CALC_ENER_VIR : 0);
+ gmx::StepWorkload stepWork;
+ stepWork.computeVirial = computeEnergyAndVirial;
+ stepWork.computeEnergy = computeEnergyAndVirial;
+ stepWork.computeForces = true;
PmeOutput output;
if (useGpuForPme)
{
- const bool boxChanged = false;
- const bool useGpuPmeForceReduction = pme_pp->useGpuDirectComm;
+ stepWork.haveDynamicBox = false;
+ stepWork.useGpuPmeFReduction = pme_pp->useGpuDirectComm;
// TODO this should be set properly by gmx_pme_recv_coeffs_coords,
// or maybe use inputrecDynamicBox(ir), at the very least - change this when this codepath is tested!
- pme_gpu_prepare_computation(pme, boxChanged, box, wcycle, pmeFlags, useGpuPmeForceReduction);
+ pme_gpu_prepare_computation(pme, box, wcycle, stepWork);
if (!pme_pp->useGpuDirectComm)
{
stateGpu->copyCoordinatesToGpu(gmx::ArrayRef<gmx::RVec>(pme_pp->x), gmx::AtomLocality::All);
auto xReadyOnDevice = nullptr;
pme_gpu_launch_spread(pme, xReadyOnDevice, wcycle);
- pme_gpu_launch_complex_transforms(pme, wcycle);
- pme_gpu_launch_gather(pme, wcycle, PmeForceOutputHandling::Set);
- output = pme_gpu_wait_finish_task(pme, pmeFlags, wcycle);
+ pme_gpu_launch_complex_transforms(pme, wcycle, stepWork);
+ pme_gpu_launch_gather(pme, wcycle);
+ output = pme_gpu_wait_finish_task(pme, computeEnergyAndVirial, wcycle);
pme_gpu_reinit_computation(pme, wcycle);
}
else
pme_pp->sigmaB.data(), box, cr, maxshift_x, maxshift_y, mynrnb, wcycle,
output.coulombVirial_, output.lennardJonesVirial_, &output.coulombEnergy_,
&output.lennardJonesEnergy_, lambda_q, lambda_lj, &dvdlambda_q,
- &dvdlambda_lj, pmeFlags);
+ &dvdlambda_lj, stepWork);
output.forces_ = pme_pp->f;
}
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ *
+ * \brief This file contains function declarations necessary for
+ * running on an MPI rank doing only PME long-ranged work.
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \inlibraryapi
+ * \ingroup module_ewald
+ */
+
+#ifndef GMX_EWALD_PME_ONLY_H
+#define GMX_EWALD_PME_ONLY_H
+
+#include <string>
+
+#include "gromacs/timing/walltime_accounting.h"
+
+struct t_commrec;
+struct t_inputrec;
+struct t_nrnb;
+struct gmx_pme_t;
+struct gmx_wallcycle;
+
+enum class PmeRunMode;
+namespace gmx
+{
+class DeviceStreamManager;
+}
+
+/*! \brief Called on the nodes that do PME exclusively */
+int gmx_pmeonly(gmx_pme_t* pme,
+ const t_commrec* cr,
+ t_nrnb* mynrnb,
+ gmx_wallcycle* wcycle,
+ gmx_walltime_accounting_t walltime_accounting,
+ t_inputrec* ir,
+ PmeRunMode runMode,
+ const gmx::DeviceStreamManager* deviceStreamManager);
+
+#endif
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \libinternal \file
+ * \brief Defines a struct useful for transferring the PME output
+ * values
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_ewald
+ */
+
+#ifndef GMX_EWALD_PME_OUTPUT_H
+#define GMX_EWALD_PME_OUTPUT_H
+
+#include "gromacs/math/vectypes.h"
+#include "gromacs/utility/arrayref.h"
+
+// TODO There's little value in computing the Coulomb and LJ virial
+// separately, so we should simplify that.
+// TODO The matrices might be best as a view, but not currently
+// possible. Use mdspan?
+struct PmeOutput
+{
+ //!< Host staging area for PME forces
+ gmx::ArrayRef<gmx::RVec> forces_;
+ //!< True if forces have been staged other false (when forces are reduced on the GPU).
+ bool haveForceOutput_ = false;
+ //!< Host staging area for PME coulomb energy
+ real coulombEnergy_ = 0;
+ //!< Host staging area for PME coulomb virial contributions
+ matrix coulombVirial_ = { { 0 } };
+ //!< Host staging area for PME LJ energy
+ real lennardJonesEnergy_ = 0;
+ //!< Host staging area for PME LJ virial contributions
+ matrix lennardJonesVirial_ = { { 0 } };
+};
+
+#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gmxpre.h"
+#include "pme_pp.h"
+
#include "config.h"
#include <cstdio>
#include "gromacs/utility/gmxmpi.h"
#include "gromacs/utility/smalloc.h"
-#include "pme_internal.h"
#include "pme_pp_communication.h"
/*! \brief Block to wait for communication to PME ranks to complete
const rvec* x,
real lambda_q,
real lambda_lj,
- gmx_bool bEnerVir,
+ bool computeEnergyAndVirial,
int64_t step,
bool useGpuPmePpComms,
bool receiveCoordinateAddressFromPme,
wallcycle_start(wcycle, ewcPP_PMESENDX);
unsigned int flags = PP_PME_COORD;
- if (bEnerVir)
+ if (computeEnergyAndVirial)
{
flags |= PP_PME_ENER_VIR;
}
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ *
+ * \brief This file contains function declarations necessary for
+ * mananging the PP side of PME-only ranks.
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_ewald
+ */
+
+#ifndef GMX_EWALD_PME_PP_H
+#define GMX_EWALD_PME_PP_H
+
+#include "gromacs/math/vectypes.h"
+#include "gromacs/utility/basedefinitions.h"
+
+struct gmx_wallcycle;
+struct interaction_const_t;
+struct t_commrec;
+struct t_forcerec;
+
+class GpuEventSynchronizer;
+
+namespace gmx
+{
+class ForceWithVirial;
+class PmePpCommGpu;
+} // namespace gmx
+
+/*! \brief Send the charges and maxshift to out PME-only node. */
+void gmx_pme_send_parameters(const t_commrec* cr,
+ const interaction_const_t* ic,
+ gmx_bool bFreeEnergy_q,
+ gmx_bool bFreeEnergy_lj,
+ real* chargeA,
+ real* chargeB,
+ real* sqrt_c6A,
+ real* sqrt_c6B,
+ real* sigmaA,
+ real* sigmaB,
+ int maxshift_x,
+ int maxshift_y);
+
+/*! \brief Send the coordinates to our PME-only node and request a PME calculation */
+void gmx_pme_send_coordinates(t_forcerec* fr,
+ const t_commrec* cr,
+ const matrix box,
+ const rvec* x,
+ real lambda_q,
+ real lambda_lj,
+ bool computeEnergyAndVirial,
+ int64_t step,
+ bool useGpuPmePpComms,
+ bool reinitGpuPmePpComms,
+ bool sendCoordinatesFromGpu,
+ GpuEventSynchronizer* coordinatesReadyOnDeviceEvent,
+ gmx_wallcycle* wcycle);
+
+/*! \brief Tell our PME-only node to finish */
+void gmx_pme_send_finish(const t_commrec* cr);
+
+/*! \brief Tell our PME-only node to reset all cycle and flop counters */
+void gmx_pme_send_resetcounters(const t_commrec* cr, int64_t step);
+
+/*! \brief PP nodes receive the long range forces from the PME nodes */
+void gmx_pme_receive_f(gmx::PmePpCommGpu* pmePpCommGpu,
+ const t_commrec* cr,
+ gmx::ForceWithVirial* forceWithVirial,
+ real* energy_q,
+ real* energy_lj,
+ real* dvdlambda_q,
+ real* dvdlambda_lj,
+ bool useGpuPmePpComms,
+ bool receivePmeForceToGpu,
+ float* pme_cycles);
+
+/*! \brief Tell our PME-only node to switch to a new grid size */
+void gmx_pme_send_switchgrid(const t_commrec* cr, ivec grid_size, real ewaldcoeff_q, real ewaldcoeff_lj);
+
+#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/classhelpers.h"
#include "gromacs/utility/gmxmpi.h"
+class DeviceContext;
+class DeviceStream;
class GpuEventSynchronizer;
namespace gmx
{
+class DeviceStreamManager;
+
/*! \libinternal
* \brief Manages communication related to GPU buffers between this
/*! \brief Creates PME-PP GPU communication object
* \param[in] comm Communicator used for simulation
* \param[in] pmeRank Rank of PME task
+ * \param[in] deviceContext GPU context.
+ * \param[in] deviceStream GPU stream.
*/
- PmePpCommGpu(MPI_Comm comm, int pmeRank);
+ PmePpCommGpu(MPI_Comm comm, int pmeRank, const DeviceContext& deviceContext, const DeviceStream& deviceStream);
~PmePpCommGpu();
/*! \brief Perform steps required when buffer size changes
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
};
/*!\brief Constructor stub. */
-PmePpCommGpu::PmePpCommGpu(MPI_Comm gmx_unused comm, int gmx_unused pmeRank) : impl_(nullptr)
+PmePpCommGpu::PmePpCommGpu(MPI_Comm /* comm */,
+ int /* pmeRank */,
+ const DeviceContext& /* deviceContext */,
+ const DeviceStream& /* deviceStream */) :
+ impl_(nullptr)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
PmePpCommGpu::~PmePpCommGpu() = default;
/*!\brief init PME-PP GPU communication stub */
-void PmePpCommGpu::reinit(int gmx_unused size)
+void PmePpCommGpu::reinit(int /* size */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication initialization was called instead of the "
"correct implementation.");
}
-void PmePpCommGpu::receiveForceFromPmeCudaDirect(void gmx_unused* recvPtr,
- int gmx_unused recvSize,
- bool gmx_unused receivePmeForceToGpu)
+void PmePpCommGpu::receiveForceFromPmeCudaDirect(void* /* recvPtr */,
+ int /* recvSize */,
+ bool /* receivePmeForceToGpu */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
-void PmePpCommGpu::sendCoordinatesToPmeCudaDirect(void gmx_unused* sendPtr,
- int gmx_unused sendSize,
- bool gmx_unused sendPmeCoordinatesFromGpu,
- GpuEventSynchronizer gmx_unused* coordinatesOnDeviceEvent)
+void PmePpCommGpu::sendCoordinatesToPmeCudaDirect(void* /* sendPtr */,
+ int /* sendSize */,
+ bool /* sendPmeCoordinatesFromGpu */,
+ GpuEventSynchronizer* /* coordinatesOnDeviceEvent */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
}
void* PmePpCommGpu::getGpuForceStagingPtr()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
return nullptr;
void* PmePpCommGpu::getForcesReadySynchronizer()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for PME-PP GPU communication was called instead of the correct "
"implementation.");
return nullptr;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/devicebuffer.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
#include "gromacs/utility/gmxmpi.h"
namespace gmx
{
-PmePpCommGpu::Impl::Impl(MPI_Comm comm, int pmeRank) : comm_(comm), pmeRank_(pmeRank)
+PmePpCommGpu::Impl::Impl(MPI_Comm comm,
+ int pmeRank,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream) :
+ deviceContext_(deviceContext),
+ pmePpCommStream_(deviceStream),
+ comm_(comm),
+ pmeRank_(pmeRank)
{
GMX_RELEASE_ASSERT(
GMX_THREAD_MPI,
"PME-PP GPU Communication is currently only supported with thread-MPI enabled");
- cudaStreamCreate(&pmePpCommStream_);
}
PmePpCommGpu::Impl::~Impl() = default;
MPI_Recv(&remotePmeFBuffer_, sizeof(void**), MPI_BYTE, pmeRank_, 0, comm_, MPI_STATUS_IGNORE);
// Reallocate buffer used for staging PME force on GPU
- reallocateDeviceBuffer(&d_pmeForces_, size, &d_pmeForcesSize_, &d_pmeForcesSizeAlloc_, nullptr);
+ reallocateDeviceBuffer(&d_pmeForces_, size, &d_pmeForcesSize_, &d_pmeForcesSizeAlloc_, deviceContext_);
#else
GMX_UNUSED_VALUE(size);
#endif
// Pull force data from remote GPU
void* pmeForcePtr = receivePmeForceToGpu ? static_cast<void*>(d_pmeForces_) : recvPtr;
cudaError_t stat = cudaMemcpyAsync(pmeForcePtr, remotePmeFBuffer_, recvSize * DIM * sizeof(float),
- cudaMemcpyDefault, pmePpCommStream_);
+ cudaMemcpyDefault, pmePpCommStream_.stream());
CU_RET_ERR(stat, "cudaMemcpyAsync on Recv from PME CUDA direct data transfer failed");
if (receivePmeForceToGpu)
{
// Ensure CPU waits for PME forces to be copied before reducing
// them with other forces on the CPU
- cudaStreamSynchronize(pmePpCommStream_);
+ cudaStreamSynchronize(pmePpCommStream_.stream());
}
#else
GMX_UNUSED_VALUE(recvPtr);
coordinatesReadyOnDeviceEvent->enqueueWaitEvent(pmePpCommStream_);
cudaError_t stat = cudaMemcpyAsync(remotePmeXBuffer_, sendPtr, sendSize * DIM * sizeof(float),
- cudaMemcpyDefault, pmePpCommStream_);
+ cudaMemcpyDefault, pmePpCommStream_.stream());
CU_RET_ERR(stat, "cudaMemcpyAsync on Send to PME CUDA direct data transfer failed");
// Record and send event to allow PME task to sync to above transfer before commencing force calculations
return static_cast<void*>(&forcesReadySynchronizer_);
}
-PmePpCommGpu::PmePpCommGpu(MPI_Comm comm, int pmeRank) : impl_(new Impl(comm, pmeRank)) {}
+PmePpCommGpu::PmePpCommGpu(MPI_Comm comm,
+ int pmeRank,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream) :
+ impl_(new Impl(comm, pmeRank, deviceContext, deviceStream))
+{
+}
PmePpCommGpu::~PmePpCommGpu() = default;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
public:
/*! \brief Creates PME-PP GPU communication object.
+ *
* \param[in] comm Communicator used for simulation
* \param[in] pmeRank Rank of PME task
+ * \param[in] deviceContext GPU context.
+ * \param[in] deviceStream GPU stream.
*/
- Impl(MPI_Comm comm, int pmeRank);
+ Impl(MPI_Comm comm, int pmeRank, const DeviceContext& deviceContext, const DeviceStream& deviceStream);
~Impl();
/*! \brief Perform steps required when buffer size changes
void* getForcesReadySynchronizer();
private:
- //! CUDA stream used for the communication operations in this class
- cudaStream_t pmePpCommStream_ = nullptr;
+ //! GPU context handle (not used in CUDA)
+ const DeviceContext& deviceContext_;
+ //! Handle for CUDA stream used for the communication operations in this class
+ const DeviceStream& pmePpCommStream_;
//! Remote location of PME coordinate data buffer
void* remotePmeXBuffer_ = nullptr;
//! Remote location of PME force data buffer
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
// Assert placeholders, to not rip them out from OpenCL implementation - hopefully they come in handy some day with OpenCL 2
-#define static_assert(a, b)
#define assert(a)
#define PmeOpenCLKernelParams PmeGpuKernelParamsBase
/* SPREAD/SPLINE */
#define atomsPerBlock (c_spreadWorkGroupSize / threadsPerAtom)
+#define atomsPerWarp (warp_size / threadsPerAtom)
// spline/spread fused
#define computeSplines 1
#define atomsPerBlock (c_gatherWorkGroupSize / threadsPerAtom)
// gather
-#define overwriteForces 1
#define CUSTOMIZED_KERNEL_NAME(x) pmeGatherKernel
#include "pme_gather.clh"
-#undef overwriteForces
-#undef CUSTOMIZED_KERNEL_NAME
-
-// gather with reduction
-#define overwriteForces 0
-#define CUSTOMIZED_KERNEL_NAME(x) pmeGatherReduceWithInputKernel
-#include "pme_gather.clh"
-#undef overwriteForces
#undef CUSTOMIZED_KERNEL_NAME
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \author Aleksei Iupinov <a.yupinov@gmail.com>
*/
-#include "pme_gpu_types.h"
#include "gromacs/gpu_utils/vectype_ops.clh"
+#include "pme_gpu_types.h"
+
/*! \brief
* PME complex grid solver kernel function.
* Please see the file description for additional defines which this kernel expects.
__global float2* __restrict__ gm_grid)
{
/* This kernel supports 2 different grid dimension orderings: YZX and XYZ */
- int majorDim, middleDim, minorDim;
+ int majorDim;
+ int middleDim;
+ int minorDim;
if (gridOrdering == YZX)
{
majorDim = YY;
gm_splineModuli + kernelParams.grid.splineValuesOffset[minorDim];
/* Various grid sizes and indices */
- const int localOffsetMinor = 0, localOffsetMajor = 0, localOffsetMiddle = 0; // unused
- const int localSizeMinor = kernelParams.grid.complexGridSizePadded[minorDim];
- const int localSizeMiddle = kernelParams.grid.complexGridSizePadded[middleDim];
- const int localCountMiddle = kernelParams.grid.complexGridSize[middleDim];
- const int localCountMinor = kernelParams.grid.complexGridSize[minorDim];
- const int nMajor = kernelParams.grid.realGridSize[majorDim];
- const int nMiddle = kernelParams.grid.realGridSize[middleDim];
- const int nMinor = kernelParams.grid.realGridSize[minorDim];
- const int maxkMajor = (nMajor + 1) / 2; // X or Y
- const int maxkMiddle = (nMiddle + 1) / 2; // Y OR Z => only check for !YZX
- const int maxkMinor = (nMinor + 1) / 2; // Z or X => only check for YZX
+ const int localOffsetMinor = 0; // unused
+ const int localOffsetMajor = 0; // unused
+ const int localOffsetMiddle = 0; // unused
+ const int localSizeMinor = kernelParams.grid.complexGridSizePadded[minorDim];
+ const int localSizeMiddle = kernelParams.grid.complexGridSizePadded[middleDim];
+ const int localCountMiddle = kernelParams.grid.complexGridSize[middleDim];
+ const int localCountMinor = kernelParams.grid.complexGridSize[minorDim];
+ const int nMajor = kernelParams.grid.realGridSize[majorDim];
+ const int nMiddle = kernelParams.grid.realGridSize[middleDim];
+ const int nMinor = kernelParams.grid.realGridSize[minorDim];
+ const int maxkMajor = (nMajor + 1) / 2; // X or Y
+ const int maxkMiddle = (nMiddle + 1) / 2; // Y OR Z => only check for !YZX
+ const int maxkMinor = (nMinor + 1) / 2; // Z or X => only check for YZX
/* Each thread works on one cell of the Fourier space complex 3D grid (gm_grid).
* Each block handles up to c_solveMaxWorkGroupSize cells -
const int gridLineIndex = threadLocalId / gridLineSize;
const int gridLineCellIndex = threadLocalId - gridLineSize * gridLineIndex;
const int gridLinesPerBlock = max((int)(get_local_size(XX)) / gridLineSize, 1);
- const int activeWarps = (get_local_size(XX) / warp_size);
- const int indexMinor = get_group_id(XX) * get_local_size(XX) + gridLineCellIndex;
- const int indexMiddle = get_group_id(YY) * gridLinesPerBlock + gridLineIndex;
- const int indexMajor = get_group_id(ZZ);
+ const int activeWarps = ((int)get_local_size(XX) / warp_size);
+ assert((get_group_id(XX) * get_local_size(XX)) < MAX_INT);
+ const int indexMinor = (int)get_group_id(XX) * (int)get_local_size(XX) + gridLineCellIndex;
+ const int indexMiddle = (int)get_group_id(YY) * gridLinesPerBlock + gridLineIndex;
+ const int indexMajor = (int)get_group_id(ZZ);
/* Optional outputs */
- float energy = 0.0f;
- float virxx = 0.0f;
- float virxy = 0.0f;
- float virxz = 0.0f;
- float viryy = 0.0f;
- float viryz = 0.0f;
- float virzz = 0.0f;
+ float energy = 0.0F;
+ float virxx = 0.0F;
+ float virxy = 0.0F;
+ float virxz = 0.0F;
+ float viryy = 0.0F;
+ float viryz = 0.0F;
+ float virzz = 0.0F;
assert(indexMajor < kernelParams.grid.complexGridSize[majorDim]);
if ((indexMiddle < localCountMiddle) & (indexMinor < localCountMinor)
const int kMajor = indexMajor + localOffsetMajor;
/* Checking either X in XYZ, or Y in YZX cases */
- const float mMajor = (kMajor < maxkMajor) ? kMajor : (kMajor - nMajor);
+ const float mMajor = (float)((kMajor < maxkMajor) ? kMajor : (kMajor - nMajor));
const int kMiddle = indexMiddle + localOffsetMiddle;
- float mMiddle = kMiddle;
+ float mMiddle = (float)kMiddle;
/* Checking Y in XYZ case */
if (gridOrdering == XYZ)
{
- mMiddle = (kMiddle < maxkMiddle) ? kMiddle : (kMiddle - nMiddle);
+ mMiddle = (float)((kMiddle < maxkMiddle) ? kMiddle : (kMiddle - nMiddle));
}
const int kMinor = localOffsetMinor + indexMinor;
- float mMinor = kMinor;
+ float mMinor = (float)kMinor;
/* Checking X in YZX case */
if (gridOrdering == YZX)
{
- mMinor = (kMinor < maxkMinor) ? kMinor : (kMinor - nMinor);
+ mMinor = (float)((kMinor < maxkMinor) ? kMinor : (kMinor - nMinor));
}
/* We should skip the k-space point (0,0,0) */
const bool notZeroPoint = (kMinor > 0) | (kMajor > 0) | (kMiddle > 0);
- float mX, mY, mZ;
+ float mX;
+ float mY;
+ float mZ;
if (gridOrdering == YZX)
{
mX = mMinor;
}
/* 0.5 correction factor for the first and last components of a Z dimension */
- float corner_fac = 1.0f;
+ float corner_fac = 1.0F;
+ const float z_corner_fac = 0.5F;
if (gridOrdering == YZX)
{
if ((kMiddle == 0) | (kMiddle == maxkMiddle))
{
- corner_fac = 0.5f;
+ corner_fac = z_corner_fac;
}
}
if (gridOrdering == XYZ)
{
if ((kMinor == 0) | (kMinor == maxkMinor))
{
- corner_fac = 0.5f;
+ corner_fac = z_corner_fac;
}
}
+ mZ * kernelParams.current.recipBox[ZZ][ZZ];
const float m2k = mhxk * mhxk + mhyk * mhyk + mhzk * mhzk;
- assert(m2k != 0.0f);
+ assert(m2k != 0.0F);
const float denom = m2k * M_PI_F * kernelParams.current.boxVolume * gm_splineValueMajor[kMajor]
* gm_splineValueMiddle[kMiddle] * gm_splineValueMinor[kMinor];
assert(isfinite(denom));
- assert(denom != 0.0f);
+ assert(denom != 0.0F);
const float tmp1 = exp(-kernelParams.grid.ewaldFactor * m2k);
const float etermk = kernelParams.constants.elFactor * tmp1 / denom;
if (computeEnergyAndVirial)
{
const float tmp1k =
- 2.0f * (gridValue.x * oldGridValue.x + gridValue.y * oldGridValue.y);
+ 2.0F * (gridValue.x * oldGridValue.x + gridValue.y * oldGridValue.y);
- const float vfactor = (kernelParams.grid.ewaldFactor + 1.0f / m2k) * 2.0f;
+ const float vfactor = (kernelParams.grid.ewaldFactor + 1.0F / m2k) * 2.0F;
const float ets2 = corner_fac * tmp1k;
energy = ets2;
sm_virialAndEnergy[2 * warp_size + lane] = virzz;
sm_virialAndEnergy[3 * warp_size + lane] = virxy;
sm_virialAndEnergy[4 * warp_size + lane] = virxz;
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
sm_virialAndEnergy[5 * warp_size + lane] = viryz;
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
sm_virialAndEnergy[6 * warp_size + lane] = energy;
}
barrier(CLK_LOCAL_MEM_FENCE);
atomicAdd_l_f(sm_virialAndEnergy + 2 * warp_size + lane, virzz);
atomicAdd_l_f(sm_virialAndEnergy + 3 * warp_size + lane, virxy);
atomicAdd_l_f(sm_virialAndEnergy + 4 * warp_size + lane, virxz);
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
atomicAdd_l_f(sm_virialAndEnergy + 5 * warp_size + lane, viryz);
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
atomicAdd_l_f(sm_virialAndEnergy + 6 * warp_size + lane, energy);
}
barrier(CLK_LOCAL_MEM_FENCE);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/smalloc.h"
#include "pme_internal.h"
+#include "pme_output.h"
#if GMX_SIMD_HAVE_REAL
/* Turn on arbitrary width SIMD intrinsics for PME solve */
using PME_T = real;
#endif
-int solve_pme_yzx(const gmx_pme_t* pme, t_complex* grid, real vol, gmx_bool bEnerVir, int nthread, int thread)
+int solve_pme_yzx(const gmx_pme_t* pme, t_complex* grid, real vol, bool computeEnergyAndVirial, int nthread, int thread)
{
/* do recip sum over local cells in grid */
/* y major, z middle, x minor or continuous */
}
kxend = local_offset[XX] + local_ndata[XX];
- if (bEnerVir)
+ if (computeEnergyAndVirial)
{
/* More expensive inner loop, especially because of the storage
* of the mh elements in array's.
}
}
- if (bEnerVir)
+ if (computeEnergyAndVirial)
{
/* Update virial with local values.
* The virial is symmetric by definition.
return local_ndata[YY] * local_ndata[XX];
}
-int solve_pme_lj_yzx(const gmx_pme_t* pme, t_complex** grid, gmx_bool bLB, real vol, gmx_bool bEnerVir, int nthread, int thread)
+int solve_pme_lj_yzx(const gmx_pme_t* pme,
+ t_complex** grid,
+ gmx_bool bLB,
+ real vol,
+ bool computeEnergyAndVirial,
+ int nthread,
+ int thread)
{
/* do recip sum over local cells in grid */
/* y major, z middle, x minor or continuous */
kxstart = local_offset[XX];
kxend = local_offset[XX] + local_ndata[XX];
- if (bEnerVir)
+ if (computeEnergyAndVirial)
{
/* More expensive inner loop, especially because of the
* storage of the mh elements in array's. Because x is the
}
}
}
- if (bEnerVir)
+ if (computeEnergyAndVirial)
{
work->vir_lj[XX][XX] = 0.25 * virxx;
work->vir_lj[YY][YY] = 0.25 * viryy;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
void get_pme_ener_vir_lj(pme_solve_work_t* work, int nthread, PmeOutput* output);
-int solve_pme_yzx(const gmx_pme_t* pme, t_complex* grid, real vol, gmx_bool bEnerVir, int nthread, int thread);
+int solve_pme_yzx(const gmx_pme_t* pme, t_complex* grid, real vol, bool computeEnergyAndVirial, int nthread, int thread);
int solve_pme_lj_yzx(const gmx_pme_t* pme,
t_complex** grid,
gmx_bool bLB,
real vol,
- gmx_bool bEnerVir,
+ bool computeEnergyAndVirial,
int nthread,
int thread);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \author Aleksei Iupinov <a.yupinov@gmail.com>
*/
-#include "pme_gpu_types.h"
-#include "pme_gpu_utils.clh"
#include "gromacs/gpu_utils/vectype_ops.clh"
+#include "pme_gpu_types.h"
+#include "pme_gpu_calculate_splines.clh"
+
/*
* This define affects the spline calculation behaviour in the kernel.
* 0: a single GPU thread handles a single dimension of a single particle (calculating and storing
/*! \brief
* General purpose function for loading atom-related data from global to shared memory.
*
- * \param[in] kernelParams Input PME GPU data in constant memory.
* \param[out] sm_destination Local memory array for output.
* \param[in] gm_source Global memory array for input.
* \param[in] dataCountPerAtom Number of data elements per single atom (e.g. DIM for an rvec coordinates array).
*
*/
-inline void pme_gpu_stage_atom_data(const struct PmeOpenCLKernelParams kernelParams,
- __local float* __restrict__ sm_destination,
+inline void pme_gpu_stage_atom_data(__local float* __restrict__ sm_destination,
__global const float* __restrict__ gm_source,
const int dataCountPerAtom)
{
- const size_t threadLocalIndex =
- ((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0) + get_local_id(0));
- const size_t localIndex = threadLocalIndex;
- const size_t globalIndexBase = get_group_id(XX) * atomsPerBlock * dataCountPerAtom;
- const size_t globalIndex = globalIndexBase + localIndex;
- const int globalCheck =
- pme_gpu_check_atom_data_index(globalIndex, kernelParams.atoms.nAtoms * dataCountPerAtom);
- if ((localIndex < atomsPerBlock * dataCountPerAtom) & globalCheck)
+ assert((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0) + get_local_id(0)
+ < MAX_INT);
+ const int threadLocalIndex =
+ (int)((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0)
+ + get_local_id(0));
+ const int localIndex = threadLocalIndex;
+ const int globalIndexBase = (int)get_group_id(XX) * atomsPerBlock * dataCountPerAtom;
+ const int globalIndex = globalIndexBase + localIndex;
+ if (localIndex < atomsPerBlock * dataCountPerAtom)
{
assert(isfinite(float(gm_source[globalIndex])));
sm_destination[localIndex] = gm_source[globalIndex];
* \param[in] gm_fractShiftsTable Atom fractional coordinates correction table
* \param[in] gm_gridlineIndicesTable Atom fractional coordinates correction table
*/
-inline void calculate_splines(const struct PmeOpenCLKernelParams kernelParams,
- const int atomIndexOffset,
- __local const float* __restrict__ sm_coordinates,
- __local const float* __restrict__ sm_coefficients,
- __local float* __restrict__ sm_theta,
- __local int* __restrict__ sm_gridlineIndices,
- __local float* __restrict__ sm_fractCoords,
- __global float* __restrict__ gm_theta,
- __global float* __restrict__ gm_dtheta,
- __global int* __restrict__ gm_gridlineIndices,
- __global const float* __restrict__ gm_fractShiftsTable,
- __global const int* __restrict__ gm_gridlineIndicesTable)
+gmx_opencl_inline void calculate_splines(const struct PmeOpenCLKernelParams kernelParams,
+ const int atomIndexOffset,
+ __local const float* __restrict__ sm_coordinates,
+ __local const float* __restrict__ sm_coefficients,
+ __local float* __restrict__ sm_theta,
+ __local int* __restrict__ sm_gridlineIndices,
+ __local float* __restrict__ sm_fractCoords,
+ __global float* __restrict__ gm_theta,
+ __global float* __restrict__ gm_dtheta,
+ __global int* __restrict__ gm_gridlineIndices,
+ __global const float* __restrict__ gm_fractShiftsTable,
+ __global const int* __restrict__ gm_gridlineIndicesTable)
{
/* Thread index w.r.t. block */
+ assert((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0) + get_local_id(0)
+ < MAX_INT);
const int threadLocalIndex =
- ((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0) + get_local_id(0));
+ (int)((get_local_id(2) * get_local_size(1) + get_local_id(1)) * get_local_size(0)
+ + get_local_id(0));
/* Warp index w.r.t. block - could probably be obtained easier? */
const int warpIndex = threadLocalIndex / warp_size;
/* Thread index w.r.t. warp */
/* Atom index w.r.t. block/shared memory */
const int atomIndexLocal = warpIndex * atomsPerWarp + atomWarpIndex;
- /* Atom index w.r.t. global memory */
- const int atomIndexGlobal = atomIndexOffset + atomIndexLocal;
/* Spline contribution index in one dimension */
const int orderIndex = threadWarpIndex / (atomsPerWarp * DIM);
/* Dimension index */
# define SPLINE_DATA(i) (*SPLINE_DATA_PTR(i))
const int localCheck = (dimIndex < DIM) && (orderIndex < (PME_GPU_PARALLEL_SPLINE ? order : 1));
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
- if (localCheck && globalCheck)
+ if (localCheck)
{
/* Indices interpolation */
if (orderIndex == 0)
{
- int tableIndex, tInt;
- float n, t;
+ int tableIndex;
+ int tInt;
+ float n;
+ float t;
const float3 x = vload3(atomIndexLocal, sm_coordinates);
/* Accessing fields in fshOffset/nXYZ/recipbox/... with dimIndex offset
.z
* kernelParams.current.recipBox[dimIndex][ZZ];
break;
+ default:
+ assert(false);
+ return;
+ break;
}
const float shift = c_pmeMaxUnitcellShift;
/* Fractional coordinates along box vectors, adding a positive shift to ensure t is positive for triclinic boxes */
t = (t + shift) * n;
tInt = (int)t;
- sm_fractCoords[sharedMemoryIndex] = t - tInt;
+ sm_fractCoords[sharedMemoryIndex] = t - (float)tInt;
tableIndex += tInt;
assert(tInt >= 0);
assert(tInt < c_pmeNeighborUnitcellCount * n);
assert(isfinite(dr));
/* dr is relative offset from lower cell limit */
- *SPLINE_DATA_PTR(order - 1) = 0.0f;
+ *SPLINE_DATA_PTR(order - 1) = 0.0F;
*SPLINE_DATA_PTR(1) = dr;
- *SPLINE_DATA_PTR(0) = 1.0f - dr;
+ *SPLINE_DATA_PTR(0) = 1.0F - dr;
# pragma unroll order
for (int k = 3; k < order; k++)
{
- div = 1.0f / (k - 1.0f);
+ div = 1.0F / ((float)k - 1.0F);
*SPLINE_DATA_PTR(k - 1) = div * dr * SPLINE_DATA(k - 2);
# pragma unroll
for (int l = 1; l < (k - 1); l++)
{
- *SPLINE_DATA_PTR(k - l - 1) = div
- * ((dr + l) * SPLINE_DATA(k - l - 2)
- + (k - l - dr) * SPLINE_DATA(k - l - 1));
+ *SPLINE_DATA_PTR(k - l - 1) =
+ div
+ * ((dr + (float)l) * SPLINE_DATA(k - l - 2)
+ + ((float)k - (float)l - dr) * SPLINE_DATA(k - l - 1));
}
- *SPLINE_DATA_PTR(0) = div * (1.0f - dr) * SPLINE_DATA(0);
+ *SPLINE_DATA_PTR(0) = div * (1.0F - dr) * SPLINE_DATA(0);
}
const int thetaIndexBase = getSplineParamIndexBase(warpIndex, atomWarpIndex);
const int thetaIndex = getSplineParamIndex(thetaIndexBase, dimIndex, o);
const int thetaGlobalIndex = thetaGlobalOffsetBase + thetaIndex;
- const float dtheta = ((o > 0) ? SPLINE_DATA(o - 1) : 0.0f) - SPLINE_DATA(o);
+ const float dtheta = ((o > 0) ? SPLINE_DATA(o - 1) : 0.0F) - SPLINE_DATA(o);
assert(isfinite(dtheta));
gm_dtheta[thetaGlobalIndex] = dtheta;
}
- div = 1.0f / (order - 1.0f);
+ div = 1.0F / (order - 1.0F);
*SPLINE_DATA_PTR(order - 1) = div * dr * SPLINE_DATA(order - 2);
# pragma unroll
for (int k = 1; k < (order - 1); k++)
{
*SPLINE_DATA_PTR(order - k - 1) = div
- * ((dr + k) * SPLINE_DATA(order - k - 2)
+ * ((dr + (float)k) * SPLINE_DATA(order - k - 2)
+ (order - k - dr) * SPLINE_DATA(order - k - 1));
}
- *SPLINE_DATA_PTR(0) = div * (1.0f - dr) * SPLINE_DATA(0);
+ *SPLINE_DATA_PTR(0) = div * (1.0F - dr) * SPLINE_DATA(0);
/* Storing the spline values (theta) */
# if !PME_GPU_PARALLEL_SPLINE
* Second stage of the whole kernel.
*
* \param[in] kernelParams Input PME GPU data in constant memory.
- * \param[in] atomIndexOffset Starting atom index for the execution block w.r.t. global
- * memory. \param[in] sm_coefficients Atom coefficents/charges in the shared memory. \param[in]
- * sm_gridlineIndices Atom gridline indices in the shared memory. \param[in] sm_theta Atom spline
- * values in the shared memory. \param[out] gm_grid Global 3D grid for spreading.
+ * \param[in] sm_coefficients Atom coefficents/charges in the shared memory.
+ * \param[in] sm_gridlineIndices Atom gridline indices in the shared memory.
+ * \param[in] sm_theta Atom spline values in the shared memory.
+ * \param[out] gm_grid Global 3D grid for spreading.
*/
-inline void spread_charges(const struct PmeOpenCLKernelParams kernelParams,
- int atomIndexOffset,
- __local const float* __restrict__ sm_coefficients,
- __local const int* __restrict__ sm_gridlineIndices,
- __local const float* __restrict__ sm_theta,
- __global float* __restrict__ gm_grid)
+gmx_opencl_inline void spread_charges(const struct PmeOpenCLKernelParams kernelParams,
+ __local const float* __restrict__ sm_coefficients,
+ __local const int* __restrict__ sm_gridlineIndices,
+ __local const float* __restrict__ sm_theta,
+ __global float* __restrict__ gm_grid)
{
const int nx = kernelParams.grid.realGridSize[XX];
const int ny = kernelParams.grid.realGridSize[YY];
const int pny = kernelParams.grid.realGridSizePadded[YY];
const int pnz = kernelParams.grid.realGridSizePadded[ZZ];
- const int offx = 0, offy = 0, offz = 0; // unused for now
+ const int offx = 0;
+ const int offy = 0;
+ const int offz = 0;
- const int atomIndexLocal = get_local_id(ZZ);
- const int atomIndexGlobal = atomIndexOffset + atomIndexLocal;
+ const int atomIndexLocal = get_local_id(ZZ);
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
const int chargeCheck = pme_gpu_check_atom_charge(sm_coefficients[atomIndexLocal]);
- if (chargeCheck & globalCheck)
+ if (chargeCheck)
{
// Spline Y/Z coordinates
const int ithy = get_local_id(YY);
// Staging coordinates - only for spline computation
__local float sm_coordinates[DIM * atomsPerBlock];
- const int atomIndexOffset = get_group_id(XX) * atomsPerBlock;
+ const int atomIndexOffset = (int)get_group_id(XX) * atomsPerBlock;
/* Staging coefficients/charges for both spline and spread */
- pme_gpu_stage_atom_data(kernelParams, sm_coefficients, gm_coefficients, 1);
+ pme_gpu_stage_atom_data(sm_coefficients, gm_coefficients, 1);
if (computeSplines)
{
/* Staging coordinates */
- pme_gpu_stage_atom_data(kernelParams, sm_coordinates, gm_coordinates, DIM);
+ pme_gpu_stage_atom_data(sm_coordinates, gm_coordinates, DIM);
barrier(CLK_LOCAL_MEM_FENCE);
calculate_splines(kernelParams, atomIndexOffset, sm_coordinates, sm_coefficients, sm_theta,
* as in after running the spline kernel)
*/
/* Spline data - only thetas (dthetas will only be needed in gather) */
- pme_gpu_stage_atom_data(kernelParams, sm_theta, gm_theta, DIM * order);
+ pme_gpu_stage_atom_data(sm_theta, gm_theta, DIM * order);
/* Gridline indices - they're actually int and not float, but C99 is angry about overloads */
- pme_gpu_stage_atom_data(kernelParams, (__local float*)sm_gridlineIndices,
+ pme_gpu_stage_atom_data((__local float*)sm_gridlineIndices,
(__global const float*)gm_gridlineIndices, DIM);
barrier(CLK_LOCAL_MEM_FENCE);
/* Spreading */
if (spreadCharges)
{
- spread_charges(kernelParams, atomIndexOffset, sm_coefficients, sm_gridlineIndices, sm_theta, gm_grid);
+ spread_charges(kernelParams, sm_coefficients, sm_gridlineIndices, sm_theta, gm_grid);
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "pme_internal.h"
#include "pme_simd.h"
#include "pme_spline_work.h"
+#include "spline_vectors.h"
/* TODO consider split of pme-spline from this file */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013-2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cassert>
#include "gromacs/gpu_utils/cuda_kernel_utils.cuh"
+#include "gromacs/gpu_utils/typecasts.cuh"
#include "pme.cuh"
-#include "pme_calculate_splines.cuh"
-#include "pme_gpu_utils.h"
+#include "pme_gpu_calculate_splines.cuh"
#include "pme_grid.h"
/*! \brief
* Optional second stage of the spline_and_spread_kernel.
*
* \tparam[in] order PME interpolation order.
- * \tparam[in] wrapX A boolean which tells if the grid overlap in dimension X should
- * be wrapped. \tparam[in] wrapY A boolean which tells if the grid overlap in
- * dimension Y should be wrapped. \tparam[in] useOrderThreads A boolean which Tells if we
- * should use order threads per atom (order*order used if false) \param[in] kernelParams Input PME
- * CUDA data in constant memory. \param[in] atomIndexOffset Starting atom index for the
- * execution block w.r.t. global memory. \param[in] atomCharge Atom charge/coefficient of
- * atom processed by thread. \param[in] sm_gridlineIndices Atom gridline indices in the shared
- * memory. \param[in] sm_theta Atom spline values in the shared memory.
+ * \tparam[in] wrapX Whether the grid overlap in dimension X should be wrapped.
+ * \tparam[in] wrapY Whether the grid overlap in dimension Y should be wrapped.
+ * \tparam[in] threadsPerAtom How many threads work on each atom
+ *
+ * \param[in] kernelParams Input PME CUDA data in constant memory.
+ * \param[in] atomCharge Atom charge/coefficient of atom processed by thread.
+ * \param[in] sm_gridlineIndices Atom gridline indices in the shared memory.
+ * \param[in] sm_theta Atom spline values in the shared memory.
*/
-template<const int order, const bool wrapX, const bool wrapY, const bool useOrderThreads>
+template<int order, bool wrapX, bool wrapY, ThreadsPerAtom threadsPerAtom>
__device__ __forceinline__ void spread_charges(const PmeGpuCudaKernelParams kernelParams,
- int atomIndexOffset,
const float* atomCharge,
const int* __restrict__ sm_gridlineIndices,
const float* __restrict__ sm_theta)
/* Global memory pointer to the output grid */
float* __restrict__ gm_grid = kernelParams.grid.d_realGrid;
-
- const int atomsPerWarp = useOrderThreads ? c_pmeSpreadGatherAtomsPerWarp4ThPerAtom
- : c_pmeSpreadGatherAtomsPerWarp;
+ // Number of atoms processed by a single warp in spread and gather
+ const int threadsPerAtomValue = (threadsPerAtom == ThreadsPerAtom::Order) ? order : order * order;
+ const int atomsPerWarp = warp_size / threadsPerAtomValue;
const int nx = kernelParams.grid.realGridSize[XX];
const int ny = kernelParams.grid.realGridSize[YY];
const int offx = 0, offy = 0, offz = 0; // unused for now
- const int atomIndexLocal = threadIdx.z;
- const int atomIndexGlobal = atomIndexOffset + atomIndexLocal;
+ const int atomIndexLocal = threadIdx.z;
- const int globalCheck = pme_gpu_check_atom_data_index(atomIndexGlobal, kernelParams.atoms.nAtoms);
const int chargeCheck = pme_gpu_check_atom_charge(*atomCharge);
- if (chargeCheck & globalCheck)
+ if (chargeCheck)
{
// Spline Z coordinates
const int ithz = threadIdx.x;
const float thetaZ = sm_theta[splineIndexZ];
/* loop not used if order*order threads per atom */
- const int ithyMin = useOrderThreads ? 0 : threadIdx.y;
- const int ithyMax = useOrderThreads ? order : threadIdx.y + 1;
+ const int ithyMin = (threadsPerAtom == ThreadsPerAtom::Order) ? 0 : threadIdx.y;
+ const int ithyMax = (threadsPerAtom == ThreadsPerAtom::Order) ? order : threadIdx.y + 1;
for (int ithy = ithyMin; ithy < ithyMax; ithy++)
{
int iy = iyBase + ithy;
* \tparam[in] wrapX A boolean which tells if the grid overlap in dimension X should be wrapped.
* \tparam[in] wrapY A boolean which tells if the grid overlap in dimension Y should be wrapped.
* \tparam[in] writeGlobal A boolean which tells if the theta values and gridlines should be written to global memory.
- * \tparam[in] useOrderThreads A boolean which tells if we should use order threads per atom (order*order used if false).
+ * \tparam[in] threadsPerAtom How many threads work on each atom
* \param[in] kernelParams Input PME CUDA data in constant memory.
*/
-template<const int order, const bool computeSplines, const bool spreadCharges, const bool wrapX, const bool wrapY, const bool writeGlobal, const bool useOrderThreads>
+template<int order, bool computeSplines, bool spreadCharges, bool wrapX, bool wrapY, bool writeGlobal, ThreadsPerAtom threadsPerAtom>
__launch_bounds__(c_spreadMaxThreadsPerBlock) CLANG_DISABLE_OPTIMIZATION_ATTRIBUTE __global__
void pme_spline_and_spread_kernel(const PmeGpuCudaKernelParams kernelParams)
{
- const int atomsPerBlock =
- useOrderThreads ? c_spreadMaxThreadsPerBlock / c_pmeSpreadGatherThreadsPerAtom4ThPerAtom
- : c_spreadMaxThreadsPerBlock / c_pmeSpreadGatherThreadsPerAtom;
+ const int threadsPerAtomValue = (threadsPerAtom == ThreadsPerAtom::Order) ? order : order * order;
+ const int atomsPerBlock = c_spreadMaxThreadsPerBlock / threadsPerAtomValue;
+ // Number of atoms processed by a single warp in spread and gather
+ const int atomsPerWarp = warp_size / threadsPerAtomValue;
// Gridline indices, ivec
__shared__ int sm_gridlineIndices[atomsPerBlock * DIM];
// Spline values
__shared__ float sm_theta[atomsPerBlock * DIM * order];
float dtheta;
- const int atomsPerWarp = useOrderThreads ? c_pmeSpreadGatherAtomsPerWarp4ThPerAtom
- : c_pmeSpreadGatherAtomsPerWarp;
-
float3 atomX;
float atomCharge;
if (c_useAtomDataPrefetch)
{
__shared__ float sm_coefficients[atomsPerBlock];
- pme_gpu_stage_atom_data<float, atomsPerBlock, 1>(kernelParams, sm_coefficients,
- kernelParams.atoms.d_coefficients);
+ pme_gpu_stage_atom_data<float, atomsPerBlock, 1>(sm_coefficients, kernelParams.atoms.d_coefficients);
__syncthreads();
atomCharge = sm_coefficients[atomIndexLocal];
}
if (computeSplines)
{
+ const float3* __restrict__ gm_coordinates = asFloat3(kernelParams.atoms.d_coordinates);
if (c_useAtomDataPrefetch)
{
// Coordinates
- __shared__ float sm_coordinates[DIM * atomsPerBlock];
+ __shared__ float3 sm_coordinates[atomsPerBlock];
/* Staging coordinates */
- pme_gpu_stage_atom_data<float, atomsPerBlock, DIM>(kernelParams, sm_coordinates,
- kernelParams.atoms.d_coordinates);
+ pme_gpu_stage_atom_data<float3, atomsPerBlock, 1>(sm_coordinates, gm_coordinates);
__syncthreads();
- atomX.x = sm_coordinates[atomIndexLocal * DIM + XX];
- atomX.y = sm_coordinates[atomIndexLocal * DIM + YY];
- atomX.z = sm_coordinates[atomIndexLocal * DIM + ZZ];
+ atomX = sm_coordinates[atomIndexLocal];
}
else
{
- atomX.x = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + XX];
- atomX.y = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + YY];
- atomX.z = kernelParams.atoms.d_coordinates[atomIndexGlobal * DIM + ZZ];
+ atomX = gm_coordinates[atomIndexGlobal];
}
calculate_splines<order, atomsPerBlock, atomsPerWarp, false, writeGlobal>(
kernelParams, atomIndexOffset, atomX, atomCharge, sm_theta, &dtheta, sm_gridlineIndices);
* as in after running the spline kernel)
*/
/* Spline data - only thetas (dthetas will only be needed in gather) */
- pme_gpu_stage_atom_data<float, atomsPerBlock, DIM * order>(kernelParams, sm_theta,
- kernelParams.atoms.d_theta);
+ pme_gpu_stage_atom_data<float, atomsPerBlock, DIM * order>(sm_theta, kernelParams.atoms.d_theta);
/* Gridline indices */
- pme_gpu_stage_atom_data<int, atomsPerBlock, DIM>(kernelParams, sm_gridlineIndices,
+ pme_gpu_stage_atom_data<int, atomsPerBlock, DIM>(sm_gridlineIndices,
kernelParams.atoms.d_gridlineIndices);
__syncthreads();
/* Spreading */
if (spreadCharges)
{
- spread_charges<order, wrapX, wrapY, useOrderThreads>(
- kernelParams, atomIndexOffset, &atomCharge, sm_gridlineIndices, sm_theta);
+ spread_charges<order, wrapX, wrapY, threadsPerAtom>(kernelParams, &atomCharge,
+ sm_gridlineIndices, sm_theta);
}
}
//! Kernel instantiations
-template __global__ void pme_spline_and_spread_kernel<4, true, true, true, true, true, true>(const PmeGpuCudaKernelParams);
-template __global__ void
-pme_spline_and_spread_kernel<4, true, false, true, true, true, true>(const PmeGpuCudaKernelParams);
-template __global__ void
-pme_spline_and_spread_kernel<4, false, true, true, true, true, true>(const PmeGpuCudaKernelParams);
-
-template __global__ void
-pme_spline_and_spread_kernel<4, true, true, true, true, false, true>(const PmeGpuCudaKernelParams);
-
-template __global__ void
-pme_spline_and_spread_kernel<4, true, true, true, true, true, false>(const PmeGpuCudaKernelParams);
-template __global__ void
-pme_spline_and_spread_kernel<4, true, false, true, true, true, false>(const PmeGpuCudaKernelParams);
-template __global__ void
-pme_spline_and_spread_kernel<4, false, true, true, true, true, false>(const PmeGpuCudaKernelParams);
-
-template __global__ void
-pme_spline_and_spread_kernel<4, true, true, true, true, false, false>(const PmeGpuCudaKernelParams);
+// clang-format off
+template __global__ void pme_spline_and_spread_kernel<4, true, true, true, true, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, true, false, true, true, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, false, true, true, true, true, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, true, true, true, true, false, ThreadsPerAtom::Order> (const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, true, true, true, true, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, true, false, true, true, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, false, true, true, true, true, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+template __global__ void pme_spline_and_spread_kernel<4, true, true, true, true, false, ThreadsPerAtom::OrderSquared>(const PmeGpuCudaKernelParams);
+// clang-format on
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#include "gromacs/mdlib/qmmm.h"
+/*! \internal \file
+ *
+ * \brief This file declares a type useful for spline vectors
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_ewald
+ */
-#ifndef GMX_MDLIB_QM_ORCA_H
-# define GMX_MDLIB_QM_ORCA_H
+#ifndef GMX_EWALD_SPLINE_VECTORS_H
+#define GMX_EWALD_SPLINE_VECTORS_H
-void init_orca(t_QMrec* qm);
+#include "gromacs/math/vectypes.h"
+#include "gromacs/utility/real.h"
-real call_orca(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+/*! \brief Helper typedef for spline vectors */
+typedef real* splinevec[DIM];
#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016,2017, by the GROMACS development team, led by
+# Copyright (c) 2016,2017,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-file(GLOB EWALD_TEST_SOURCES *.cpp)
+gmx_add_unit_test(EwaldUnitTests ewald-test HARDWARE_DETECTION
+ CPP_SOURCE_FILES
+ pmebsplinetest.cpp
+ pmegathertest.cpp
+ pmesolvetest.cpp
+ pmesplinespreadtest.cpp
+ testhardwarecontexts.cpp
+ GPU_CPP_SOURCE_FILES
+ pmetestcommon.cpp
+)
+
+gmx_add_libgromacs_sources(
+ testhardwarecontext.cpp
+)
if (GMX_USE_CUDA)
- file(GLOB EWALD_CUDA_SOURCES ../*.cu)
+gmx_compile_cpp_as_cuda(
+ testhardwarecontext.cpp
+)
endif()
-
-gmx_add_unit_test(EwaldUnitTests ewald-test HARDWARE_DETECTION
- ${EWALD_TEST_SOURCES} ${EWALD_CUDA_SOURCES})
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/testasserts.h"
#include "pmetestcommon.h"
+#include "testhardwarecontexts.h"
namespace gmx
{
using PmeBSplineModuliFailureTest = PmeBSplineModuliTest;
TEST_P(PmeBSplineModuliFailureTest, Throws)
{
- EXPECT_THROW(runTest(), InconsistentInputError);
+ EXPECT_THROW_GMX(runTest(), InconsistentInputError);
}
//! Correctness test alias
using PmeBSplineModuliCorrectnessTest = PmeBSplineModuliTest;
TEST_P(PmeBSplineModuliCorrectnessTest, ReproducesValues)
{
- EXPECT_NO_THROW(runTest());
+ EXPECT_NO_THROW_GMX(runTest());
}
/* Invalid input instances */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/testasserts.h"
#include "pmetestcommon.h"
+#include "testhardwarecontexts.h"
namespace gmx
{
* The rest of the atom-related input data - gridline indices, spline theta values, spline dtheta
* values, atom charges - is looked up in the inputAtomDataSets_ test fixture variable.
*/
-typedef std::tuple<Matrix3x3, int, IVec, SparseRealGridValuesInput, PmeForceOutputHandling, size_t> GatherInputParameters;
+typedef std::tuple<Matrix3x3, int, IVec, SparseRealGridValuesInput, size_t> GatherInputParameters;
//! Test fixture
class PmeGatherTest : public ::testing::TestWithParam<GatherInputParameters>
IVec gridSize;
size_t atomCount;
SparseRealGridValuesInput nonZeroGridValues;
- PmeForceOutputHandling inputForceTreatment;
- std::tie(box, pmeOrder, gridSize, nonZeroGridValues, inputForceTreatment, atomCount) = GetParam();
+ std::tie(box, pmeOrder, gridSize, nonZeroGridValues, atomCount) = GetParam();
auto inputAtomData = s_inputAtomDataSets_[atomCount];
auto inputAtomSplineData = inputAtomData.splineDataByPmeOrder[pmeOrder];
TestReferenceData refData;
for (const auto& context : getPmeTestEnv()->getHardwareContexts())
{
- CodePath codePath = context->getCodePath();
+ CodePath codePath = context->codePath();
const bool supportedInput =
pmeSupportsInputForMode(*getPmeTestEnv()->hwinfo(), &inputRec, codePath);
if (!supportedInput)
{
/* Testing the failure for the unsupported input */
- EXPECT_THROW(pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, box), NotImplementedError);
+ EXPECT_THROW_GMX(pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, nullptr, box),
+ NotImplementedError);
continue;
}
/* Describing the test uniquely */
SCOPED_TRACE(
formatString("Testing force gathering with %s %sfor PME grid size %d %d %d"
- ", order %d, %zu atoms, %s",
- codePathToString(codePath), context->getDescription().c_str(),
- gridSize[XX], gridSize[YY], gridSize[ZZ], pmeOrder, atomCount,
- (inputForceTreatment == PmeForceOutputHandling::ReduceWithInput)
- ? "with reduction"
- : "without reduction"));
-
- PmeSafePointer pmeSafe = pmeInitWrapper(&inputRec, codePath, context->getDeviceInfo(),
- context->getPmeGpuProgram(), box);
+ ", order %d, %zu atoms",
+ codePathToString(codePath), context->description().c_str(),
+ gridSize[XX], gridSize[YY], gridSize[ZZ], pmeOrder, atomCount));
+
+ PmeSafePointer pmeSafe =
+ pmeInitWrapper(&inputRec, codePath, context->deviceContext(),
+ context->deviceStream(), context->pmeGpuProgram(), box);
std::unique_ptr<StatePropagatorDataGpu> stateGpu =
- (codePath == CodePath::GPU) ? makeStatePropagatorDataGpu(*pmeSafe.get()) : nullptr;
+ (codePath == CodePath::GPU)
+ ? makeStatePropagatorDataGpu(*pmeSafe.get(), context->deviceContext(),
+ context->deviceStream())
+ : nullptr;
pmeInitAtoms(pmeSafe.get(), stateGpu.get(), codePath, inputAtomData.coordinates,
inputAtomData.charges);
auto forces = ForcesVector(inputForcesFull).subArray(0, atomCount);
/* Running the force gathering itself */
- pmePerformGather(pmeSafe.get(), codePath, inputForceTreatment, forces);
+ pmePerformGather(pmeSafe.get(), codePath, forces);
pmeFinalizeTest(pmeSafe.get(), codePath);
/* Check the output forces correctness */
//! Test for PME force gathering
TEST_P(PmeGatherTest, ReproducesOutputs)
{
- EXPECT_NO_THROW(runTest());
+ EXPECT_NO_THROW_GMX(runTest());
}
//! Instantiation of the PME gathering test
::testing::ValuesIn(pmeOrders),
::testing::ValuesIn(c_sampleGridSizes),
::testing::ValuesIn(c_sampleGrids),
- ::testing::Values(PmeForceOutputHandling::Set,
- PmeForceOutputHandling::ReduceWithInput),
::testing::ValuesIn(atomCounts)));
} // namespace
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/testasserts.h"
#include "pmetestcommon.h"
+#include "testhardwarecontexts.h"
namespace gmx
{
TestReferenceData refData;
for (const auto& context : getPmeTestEnv()->getHardwareContexts())
{
- CodePath codePath = context->getCodePath();
+ CodePath codePath = context->codePath();
const bool supportedInput =
pmeSupportsInputForMode(*getPmeTestEnv()->hwinfo(), &inputRec, codePath);
if (!supportedInput)
{
/* Testing the failure for the unsupported input */
- EXPECT_THROW(pmeInitEmpty(&inputRec, codePath, nullptr, nullptr, box, ewaldCoeff_q,
- ewaldCoeff_lj),
- NotImplementedError);
+ EXPECT_THROW_GMX(pmeInitEmpty(&inputRec, codePath, nullptr, nullptr, nullptr, box,
+ ewaldCoeff_q, ewaldCoeff_lj),
+ NotImplementedError);
continue;
}
"size %d %d %d, Ewald coefficients %g %g",
(method == PmeSolveAlgorithm::LennardJones) ? "Lennard-Jones" : "Coulomb",
gridOrdering.second.c_str(), computeEnergyAndVirial ? "with" : "without",
- codePathToString(codePath), context->getDescription().c_str(),
+ codePathToString(codePath), context->description().c_str(),
gridSize[XX], gridSize[YY], gridSize[ZZ], ewaldCoeff_q, ewaldCoeff_lj));
/* Running the test */
- PmeSafePointer pmeSafe =
- pmeInitEmpty(&inputRec, codePath, context->getDeviceInfo(),
- context->getPmeGpuProgram(), box, ewaldCoeff_q, ewaldCoeff_lj);
+ PmeSafePointer pmeSafe = pmeInitEmpty(
+ &inputRec, codePath, context->deviceContext(), context->deviceStream(),
+ context->pmeGpuProgram(), box, ewaldCoeff_q, ewaldCoeff_lj);
pmeSetComplexGrid(pmeSafe.get(), codePath, gridOrdering.first, nonZeroGridValues);
const real cellVolume = box[0] * box[4] * box[8];
// FIXME - this is box[XX][XX] * box[YY][YY] * box[ZZ][ZZ], should be stored in the PME structure
/*! \brief Test for PME solving */
TEST_P(PmeSolveTest, ReproducesOutputs)
{
- EXPECT_NO_THROW(runTest());
+ EXPECT_NO_THROW_GMX(runTest());
}
/* Valid input instances */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/testasserts.h"
#include "pmetestcommon.h"
+#include "testhardwarecontexts.h"
namespace gmx
{
for (const auto& context : getPmeTestEnv()->getHardwareContexts())
{
- CodePath codePath = context->getCodePath();
+ CodePath codePath = context->codePath();
const bool supportedInput =
pmeSupportsInputForMode(*getPmeTestEnv()->hwinfo(), &inputRec, codePath);
if (!supportedInput)
{
/* Testing the failure for the unsupported input */
- EXPECT_THROW(pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, box), NotImplementedError);
+ EXPECT_THROW_GMX(pmeInitWrapper(&inputRec, codePath, nullptr, nullptr, nullptr, box),
+ NotImplementedError);
continue;
}
{
/* Describing the test uniquely in case it fails */
- SCOPED_TRACE(
- formatString("Testing %s with %s %sfor PME grid size %d %d %d"
- ", order %d, %zu atoms",
- option.second.c_str(), codePathToString(codePath),
- context->getDescription().c_str(), gridSize[XX], gridSize[YY],
- gridSize[ZZ], pmeOrder, atomCount));
+ SCOPED_TRACE(formatString(
+ "Testing %s with %s %sfor PME grid size %d %d %d"
+ ", order %d, %zu atoms",
+ option.second.c_str(), codePathToString(codePath), context->description().c_str(),
+ gridSize[XX], gridSize[YY], gridSize[ZZ], pmeOrder, atomCount));
/* Running the test */
- PmeSafePointer pmeSafe = pmeInitWrapper(&inputRec, codePath, context->getDeviceInfo(),
- context->getPmeGpuProgram(), box);
+ PmeSafePointer pmeSafe =
+ pmeInitWrapper(&inputRec, codePath, context->deviceContext(),
+ context->deviceStream(), context->pmeGpuProgram(), box);
std::unique_ptr<StatePropagatorDataGpu> stateGpu =
- (codePath == CodePath::GPU) ? makeStatePropagatorDataGpu(*pmeSafe.get()) : nullptr;
+ (codePath == CodePath::GPU)
+ ? makeStatePropagatorDataGpu(*pmeSafe.get(), context->deviceContext(),
+ context->deviceStream())
+ : nullptr;
pmeInitAtoms(pmeSafe.get(), stateGpu.get(), codePath, coordinates, charges);
/*! \brief Test for spline parameter computation and charge spreading. */
TEST_P(PmeSplineAndSpreadTest, ReproducesOutputs)
{
- EXPECT_NO_THROW(runTest());
+ EXPECT_NO_THROW_GMX(runTest());
}
/* Valid input instances */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/domdec.h"
#include "gromacs/ewald/pme_gather.h"
+#include "gromacs/ewald/pme_gpu_calculate_splines.h"
+#include "gromacs/ewald/pme_gpu_constants.h"
#include "gromacs/ewald/pme_gpu_internal.h"
+#include "gromacs/ewald/pme_gpu_staging.h"
#include "gromacs/ewald/pme_grid.h"
#include "gromacs/ewald/pme_internal.h"
#include "gromacs/ewald/pme_redistribute.h"
#include "gromacs/ewald/pme_solve.h"
#include "gromacs/ewald/pme_spread.h"
#include "gromacs/fft/parallel_3dfft.h"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/math/invertmatrix.h"
#include "gromacs/mdtypes/commrec.h"
#include "testutils/testasserts.h"
+#include "testhardwarecontexts.h"
+
namespace gmx
{
namespace test
}
//! PME initialization
-PmeSafePointer pmeInitWrapper(const t_inputrec* inputRec,
- const CodePath mode,
- const gmx_device_info_t* gpuInfo,
- PmeGpuProgramHandle pmeGpuProgram,
- const Matrix3x3& box,
- const real ewaldCoeff_q,
- const real ewaldCoeff_lj)
+PmeSafePointer pmeInitWrapper(const t_inputrec* inputRec,
+ const CodePath mode,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
+ const Matrix3x3& box,
+ const real ewaldCoeff_q,
+ const real ewaldCoeff_lj)
{
const MDLogger dummyLogger;
const auto runMode = (mode == CodePath::CPU) ? PmeRunMode::CPU : PmeRunMode::Mixed;
t_commrec dummyCommrec = { 0 };
NumPmeDomains numPmeDomains = { 1, 1 };
- gmx_pme_t* pmeDataRaw =
- gmx_pme_init(&dummyCommrec, numPmeDomains, inputRec, false, false, true, ewaldCoeff_q,
- ewaldCoeff_lj, 1, runMode, nullptr, gpuInfo, pmeGpuProgram, dummyLogger);
+ gmx_pme_t* pmeDataRaw = gmx_pme_init(&dummyCommrec, numPmeDomains, inputRec, false, false, true,
+ ewaldCoeff_q, ewaldCoeff_lj, 1, runMode, nullptr,
+ deviceContext, deviceStream, pmeGpuProgram, dummyLogger);
PmeSafePointer pme(pmeDataRaw); // taking ownership
// TODO get rid of this with proper matrix type
boxTemp[i][j] = box[i * DIM + j];
}
}
- const char* boxError = check_box(-1, boxTemp);
+ const char* boxError = check_box(PbcType::Unset, boxTemp);
GMX_RELEASE_ASSERT(boxError == nullptr, boxError);
switch (mode)
}
//! Simple PME initialization based on input, no atom data
-PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec,
- const CodePath mode,
- const gmx_device_info_t* gpuInfo,
- PmeGpuProgramHandle pmeGpuProgram,
- const Matrix3x3& box,
- real ewaldCoeff_q,
- real ewaldCoeff_lj)
-{
- return pmeInitWrapper(inputRec, mode, gpuInfo, pmeGpuProgram, box, ewaldCoeff_q, ewaldCoeff_lj);
+PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec,
+ const CodePath mode,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
+ const Matrix3x3& box,
+ const real ewaldCoeff_q,
+ const real ewaldCoeff_lj)
+{
+ return pmeInitWrapper(inputRec, mode, deviceContext, deviceStream, pmeGpuProgram, box,
+ ewaldCoeff_q, ewaldCoeff_lj);
// hiding the fact that PME actually needs to know the number of atoms in advance
}
+PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec)
+{
+ const Matrix3x3 defaultBox = { { 1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F } };
+ return pmeInitWrapper(inputRec, CodePath::CPU, nullptr, nullptr, nullptr, defaultBox, 0.0F, 0.0F);
+}
+
//! Make a GPU state-propagator manager
-std::unique_ptr<StatePropagatorDataGpu> makeStatePropagatorDataGpu(const gmx_pme_t& pme)
+std::unique_ptr<StatePropagatorDataGpu> makeStatePropagatorDataGpu(const gmx_pme_t& pme,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream)
{
// TODO: Pin the host buffer and use async memory copies
// TODO: Special constructor for PME-only rank / PME-tests is used here. There should be a mechanism to
// restrict one from using other constructor here.
- return std::make_unique<StatePropagatorDataGpu>(
- pme_gpu_get_device_stream(&pme), pme_gpu_get_device_context(&pme),
- GpuApiCallBehavior::Sync, pme_gpu_get_padding_size(&pme), nullptr);
+ return std::make_unique<StatePropagatorDataGpu>(deviceStream, *deviceContext, GpuApiCallBehavior::Sync,
+ pme_gpu_get_block_size(&pme), nullptr);
}
//! PME initialization with atom data
}
//! PME force gathering
-void pmePerformGather(gmx_pme_t* pme, CodePath mode, PmeForceOutputHandling inputTreatment, ForcesVector& forces)
+void pmePerformGather(gmx_pme_t* pme, CodePath mode, ForcesVector& forces)
{
PmeAtomComm* atc = &(pme->atc[0]);
const index atomCount = atc->numAtoms();
GMX_RELEASE_ASSERT(forces.ssize() == atomCount, "Invalid force buffer size");
- const bool forceReductionWithInput = (inputTreatment == PmeForceOutputHandling::ReduceWithInput);
- const real scale = 1.0;
- const size_t threadIndex = 0;
- const size_t gridIndex = 0;
- real* pmegrid = pme->pmegrid[gridIndex].grid.grid;
- real* fftgrid = pme->fftgrid[gridIndex];
+ const real scale = 1.0;
+ const size_t threadIndex = 0;
+ const size_t gridIndex = 0;
+ real* pmegrid = pme->pmegrid[gridIndex].grid.grid;
+ real* fftgrid = pme->fftgrid[gridIndex];
switch (mode)
{
}
copy_fftgrid_to_pmegrid(pme, fftgrid, pmegrid, gridIndex, pme->nthread, threadIndex);
unwrap_periodic_pmegrid(pme, pmegrid);
- gather_f_bsplines(pme, pmegrid, !forceReductionWithInput, atc, &atc->spline[threadIndex], scale);
+ gather_f_bsplines(pme, pmegrid, true, atc, &atc->spline[threadIndex], scale);
break;
case CodePath::GPU:
{
// Variable initialization needs a non-switch scope
- PmeOutput output = pme_gpu_getOutput(*pme, GMX_PME_CALC_F);
+ const bool computeEnergyAndVirial = false;
+ PmeOutput output = pme_gpu_getOutput(*pme, computeEnergyAndVirial);
GMX_ASSERT(forces.size() == output.forces_.size(),
"Size of force buffers did not match");
- if (forceReductionWithInput)
- {
- std::copy(std::begin(forces), std::end(forces), std::begin(output.forces_));
- }
- pme_gpu_gather(pme->gpu, inputTreatment, reinterpret_cast<float*>(fftgrid));
+ pme_gpu_gather(pme->gpu, reinterpret_cast<float*>(fftgrid));
std::copy(std::begin(output.forces_), std::end(output.forces_), std::begin(forces));
}
break;
}
}
+//! A binary enum for spline data layout transformation
+enum class PmeLayoutTransform
+{
+ GpuToHost,
+ HostToGpu
+};
+
+/*! \brief Gets a unique index to an element in a spline parameter buffer.
+ *
+ * These theta/dtheta buffers are laid out for GPU spread/gather
+ * kernels. The index is wrt the execution block, in range(0,
+ * atomsPerBlock * order * DIM).
+ *
+ * This is a wrapper, only used in unit tests.
+ * \param[in] order PME order
+ * \param[in] splineIndex Spline contribution index (from 0 to \p order - 1)
+ * \param[in] dimIndex Dimension index (from 0 to 2)
+ * \param[in] atomIndex Atom index wrt the block.
+ * \param[in] atomsPerWarp Number of atoms processed by a warp.
+ *
+ * \returns Index into theta or dtheta array using GPU layout.
+ */
+static int getSplineParamFullIndex(int order, int splineIndex, int dimIndex, int atomIndex, int atomsPerWarp)
+{
+ if (order != c_pmeGpuOrder)
+ {
+ throw order;
+ }
+ constexpr int fixedOrder = c_pmeGpuOrder;
+ GMX_UNUSED_VALUE(fixedOrder);
+
+ const int atomWarpIndex = atomIndex % atomsPerWarp;
+ const int warpIndex = atomIndex / atomsPerWarp;
+ int indexBase, result;
+ switch (atomsPerWarp)
+ {
+ case 1:
+ indexBase = getSplineParamIndexBase<fixedOrder, 1>(warpIndex, atomWarpIndex);
+ result = getSplineParamIndex<fixedOrder, 1>(indexBase, dimIndex, splineIndex);
+ break;
+
+ case 2:
+ indexBase = getSplineParamIndexBase<fixedOrder, 2>(warpIndex, atomWarpIndex);
+ result = getSplineParamIndex<fixedOrder, 2>(indexBase, dimIndex, splineIndex);
+ break;
+
+ case 4:
+ indexBase = getSplineParamIndexBase<fixedOrder, 4>(warpIndex, atomWarpIndex);
+ result = getSplineParamIndex<fixedOrder, 4>(indexBase, dimIndex, splineIndex);
+ break;
+
+ case 8:
+ indexBase = getSplineParamIndexBase<fixedOrder, 8>(warpIndex, atomWarpIndex);
+ result = getSplineParamIndex<fixedOrder, 8>(indexBase, dimIndex, splineIndex);
+ break;
+
+ default:
+ GMX_THROW(NotImplementedError(
+ formatString("Test function call not unrolled for atomsPerWarp = %d in "
+ "getSplineParamFullIndex",
+ atomsPerWarp)));
+ }
+ return result;
+}
+
+/*!\brief Return the number of atoms per warp */
+static int pme_gpu_get_atoms_per_warp(const PmeGpu* pmeGpu)
+{
+ const int order = pmeGpu->common->pme_order;
+ const int threadsPerAtom =
+ (pmeGpu->settings.threadsPerAtom == ThreadsPerAtom::Order ? order : order * order);
+ return pmeGpu->programHandle_->warpSize() / threadsPerAtom;
+}
+
+/*! \brief Rearranges the atom spline data between the GPU and host layouts.
+ * Only used for test purposes so far, likely to be horribly slow.
+ *
+ * \param[in] pmeGpu The PME GPU structure.
+ * \param[out] atc The PME CPU atom data structure (with a single-threaded layout).
+ * \param[in] type The spline data type (values or derivatives).
+ * \param[in] dimIndex Dimension index.
+ * \param[in] transform Layout transform type
+ */
+static void pme_gpu_transform_spline_atom_data(const PmeGpu* pmeGpu,
+ const PmeAtomComm* atc,
+ PmeSplineDataType type,
+ int dimIndex,
+ PmeLayoutTransform transform)
+{
+ // The GPU atom spline data is laid out in a different way currently than the CPU one.
+ // This function converts the data from GPU to CPU layout (in the host memory).
+ // It is only intended for testing purposes so far.
+ // Ideally we should use similar layouts on CPU and GPU if we care about mixed modes and their
+ // performance (e.g. spreading on GPU, gathering on CPU).
+ GMX_RELEASE_ASSERT(atc->nthread == 1, "Only the serial PME data layout is supported");
+ const uintmax_t threadIndex = 0;
+ const auto atomCount = atc->numAtoms();
+ const auto atomsPerWarp = pme_gpu_get_atoms_per_warp(pmeGpu);
+ const auto pmeOrder = pmeGpu->common->pme_order;
+ GMX_ASSERT(pmeOrder == c_pmeGpuOrder, "Only PME order 4 is implemented");
+
+ real* cpuSplineBuffer;
+ float* h_splineBuffer;
+ switch (type)
+ {
+ case PmeSplineDataType::Values:
+ cpuSplineBuffer = atc->spline[threadIndex].theta.coefficients[dimIndex];
+ h_splineBuffer = pmeGpu->staging.h_theta;
+ break;
+
+ case PmeSplineDataType::Derivatives:
+ cpuSplineBuffer = atc->spline[threadIndex].dtheta.coefficients[dimIndex];
+ h_splineBuffer = pmeGpu->staging.h_dtheta;
+ break;
+
+ default: GMX_THROW(InternalError("Unknown spline data type"));
+ }
+
+ for (auto atomIndex = 0; atomIndex < atomCount; atomIndex++)
+ {
+ for (auto orderIndex = 0; orderIndex < pmeOrder; orderIndex++)
+ {
+ const auto gpuValueIndex =
+ getSplineParamFullIndex(pmeOrder, orderIndex, dimIndex, atomIndex, atomsPerWarp);
+ const auto cpuValueIndex = atomIndex * pmeOrder + orderIndex;
+ GMX_ASSERT(cpuValueIndex < atomCount * pmeOrder,
+ "Atom spline data index out of bounds (while transforming GPU data layout "
+ "for host)");
+ switch (transform)
+ {
+ case PmeLayoutTransform::GpuToHost:
+ cpuSplineBuffer[cpuValueIndex] = h_splineBuffer[gpuValueIndex];
+ break;
+
+ case PmeLayoutTransform::HostToGpu:
+ h_splineBuffer[gpuValueIndex] = cpuSplineBuffer[cpuValueIndex];
+ break;
+
+ default: GMX_THROW(InternalError("Unknown layout transform"));
+ }
+ }
+ }
+}
+
//! Setting atom spline values/derivatives to be used in spread/gather
void pmeSetSplineData(const gmx_pme_t* pme,
CodePath mode,
switch (mode)
{
case CodePath::GPU:
- memcpy(pme->gpu->staging.h_gridlineIndices, gridLineIndices.data(),
+ memcpy(pme_gpu_staging(pme->gpu).h_gridlineIndices, gridLineIndices.data(),
atomCount * sizeof(gridLineIndices[0]));
break;
{
case CodePath::GPU:
gridLineIndices = arrayRefFromArray(
- reinterpret_cast<IVec*>(pme->gpu->staging.h_gridlineIndices), atomCount);
+ reinterpret_cast<IVec*>(pme_gpu_staging(pme->gpu).h_gridlineIndices), atomCount);
break;
case CodePath::CPU: gridLineIndices = atc->idx; break;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <map>
#include <vector>
-#include <gtest/gtest.h>
-
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_gpu_internal.h"
#include "gromacs/math/gmxcomplex.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/unique_cptr.h"
-#include "testhardwarecontexts.h"
-
namespace gmx
{
+
+class DeviceStreamManager;
namespace test
{
+// Forward declaration
+enum class CodePath;
+
// Convenience typedefs
//! A safe pointer type for PME.
typedef gmx::unique_cptr<gmx_pme_t, gmx_pme_destroy> PmeSafePointer;
// PME stages
//! PME initialization
-PmeSafePointer pmeInitWrapper(const t_inputrec* inputRec,
- CodePath mode,
- const gmx_device_info_t* gpuInfo,
- PmeGpuProgramHandle pmeGpuProgram,
- const Matrix3x3& box,
- real ewaldCoeff_q = 1.0F,
- real ewaldCoeff_lj = 1.0F);
+PmeSafePointer pmeInitWrapper(const t_inputrec* inputRec,
+ CodePath mode,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
+ const Matrix3x3& box,
+ real ewaldCoeff_q = 1.0F,
+ real ewaldCoeff_lj = 1.0F);
//! Simple PME initialization (no atom data)
-PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec,
- CodePath mode = CodePath::CPU,
- const gmx_device_info_t* gpuInfo = nullptr,
- PmeGpuProgramHandle pmeGpuProgram = nullptr,
- const Matrix3x3& box = { { 1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F } },
- real ewaldCoeff_q = 0.0F,
- real ewaldCoeff_lj = 0.0F);
+PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec,
+ CodePath mode,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream,
+ const PmeGpuProgram* pmeGpuProgram,
+ const Matrix3x3& box,
+ real ewaldCoeff_q,
+ real ewaldCoeff_lj);
+
+//! Simple PME initialization based on inputrec only
+PmeSafePointer pmeInitEmpty(const t_inputrec* inputRec);
+
//! Make a GPU state-propagator manager
-std::unique_ptr<StatePropagatorDataGpu> makeStatePropagatorDataGpu(const gmx_pme_t& pme);
+std::unique_ptr<StatePropagatorDataGpu> makeStatePropagatorDataGpu(const gmx_pme_t& pme,
+ const DeviceContext* deviceContext,
+ const DeviceStream* deviceStream);
//! PME initialization with atom data and system box
void pmeInitAtoms(gmx_pme_t* pme,
StatePropagatorDataGpu* stateGpu,
GridOrdering gridOrdering,
bool computeEnergyAndVirial);
//! PME force gathering
-void pmePerformGather(gmx_pme_t* pme,
- CodePath mode,
- PmeForceOutputHandling inputTreatment,
- ForcesVector& forces); //NOLINT(google-runtime-references)
+void pmePerformGather(gmx_pme_t* pme,
+ CodePath mode,
+ ForcesVector& forces); //NOLINT(google-runtime-references)
//! PME test finalization before fetching the outputs
void pmeFinalizeTest(const gmx_pme_t* pme, CodePath mode);
const SplineParamsDimVector& splineValues,
PmeSplineDataType type,
int dimIndex);
+
//! Setting gridline indices be used in spread/gather
void pmeSetGridLineIndices(gmx_pme_t* pme, CodePath mode, const GridLineIndicesVector& gridLineIndices);
//! Setting real grid to be used in gather
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-4.2362713136143704</Real>
- <Real Name="Y">-2.3275379753649541</Real>
- <Real Name="Z">-11.746263473883745</Real>
+ <Real Name="X">-3.4582204419484599</Real>
+ <Real Name="Y">-3.9969224751666577</Real>
+ <Real Name="Z">-9.9756355772564991</Real>
</Vector>
<Vector>
- <Real Name="X">0.57636324498554081</Real>
- <Real Name="Y">-0.013594713514657464</Real>
- <Real Name="Z">-6.1436686744664879</Real>
+ <Real Name="X">-0.067954884757908562</Real>
+ <Real Name="Y">-0.85449341275494772</Real>
+ <Real Name="Z">-5.12573966904852</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.6940571045158022</Real>
- <Real Name="Y">2.1019189996213141</Real>
- <Real Name="Z">-0.21251856629141863</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.19104463336113997</Real>
- <Real Name="Y">-16.083563532509753</Real>
- <Real Name="Z">2.8065205292802267</Real>
- </Vector>
- <Vector>
- <Real Name="X">-2.6398356036393578</Real>
- <Real Name="Y">-0.91018032292522766</Real>
- <Real Name="Z">0.93368498675769429</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-8.0544456082501288</Real>
- <Real Name="Y">-11.923968234039531</Real>
- <Real Name="Z">1.9257328983388657</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.59903073971265186</Real>
- <Real Name="Y">-1.6350310136998707</Real>
- <Real Name="Z">-2.6446765062295143</Real>
- </Vector>
- <Vector>
- <Real Name="X">-7.7106240328717144</Real>
- <Real Name="Y">-1.2779139061856373</Real>
- <Real Name="Z">2.2200763403785335</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.060088412760632121</Real>
- <Real Name="Y">-1.4519790167692483</Real>
- <Real Name="Z">0.24378158880830342</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.3603736897226484</Real>
- <Real Name="Y">-1.4452674741283262</Real>
- <Real Name="Z">-0.088156767496452001</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-8.0344456086971636</Real>
- <Real Name="Y">-11.05396822927116</Real>
- <Real Name="Z">2.8757328864179366</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.5790307401596867</Real>
- <Real Name="Y">-0.76503100893149911</Real>
- <Real Name="Z">-1.6946765181504433</Real>
- </Vector>
- <Vector>
- <Real Name="X">-7.0506240066456707</Real>
- <Real Name="Y">-0.60791388949633673</Real>
- <Real Name="Z">2.6000763356101619</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.76991157055006731</Real>
- <Real Name="Y">-1.1419790143850626</Real>
- <Real Name="Z">0.9737816078817898</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.0903736789938123</Real>
- <Real Name="Y">-0.46526745505483991</Real>
- <Real Name="Z">0.7418432158142475</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-9.4063956103865909</Real>
- <Real Name="Y">1.0613765111849376</Real>
- <Real Name="Z">1.4765278904032615</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">1.6526713761104288</Real>
- <Real Name="Y">1.789898728665017</Real>
- <Real Name="Z">-0.59016766968693601</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.82999998331069946</Real>
- <Real Name="Y">0.31000000238418579</Real>
- <Real Name="Z">0.73000001907348633</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-3.3126533138132714</Real>
- <Real Name="Y">-8.6003366303629782</Real>
- <Real Name="Z">-22.745529254386152</Real>
+ <Real Name="X">-2.9109058261904628</Real>
+ <Real Name="Y">-11.975420811795583</Real>
+ <Real Name="Z">-18.523630115333241</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.82959875104586944</Real>
- <Real Name="Y">-20.491954418617421</Real>
- <Real Name="Z">2.8871516559459058</Real>
- </Vector>
- <Vector>
- <Real Name="X">-2.7217414105226196</Real>
- <Real Name="Y">-1.2127254019801541</Real>
- <Real Name="Z">0.55819396762823659</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-9.3863956108336257</Real>
- <Real Name="Y">1.9313765159533092</Real>
- <Real Name="Z">2.4265278784823323</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.3126714023364725</Real>
- <Real Name="Y">2.4598987453543177</Real>
- <Real Name="Z">-0.2101676744553076</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.00040123226483002039</Real>
- <Real Name="Y">-20.181954416233236</Real>
- <Real Name="Z">3.6171516750193922</Real>
- </Vector>
- <Vector>
- <Real Name="X">-2.0117414319802918</Real>
- <Real Name="Y">-1.1527254033212586</Real>
- <Real Name="Z">0.90819396166777211</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-6.5442370567032295</Real>
- <Real Name="Y">-14.904960292549413</Real>
- <Real Name="Z">2.4825316419739121</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.48671247601652962</Real>
- <Real Name="Y">-2.0437887671248385</Real>
- <Real Name="Z">-1.9489107480528729</Real>
- </Vector>
- <Vector>
- <Real Name="X">-6.2648820267082685</Real>
- <Real Name="Y">-1.5973923827320464</Real>
- <Real Name="Z">1.9008625299783468</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.0488218353680136</Real>
- <Real Name="Y">-1.8149737709615605</Real>
- <Real Name="Z">0.30251804902903451</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.1053036228996518</Real>
- <Real Name="Y">-1.8065843426604078</Real>
- <Real Name="Z">0.051190455240391619</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-6.5242370571502644</Real>
- <Real Name="Y">-14.034960287781042</Real>
- <Real Name="Z">3.4325316300529831</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.46671247646356445</Real>
- <Real Name="Y">-1.1737887623564669</Real>
- <Real Name="Z">-0.99891075997380185</Real>
- </Vector>
- <Vector>
- <Real Name="X">-5.6048820004822248</Real>
- <Real Name="Y">-0.92739236604274589</Real>
- <Real Name="Z">2.280862525209975</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.78117814794268581</Real>
- <Real Name="Y">-1.5049737685773747</Real>
- <Real Name="Z">1.0325180681025208</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.83530361217081572</Real>
- <Real Name="Y">-0.82658432358692147</Real>
- <Real Name="Z">0.88119043855109114</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">0.55642797645760989</Real>
- <Real Name="Y">0.3723331315116295</Real>
- <Real Name="Z">1.6306575619901507</Real>
+ <Real Name="X">-10.129964503493252</Real>
+ <Real Name="Y">1.0239161111946309</Real>
+ <Real Name="Z">-8.1365401298928379</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">3.4320122274828666</Real>
- <Real Name="Y">-0.81224418229071649</Real>
- <Real Name="Z">-0.764761636476889</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">12.870589400646217</Real>
- <Real Name="Y">2.4002360860135794</Real>
- <Real Name="Z">-2.7526346195710181</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-3.9130491664545959</Real>
- <Real Name="Y">-0.62204635074971815</Real>
- <Real Name="Z">1.1633583220151211</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">4.1305407769409488</Real>
- <Real Name="Y">-0.46469970389626269</Real>
- <Real Name="Z">-3.6193285397896875</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.1597567999404905</Real>
- <Real Name="Y">-0.73800016335319685</Real>
- <Real Name="Z">-0.54897393926970917</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.2124223213639174</Real>
- <Real Name="Y">-16.220145737822616</Real>
- <Real Name="Z">2.8258755564357965</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">3.4520122270358318</Real>
- <Real Name="Y">0.057755822477655094</Real>
- <Real Name="Z">0.18523835160218205</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">13.530589426872261</Real>
- <Real Name="Y">3.0702361027028799</Real>
- <Real Name="Z">-2.3726346243393897</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-3.8930491669016307</Real>
- <Real Name="Y">0.24795365401865344</Real>
- <Real Name="Z">2.1133583100941919</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">4.9605407602516483</Real>
- <Real Name="Y">-0.1546997015120769</Real>
- <Real Name="Z">-2.8893285207162012</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.55024317860183736</Real>
- <Real Name="Y">-0.67800016469430135</Real>
- <Real Name="Z">-0.19897394523017364</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.4824223320927534</Real>
- <Real Name="Y">-15.24014571874913</Real>
- <Real Name="Z">3.6558755397464959</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-16.500695458472016</Real>
- <Real Name="Y">-15.572010667113076</Real>
- <Real Name="Z">6.0618364657657224</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.56750283571532234</Real>
- <Real Name="Y">-0.70603611451836135</Real>
- <Real Name="Z">-0.73298662849655538</Real>
- </Vector>
- <Vector>
- <Real Name="X">-7.5662986143550031</Real>
- <Real Name="Y">-4.9570092424793035</Real>
- <Real Name="Z">0.22987632186540616</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-8.3516260207559565</Real>
- <Real Name="Y">-0.89155680381272195</Real>
- <Real Name="Z">1.9626024243687374</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-10.991689448063681</Real>
- <Real Name="Y">-17.399473852314976</Real>
- <Real Name="Z">1.9943402280115583</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.5304702532285459</Real>
- <Real Name="Y">-2.0431421404374799</Real>
- <Real Name="Z">-2.0385186389652117</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-7.0292328592073234</Real>
- <Real Name="Y">-14.608255429729208</Real>
- <Real Name="Z">3.679921612389506</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.67546778632879001</Real>
- <Real Name="Y">-0.07424836221296291</Real>
- <Real Name="Z">0.089381774901316297</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-16.480695458919051</Real>
- <Real Name="Y">-14.702010662344705</Real>
- <Real Name="Z">7.0118364538447935</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44047122348806367</Real>
- <Real Name="Y">0.3871114065335613</Real>
- <Real Name="Z">2.3221153764227829</Real>
+ <Real Name="X">1.7797999435035388</Real>
+ <Real Name="Y">1.7267257437615944</Real>
+ <Real Name="Z">1.3771557011554771</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-0.54750283616235718</Real>
- <Real Name="Y">0.16396389025001024</Real>
- <Real Name="Z">0.21701335958251566</Real>
- </Vector>
- <Vector>
- <Real Name="X">-6.9062985881289594</Real>
- <Real Name="Y">-4.287009225790003</Real>
- <Real Name="Z">0.6098763170970346</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-8.3316260212029913</Real>
- <Real Name="Y">-0.021556799044350372</Real>
- <Real Name="Z">2.9126024124478085</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-10.161689464752982</Real>
- <Real Name="Y">-17.089473849930791</Real>
- <Real Name="Z">2.7243402470850446</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.82047027468621803</Real>
- <Real Name="Y">-1.9831421417785844</Real>
- <Real Name="Z">-1.6885186449256762</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-6.7592328484784874</Real>
- <Real Name="Y">-13.628255410655722</Real>
- <Real Name="Z">4.5099215957002059</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.38546779467344028</Real>
- <Real Name="Y">0.02575163927715321</Real>
- <Real Name="Z">0.76938178205387364</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">2.788509934829829</Real>
- <Real Name="Y">-1.0153052278633954</Real>
- <Real Name="Z">-0.5654353231810999</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">10.457353888025052</Real>
- <Real Name="Y">3.0002951075169739</Real>
- <Real Name="Z">-2.4443752014337479</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-3.1793524477443595</Real>
- <Real Name="Y">-0.77755793843714771</Real>
- <Real Name="Z">0.99148224011632069</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">3.3560643812645212</Real>
- <Real Name="Y">-0.58087462987032856</Real>
- <Real Name="Z">-2.8401295588358915</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.12980239995164852</Real>
- <Real Name="Y">-0.92250020419149636</Real>
- <Real Name="Z">-0.37393805370732247</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">1.7975931361081829</Real>
- <Real Name="Y">-20.275182172278267</Real>
- <Real Name="Z">3.4378840352447644</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">2.8085099343827942</Real>
- <Real Name="Y">-0.14530522309502381</Real>
- <Real Name="Z">0.38456466489797114</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">11.117353914251096</Real>
- <Real Name="Y">3.6702951242062745</Real>
- <Real Name="Z">-2.0643752062021195</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-3.1593524481913944</Real>
- <Real Name="Y">0.092442066331223871</Real>
- <Real Name="Z">1.9414822281953916</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">4.1860643645752207</Real>
- <Real Name="Y">-0.27087462748614277</Real>
- <Real Name="Z">-2.1101295397624051</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.58019757859067933</Real>
- <Real Name="Y">-0.86250020553260087</Real>
- <Real Name="Z">-0.023938059667786948</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.067593146837019</Real>
- <Real Name="Y">-19.295182153204781</Real>
- <Real Name="Z">4.2678840185554634</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-13.406815060008514</Real>
- <Real Name="Y">-19.465013333891342</Real>
- <Real Name="Z">6.0748932006495915</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-3.4931516109310436</Real>
- <Real Name="Y">-1.1695586621622649</Real>
- <Real Name="Z">0.37948711624127879</Real>
- </Vector>
- <Vector>
- <Real Name="X">-6.1476176241634404</Real>
- <Real Name="Y">-6.196261553099129</Real>
- <Real Name="Z">0.61604971101077255</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-8.1581138200755436</Real>
- <Real Name="Y">-14.70340061881376</Real>
- <Real Name="Z">-8.9453847792568535</Real>
+ <Real Name="X">-0.89341403958785948</Real>
+ <Real Name="Y">-19.76870795422418</Real>
+ <Real Name="Z">-5.5136166998409726</Real>
</Vector>
<Vector>
- <Real Name="X">-8.4309497156824804</Real>
- <Real Name="Y">-11.184451168201075</Real>
- <Real Name="Z">-7.7012318674352152</Real>
+ <Real Name="X">-2.9311061344089753</Real>
+ <Real Name="Y">-1.1699232689408006</Real>
+ <Real Name="Z">-3.2719141904858438</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-6.7856961418642161</Real>
- <Real Name="Y">-1.1144460047659024</Real>
- <Real Name="Z">1.6740807570530818</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-8.9307476765517411</Real>
- <Real Name="Y">-21.749342315393726</Real>
- <Real Name="Z">2.9757623819770487</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.2435070807481936</Real>
- <Real Name="Y">-2.5539276755468499</Real>
- <Real Name="Z">-1.4344239512261392</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-5.7112516981059507</Real>
- <Real Name="Y">-18.260319287161511</Real>
- <Real Name="Z">4.0572521792161034</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.5488175763921419</Real>
- <Real Name="Y">-0.092810452766203616</Real>
- <Real Name="Z">0.081070341914709868</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-13.386815060455548</Real>
- <Real Name="Y">-18.59501332912297</Real>
- <Real Name="Z">7.0248931887286625</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-3.4731516113780785</Real>
- <Real Name="Y">-0.29955865739389331</Real>
- <Real Name="Z">1.3294871043203498</Real>
- </Vector>
- <Vector>
- <Real Name="X">-5.4876175979373967</Real>
- <Real Name="Y">-5.5262615364098284</Real>
- <Real Name="Z">0.99604970624240097</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">-6.7656961423112509</Real>
- <Real Name="Y">-0.24444599999753081</Real>
- <Real Name="Z">2.6240807451321526</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-8.1007476932410416</Real>
- <Real Name="Y">-21.43934231300954</Real>
- <Real Name="Z">3.705762401050535</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.53350710220586572</Real>
- <Real Name="Y">-2.4939276768879544</Real>
- <Real Name="Z">-1.0844239571866037</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-5.4412516873771146</Real>
- <Real Name="Y">-17.280319268088025</Real>
- <Real Name="Z">4.8872521625268028</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.25881758473679217</Real>
- <Real Name="Y">0.0071895487239125033</Real>
- <Real Name="Z">0.76107034906726723</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">0.57642797601057505</Real>
- <Real Name="Y">1.242333136280001</Real>
- <Real Name="Z">2.5806575500692217</Real>
+ <Real Name="X">-7.0476399072188638</Real>
+ <Real Name="Y">-14.378902132683789</Real>
+ <Real Name="Z">-14.272277552262375</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-0.52415189724857048</Real>
+ <Real Name="Y">-1.9716549447673803</Real>
+ <Real Name="Z">-18.815861243981043</Real>
</Vector>
<Vector>
- <Real Name="X">1.1004712497141074</Real>
- <Real Name="Y">1.0571114232228618</Real>
- <Real Name="Z">2.7021153716544113</Real>
+ <Real Name="X">-6.7467960287627502</Real>
+ <Real Name="Y">-1.5410137489785949</Real>
+ <Real Name="Z">-1.2290404991250639</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-7.3281138367648442</Real>
- <Real Name="Y">-14.393400616429574</Real>
- <Real Name="Z">-8.2153847601833672</Real>
+ <Real Name="X">-0.052577361165553116</Real>
+ <Real Name="Y">-1.7509157833241376</Real>
+ <Real Name="Z">-0.070066070618527432</Real>
</Vector>
<Vector>
- <Real Name="X">-7.7209497371401525</Real>
- <Real Name="Y">-11.12445116954218</Real>
- <Real Name="Z">-7.3512318733956796</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
+ <Real Name="X">-1.1903269785073174</Real>
+ <Real Name="Y">-1.7428224529077028</Real>
+ <Real Name="Z">-4.3636777044640338</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-16.205517527929572</Real>
- <Real Name="Y">-7.3188043172213684</Real>
- <Real Name="Z">-7.9336359387100472</Real>
+ <Real Name="X">-8.2305961590882664</Real>
+ <Real Name="Y">1.2798951389932887</Real>
+ <Real Name="Z">-6.3929958163443716</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-3.4582204419484599</Real>
- <Real Name="Y">-3.9969224751666577</Real>
- <Real Name="Z">-9.9756355772564991</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.067954884757908562</Real>
- <Real Name="Y">-0.85449341275494772</Real>
- <Real Name="Z">-5.12573966904852</Real>
+ <Real Name="X">1.4460874540966253</Real>
+ <Real Name="Y">2.1584071797019928</Real>
+ <Real Name="Z">1.0820509080507321</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">-0.72589890716513583</Real>
+ <Real Name="Y">-24.710884942780222</Real>
+ <Real Name="Z">-4.3321274070179072</Real>
+ </Vector>
+ <Vector>
+ <Real Name="X">-2.3815237342072924</Real>
+ <Real Name="Y">-1.4624040861760008</Real>
+ <Real Name="Z">-2.5707897210960202</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
<Real Name="Z">0</Real>
</Vector>
- <Vector>
- <Real Name="X">-2.9109058261904628</Real>
- <Real Name="Y">-11.975420811795583</Real>
- <Real Name="Z">-18.523630115333241</Real>
- </Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-16.185517528376607</Real>
- <Real Name="Y">-6.4488043124529968</Real>
- <Real Name="Z">-6.9836359506309762</Real>
+ <Real Name="X">-5.7262074246153265</Real>
+ <Real Name="Y">-17.973627665854735</Real>
+ <Real Name="Z">-11.213932362491866</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-3.4382204423954947</Real>
- <Real Name="Y">-3.1269224703982861</Real>
- <Real Name="Z">-9.025635589177428</Real>
+ <Real Name="X">-0.42587341651446342</Real>
+ <Real Name="Y">-2.4645686809592258</Real>
+ <Real Name="Z">-14.783890977413678</Real>
</Vector>
<Vector>
- <Real Name="X">0.59204514146813514</Real>
- <Real Name="Y">-0.18449339606564719</Real>
- <Real Name="Z">-4.7457396738168915</Real>
+ <Real Name="X">-5.4817717733697346</Real>
+ <Real Name="Y">-1.9262671862232437</Real>
+ <Real Name="Z">-0.96567467788397876</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.82999998331069946</Real>
- <Real Name="Y">0.31000000238418579</Real>
- <Real Name="Z">0.73000001907348633</Real>
+ <Real Name="X">-0.0427191059470119</Real>
+ <Real Name="Y">-2.1886447291551718</Real>
+ <Real Name="Z">-0.055051912628842979</Real>
</Vector>
<Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-2.6409058154616267</Real>
- <Real Name="Y">-10.995420792722097</Real>
- <Real Name="Z">-17.693630132022541</Real>
+ <Real Name="X">-0.96714067003719539</Real>
+ <Real Name="Y">-2.1785280661346289</Real>
+ <Real Name="Z">-3.4286039106503119</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-10.129964503493252</Real>
- <Real Name="Y">1.0239161111946307</Real>
- <Real Name="Z">-8.1365401298928379</Real>
+ <Real Name="X">3.0030106990475081</Real>
+ <Real Name="Y">-0.97947087544725719</Real>
+ <Real Name="Z">0.52873130622863018</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">1.7797999435035388</Real>
- <Real Name="Y">1.7267257437615944</Real>
- <Real Name="Z">1.3771557011554771</Real>
+ <Real Name="X">11.261765725565441</Real>
+ <Real Name="Y">2.8944021905057711</Real>
+ <Real Name="Z">8.1326966202729416</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">-3.423918020647772</Real>
+ <Real Name="Y">-0.75011467859246217</Real>
+ <Real Name="Z">-0.37339673869951689</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.89341403958785948</Real>
- <Real Name="Y">-19.76870795422418</Real>
- <Real Name="Z">-5.5136166998409726</Real>
+ <Real Name="X">3.6142231798233309</Real>
+ <Real Name="Y">-0.5603731435929743</Real>
+ <Real Name="Z">-15.314157091800631</Real>
</Vector>
<Vector>
- <Real Name="X">-2.9311061344089753</Real>
- <Real Name="Y">-1.1699232689408006</Real>
- <Real Name="Z">-3.2719141904858438</Real>
+ <Real Name="X">-0.13978719994792918</Real>
+ <Real Name="Y">-0.88994132779279667</Real>
+ <Real Name="Z">-4.3663155404400467</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">1.935869531193428</Real>
+ <Real Name="Y">-19.559586503779869</Real>
+ <Real Name="Z">4.8894339493261105</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-10.109964503940287</Real>
- <Real Name="Y">1.8939161159630022</Real>
- <Real Name="Z">-7.1865401418137669</Real>
+ <Real Name="X">-14.438108526163012</Real>
+ <Real Name="Y">-18.778011899791231</Real>
+ <Real Name="Z">-7.4710258563699679</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-0.49656498125090714</Real>
+ <Real Name="Y">-0.85139644735204068</Real>
+ <Real Name="Z">-6.170384440946111</Real>
</Vector>
<Vector>
- <Real Name="X">2.4397999697295827</Real>
- <Real Name="Y">2.3967257604508951</Real>
- <Real Name="Z">1.7571556963871056</Real>
+ <Real Name="X">-6.6205112875606282</Real>
+ <Real Name="Y">-5.9775696621654237</Real>
+ <Real Name="Z">-16.795786276144295</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-7.3076727681614635</Real>
+ <Real Name="Y">-1.0751125611988102</Real>
+ <Real Name="Z">-3.5350277386547013</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.063414056277160014</Real>
- <Real Name="Y">-19.458707951839994</Real>
- <Real Name="Z">-4.7836166807674863</Real>
+ <Real Name="X">-9.6177282670557229</Real>
+ <Real Name="Y">-20.98171739240464</Real>
+ <Real Name="Z">-24.469455185751023</Real>
</Vector>
<Vector>
- <Real Name="X">-2.2211061558666474</Real>
- <Real Name="Y">-1.1099232702819051</Real>
- <Real Name="Z">-2.9219141964463082</Real>
+ <Real Name="X">-1.3391614715749778</Real>
+ <Real Name="Y">-2.4637889252880081</Real>
+ <Real Name="Z">-17.156428586866937</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
+ <Real Name="X">-6.1505787518064086</Real>
+ <Real Name="Y">-17.61583652610614</Real>
+ <Real Name="Z">-4.4618914487107055</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">-0.59103431303769127</Real>
+ <Real Name="Y">-0.089534785133402892</Real>
+ <Real Name="Z">-0.71108816991442636</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">0.70483443211617736</Real>
- <Real Name="Y">1.1678665099776753</Real>
- <Real Name="Z">3.0253823397028992</Real>
+ <Real Name="X">-19.945252342067167</Real>
+ <Real Name="Y">-5.8550434537770943</Real>
+ <Real Name="Z">-10.097354831085514</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-7.0476399072188638</Real>
- <Real Name="Y">-14.378902132683789</Real>
- <Real Name="Z">-14.272277552262375</Real>
+ <Real Name="X">2.4399461929761004</Real>
+ <Real Name="Y">-1.2243385943090714</Real>
+ <Real Name="Z">0.41543174060820942</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.52415189724857048</Real>
- <Real Name="Y">-1.9716549447673803</Real>
- <Real Name="Z">-18.815861243981043</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-6.7467960287627502</Real>
- <Real Name="Y">-1.5410137489785949</Real>
- <Real Name="Z">-1.2290404991250639</Real>
+ <Real Name="X">9.1501846520219203</Real>
+ <Real Name="Y">3.6180027381322137</Real>
+ <Real Name="Z">6.3899759159287406</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">-2.7819333917763145</Real>
+ <Real Name="Y">-0.93764334824057782</Real>
+ <Real Name="Z">-0.2933831518353347</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.052577361165553116</Real>
- <Real Name="Y">-1.7509157833241376</Real>
- <Real Name="Z">-0.070066070618527432</Real>
+ <Real Name="X">2.9365563336064566</Real>
+ <Real Name="Y">-0.70046642949121796</Real>
+ <Real Name="Z">-12.032552000700495</Real>
</Vector>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">-0.11357709995769247</Real>
+ <Real Name="Y">-1.112426659740996</Real>
+ <Real Name="Z">-3.4306764960600371</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-1.1903269785073174</Real>
- <Real Name="Y">-1.7428224529077028</Real>
- <Real Name="Z">-4.3636777044640338</Real>
+ <Real Name="X">1.5728939940946602</Real>
+ <Real Name="Y">-24.449483129724836</Real>
+ <Real Name="Z">3.8416981030419435</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-7.0276399076658986</Real>
- <Real Name="Y">-13.508902127915418</Real>
- <Real Name="Z">-13.322277564183304</Real>
+ <Real Name="X">-11.730963177507448</Real>
+ <Real Name="Y">-23.472514874739037</Real>
+ <Real Name="Z">-5.870091744290689</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.50415189769560531</Real>
- <Real Name="Y">-1.1016549399990088</Real>
- <Real Name="Z">-17.865861255901972</Real>
+ <Real Name="X">-3.0565076595646632</Real>
+ <Real Name="Y">-1.4103500790664754</Real>
+ <Real Name="Z">-4.9677026084105016</Real>
</Vector>
<Vector>
- <Real Name="X">-6.0867960025367065</Real>
- <Real Name="Y">-0.87101373228929435</Real>
- <Real Name="Z">-0.84904050389343544</Real>
+ <Real Name="X">-5.3791654211430107</Real>
+ <Real Name="Y">-7.4719620777067792</Real>
+ <Real Name="Z">-13.196689216970519</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-5.9374841241311893</Real>
+ <Real Name="Y">-1.3438907014985126</Real>
+ <Real Name="Z">-2.7775217946572655</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.77742262214514635</Real>
- <Real Name="Y">-1.4409157809399518</Real>
- <Real Name="Z">0.6599339484549589</Real>
+ <Real Name="X">-7.8144042169827745</Real>
+ <Real Name="Y">-26.227146740505805</Real>
+ <Real Name="Z">-19.226000503090088</Real>
</Vector>
<Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
+ <Real Name="X">-1.0880686956546695</Real>
+ <Real Name="Y">-3.0797361566100099</Real>
+ <Real Name="Z">-13.480051032538309</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.92032696777848133</Real>
- <Real Name="Y">-0.76282243383421644</Real>
- <Real Name="Z">-3.5336777211533343</Real>
+ <Real Name="X">-4.9973452358427064</Real>
+ <Real Name="Y">-22.019795657632674</Real>
+ <Real Name="Z">-3.5057718525584116</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">-0.48021537934312419</Real>
+ <Real Name="Y">-0.1119184814167536</Real>
+ <Real Name="Z">-0.55871213350419213</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-8.2305961590882664</Real>
- <Real Name="Y">1.2798951389932887</Real>
- <Real Name="Z">-6.3929958163443734</Real>
+ <Real Name="X">0.78266792292938536</Real>
+ <Real Name="Y">0.24701126089639641</Real>
+ <Real Name="Z">0.075197087339731225</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">1.4460874540966253</Real>
- <Real Name="Y">2.1584071797019928</Real>
- <Real Name="Z">1.0820509080507321</Real>
+ <Real Name="X">0.61956391875244121</Real>
+ <Real Name="Y">0.25681538531643089</Real>
+ <Real Name="Z">0.264650385589911</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.72589890716513583</Real>
- <Real Name="Y">-24.710884942780222</Real>
- <Real Name="Z">-4.3321274070179072</Real>
+ <Real Name="X">-11.475149109556806</Real>
+ <Real Name="Y">-9.7544516427343577</Real>
+ <Real Name="Z">3.0247422457903341</Real>
</Vector>
<Vector>
- <Real Name="X">-2.3815237342072924</Real>
- <Real Name="Y">-1.4624040861760008</Real>
- <Real Name="Z">-2.5707897210960202</Real>
+ <Real Name="X">-11.858918281399532</Real>
+ <Real Name="Y">-7.4199289605932677</Real>
+ <Real Name="Z">3.011716132619819</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-8.2105961595353012</Real>
- <Real Name="Y">2.1498951437616602</Real>
- <Real Name="Z">-5.4429958282653024</Real>
+ <Real Name="X">-22.79457410521962</Real>
+ <Real Name="Y">-4.8554021376267826</Real>
+ <Real Name="Z">5.6800905790772545</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-4.2562713131673355</Real>
+ <Real Name="Y">-3.1975379801333257</Real>
+ <Real Name="Z">-12.696263461962817</Real>
</Vector>
<Vector>
- <Real Name="X">1.2021184551344297</Real>
- <Real Name="Y">0.97968914191614953</Real>
- <Real Name="Z">3.3354195652242611</Real>
+ <Real Name="X">-0.083636781240502847</Real>
+ <Real Name="Y">-0.683594730203958</Real>
+ <Real Name="Z">-6.5236686696981163</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-4.8643100721912402</Real>
+ <Real Name="Y">-2.6516169976273649</Real>
+ <Real Name="Z">-0.25116456753339361</Real>
</Vector>
<Vector>
- <Real Name="X">2.1060874803226692</Real>
- <Real Name="Y">2.8284071963912933</Real>
- <Real Name="Z">1.4620509032823605</Real>
+ <Real Name="X">-0.09558489284628896</Real>
+ <Real Name="Y">-0.56688346388984168</Real>
+ <Real Name="Z">-0.94910028423615156</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.10410107614556363</Real>
- <Real Name="Y">-24.400884940396036</Real>
- <Real Name="Z">-3.6021273879444209</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-1.6715237556649645</Real>
- <Real Name="Y">-1.4024040875171053</Real>
- <Real Name="Z">-2.2207897270564847</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
+ <Real Name="X">-4.0944609423338374</Real>
+ <Real Name="Y">-7.9446698242436193</Real>
+ <Real Name="Z">-1.3877955568392644</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-5.7262074246153265</Real>
- <Real Name="Y">-17.973627665854735</Real>
- <Real Name="Z">-11.213932362491866</Real>
+ <Real Name="X">0.63591768738012566</Real>
+ <Real Name="Y">0.3087640761204955</Real>
+ <Real Name="Z">0.03426844856107035</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.42587341651446342</Real>
- <Real Name="Y">-2.4645686809592258</Real>
- <Real Name="Z">-14.783890977413678</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-5.4817717733697346</Real>
- <Real Name="Y">-1.9262671862232437</Real>
- <Real Name="Z">-0.96567467788397876</Real>
+ <Real Name="X">0.50339568398635848</Real>
+ <Real Name="Y">0.32101923164553864</Real>
+ <Real Name="Z">0.18363175660878781</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.0427191059470119</Real>
- <Real Name="Y">-2.1886447291551718</Real>
- <Real Name="Z">-0.055051912628842979</Real>
+ <Real Name="X">-9.3235586515149063</Real>
+ <Real Name="Y">-12.193064553417946</Real>
+ <Real Name="Z">3.2071979869138385</Real>
+ </Vector>
+ <Vector>
+ <Real Name="X">-9.6353711036371195</Real>
+ <Real Name="Y">-9.2749112007415846</Real>
+ <Real Name="Z">3.0222260742447977</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
<Real Name="Z">0</Real>
</Vector>
- <Vector>
- <Real Name="X">-0.96714067003719539</Real>
- <Real Name="Y">-2.1785280661346289</Real>
- <Real Name="Z">-3.4286039106503119</Real>
- </Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-5.7062074250623613</Real>
- <Real Name="Y">-17.103627661086364</Real>
- <Real Name="Z">-10.263932374412795</Real>
+ <Real Name="X">-18.520591460490941</Real>
+ <Real Name="Y">-6.0692526720334774</Real>
+ <Real Name="Z">5.0076479125818185</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.40587341696149826</Real>
- <Real Name="Y">-1.5945686761908542</Real>
- <Real Name="Z">-13.833890989334607</Real>
+ <Real Name="X">-3.9522519336553823</Real>
+ <Real Name="Y">-3.3145212470342056</Real>
+ <Real Name="Z">0.041856812732197594</Real>
</Vector>
<Vector>
- <Real Name="X">-4.8217717471436909</Real>
- <Real Name="Y">-1.2562671695339431</Real>
- <Real Name="Z">-0.58567468265235034</Real>
+ <Real Name="X">-0.077662725437609784</Real>
+ <Real Name="Y">-0.70860432986230215</Real>
+ <Real Name="Z">-0.70184026829559087</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.78728087736368757</Real>
- <Real Name="Y">-1.878644726770986</Real>
- <Real Name="Z">0.67494810644464331</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.69714065930835933</Real>
- <Real Name="Y">-1.1985280470611426</Real>
- <Real Name="Z">-2.5986039273396124</Real>
+ <Real Name="X">-3.326749515646243</Real>
+ <Real Name="Y">-9.9308372803045231</Real>
+ <Real Name="Z">-0.45425921737202102</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">3.0030106990475081</Real>
- <Real Name="Y">-0.97947087544725719</Real>
- <Real Name="Z">0.52873130622863018</Real>
+ <Real Name="X">-11.577102289706572</Real>
+ <Real Name="Y">0.84910120894795016</Real>
+ <Real Name="Z">1.8482439089193423</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">11.261765725565441</Real>
- <Real Name="Y">2.8944021905057711</Real>
- <Real Name="Z">8.1326966202729416</Real>
+ <Real Name="X">2.0340570782897585</Real>
+ <Real Name="Y">1.4319189829320136</Real>
+ <Real Name="Z">-0.59251856152304705</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-9.2107554875515074</Real>
- <Real Name="Y">-11.452720492666822</Real>
- <Real Name="Z">-10.655035154526145</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-9.6665535176822637</Real>
- <Real Name="Y">-8.8875609359019645</Real>
- <Real Name="Z">-9.4515678372416474</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
+ <Real Name="X">-3.5826533245421075</Real>
+ <Real Name="Y">-9.5803366494364646</Real>
+ <Real Name="Z">-23.575529237696852</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-3.423918020647772</Real>
- <Real Name="Y">-0.75011467859246217</Real>
- <Real Name="Z">-0.37339673869951695</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">3.6142231798233309</Real>
- <Real Name="Y">-0.5603731435929743</Real>
- <Real Name="Z">-15.314157091800631</Real>
+ <Real Name="X">-1.0210446166718394</Real>
+ <Real Name="Y">-16.393563534893939</Real>
+ <Real Name="Z">2.0765205102067403</Real>
</Vector>
<Vector>
- <Real Name="X">-0.13978719994792918</Real>
- <Real Name="Y">-0.88994132779279667</Real>
- <Real Name="Z">-4.3663155404400467</Real>
+ <Real Name="X">-3.3498355821816856</Real>
+ <Real Name="Y">-0.97018032158412315</Real>
+ <Real Name="Z">0.58368499271815877</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">1.935869531193428</Real>
- <Real Name="Y">-19.559586503779869</Real>
- <Real Name="Z">4.8894339493261105</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">3.0230106986004732</Real>
- <Real Name="Y">-0.10947087067888561</Real>
- <Real Name="Z">1.4787312943077011</Real>
+ <Real Name="X">-8.0544456082501288</Real>
+ <Real Name="Y">-11.923968234039531</Real>
+ <Real Name="Z">1.9257328983388657</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-0.59903073971265186</Real>
+ <Real Name="Y">-1.6350310136998707</Real>
+ <Real Name="Z">-2.6446765062295143</Real>
</Vector>
<Vector>
- <Real Name="X">11.921765751791485</Real>
- <Real Name="Y">3.5644022071950716</Real>
- <Real Name="Z">8.51269661550457</Real>
+ <Real Name="X">-7.7106240328717144</Real>
+ <Real Name="Y">-1.2779139061856373</Real>
+ <Real Name="Z">2.2200763403785335</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-3.4039180210948068</Real>
- <Real Name="Y">0.11988532617590941</Real>
- <Real Name="Z">0.57660324937955409</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">4.4442231631340299</Real>
- <Real Name="Y">-0.25037314120878851</Real>
- <Real Name="Z">-14.584157072727145</Real>
+ <Real Name="X">-0.060088412760632121</Real>
+ <Real Name="Y">-1.4519790167692483</Real>
+ <Real Name="Z">0.24378158880830342</Real>
</Vector>
<Vector>
- <Real Name="X">0.57021277859439867</Real>
- <Real Name="Y">-0.82994132913390117</Real>
- <Real Name="Z">-4.0163155464005111</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">2.2058695419222643</Real>
- <Real Name="Y">-18.579586484706383</Real>
- <Real Name="Z">5.71943393263681</Real>
+ <Real Name="X">-1.3603736897226484</Real>
+ <Real Name="Y">-1.4452674741283262</Real>
+ <Real Name="Z">-0.088156767496452001</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-14.438108526163015</Real>
- <Real Name="Y">-18.778011899791231</Real>
- <Real Name="Z">-7.4710258563699679</Real>
+ <Real Name="X">-9.4063956103865909</Real>
+ <Real Name="Y">1.0613765111849378</Real>
+ <Real Name="Z">1.4765278904032617</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.49656498125090714</Real>
- <Real Name="Y">-0.85139644735204068</Real>
- <Real Name="Z">-6.170384440946111</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-6.6205112875606282</Real>
- <Real Name="Y">-5.9775696621654237</Real>
- <Real Name="Z">-16.795786276144295</Real>
+ <Real Name="X">1.6526713761104288</Real>
+ <Real Name="Y">1.789898728665017</Real>
+ <Real Name="Z">-0.59016766968693601</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-7.3076727681614635</Real>
- <Real Name="Y">-1.0751125611988102</Real>
- <Real Name="Z">-3.5350277386547013</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-9.6177282670557229</Real>
- <Real Name="Y">-20.98171739240464</Real>
- <Real Name="Z">-24.469455185751023</Real>
+ <Real Name="X">-0.82959875104586944</Real>
+ <Real Name="Y">-20.491954418617421</Real>
+ <Real Name="Z">2.8871516559459058</Real>
</Vector>
<Vector>
- <Real Name="X">-1.3391614715749778</Real>
- <Real Name="Y">-2.4637889252880081</Real>
- <Real Name="Z">-17.156428586866937</Real>
+ <Real Name="X">-2.7217414105226196</Real>
+ <Real Name="Y">-1.2127254019801541</Real>
+ <Real Name="Z">0.55819396762823659</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-6.1505787518064086</Real>
- <Real Name="Y">-17.61583652610614</Real>
- <Real Name="Z">-4.4618914487107055</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.59103431303769127</Real>
- <Real Name="Y">-0.089534785133402892</Real>
- <Real Name="Z">-0.71108816991442636</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-14.41810852661005</Real>
- <Real Name="Y">-17.90801189502286</Real>
- <Real Name="Z">-6.5210258682908968</Real>
+ <Real Name="X">-6.5442370567032295</Real>
+ <Real Name="Y">-14.904960292549413</Real>
+ <Real Name="Z">2.4825316419739121</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-0.47656498169794198</Real>
- <Real Name="Y">0.018603557416330907</Real>
- <Real Name="Z">-5.22038445286704</Real>
+ <Real Name="X">-0.48671247601652962</Real>
+ <Real Name="Y">-2.0437887671248385</Real>
+ <Real Name="Z">-1.9489107480528729</Real>
</Vector>
<Vector>
- <Real Name="X">-5.9605112613345845</Real>
- <Real Name="Y">-5.3075696454761232</Real>
- <Real Name="Z">-16.415786280912666</Real>
+ <Real Name="X">-6.2648820267082685</Real>
+ <Real Name="Y">-1.5973923827320464</Real>
+ <Real Name="Z">1.9008625299783468</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-7.2876727686084983</Real>
- <Real Name="Y">-0.20511255643043858</Real>
- <Real Name="Z">-2.5850277505756303</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-8.7877282837450235</Real>
- <Real Name="Y">-20.671717390020454</Real>
- <Real Name="Z">-23.739455166677537</Real>
+ <Real Name="X">-0.0488218353680136</Real>
+ <Real Name="Y">-1.8149737709615605</Real>
+ <Real Name="Z">0.30251804902903451</Real>
</Vector>
<Vector>
- <Real Name="X">-0.6291614930326499</Real>
- <Real Name="Y">-2.4037889266291126</Real>
- <Real Name="Z">-16.806428592827402</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-5.8805787410775725</Real>
- <Real Name="Y">-16.635836507032653</Real>
- <Real Name="Z">-3.6318914654000061</Real>
+ <Real Name="X">-1.1053036228996518</Real>
+ <Real Name="Y">-1.8065843426604078</Real>
+ <Real Name="Z">0.051190455240391619</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.30103432138234154</Real>
- <Real Name="Y">0.010465216356713228</Real>
- <Real Name="Z">-0.031088162761868987</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-19.945252342067167</Real>
- <Real Name="Y">-5.8550434537770943</Real>
- <Real Name="Z">-10.097354831085514</Real>
+ <Real Name="X">0.55642797645760989</Real>
+ <Real Name="Y">0.3723331315116295</Real>
+ <Real Name="Z">1.6306575619901507</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">2.4399461929761004</Real>
- <Real Name="Y">-1.2243385943090714</Real>
- <Real Name="Z">0.41543174060820942</Real>
+ <Real Name="X">3.4320122274828666</Real>
+ <Real Name="Y">-0.81224418229071649</Real>
+ <Real Name="Z">-0.764761636476889</Real>
</Vector>
</Sequence>
</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">9.1501846520219203</Real>
- <Real Name="Y">3.6180027381322137</Real>
- <Real Name="Z">6.3899759159287406</Real>
+ <Real Name="X">12.870589400646217</Real>
+ <Real Name="Y">2.4002360860135794</Real>
+ <Real Name="Z">-2.7526346195710181</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-2.7819333917763145</Real>
- <Real Name="Y">-0.93764334824057782</Real>
- <Real Name="Z">-0.29338315183533475</Real>
+ <Real Name="X">-3.9130491664545959</Real>
+ <Real Name="Y">-0.62204635074971815</Real>
+ <Real Name="Z">1.1633583220151211</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">2.9365563336064566</Real>
- <Real Name="Y">-0.70046642949121796</Real>
- <Real Name="Z">-12.032552000700495</Real>
+ <Real Name="X">4.1305407769409488</Real>
+ <Real Name="Y">-0.46469970389626269</Real>
+ <Real Name="Z">-3.6193285397896875</Real>
</Vector>
<Vector>
- <Real Name="X">-0.11357709995769247</Real>
- <Real Name="Y">-1.112426659740996</Real>
- <Real Name="Z">-3.4306764960600371</Real>
+ <Real Name="X">-0.1597567999404905</Real>
+ <Real Name="Y">-0.73800016335319685</Real>
+ <Real Name="Z">-0.54897393926970917</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">1.5728939940946602</Real>
- <Real Name="Y">-24.449483129724836</Real>
- <Real Name="Z">3.8416981030419435</Real>
+ <Real Name="X">2.2124223213639174</Real>
+ <Real Name="Y">-16.220145737822616</Real>
+ <Real Name="Z">2.8258755564357965</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">2.4599461925290655</Real>
- <Real Name="Y">-0.35433858954069986</Real>
- <Real Name="Z">1.3654317286872804</Real>
+ <Real Name="X">-16.500695458472013</Real>
+ <Real Name="Y">-15.572010667113076</Real>
+ <Real Name="Z">6.0618364657657224</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
+ <Real Name="X">-0.56750283571532234</Real>
+ <Real Name="Y">-0.70603611451836135</Real>
+ <Real Name="Z">-0.73298662849655538</Real>
</Vector>
<Vector>
- <Real Name="X">9.810184678247964</Real>
- <Real Name="Y">4.2880027548215143</Real>
- <Real Name="Z">6.769975911160369</Real>
+ <Real Name="X">-7.5662986143550031</Real>
+ <Real Name="Y">-4.9570092424793035</Real>
+ <Real Name="Z">0.22987632186540616</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-2.7619333922233493</Real>
- <Real Name="Y">-0.067643343472206241</Real>
- <Real Name="Z">0.65661683624373635</Real>
+ <Real Name="X">-8.3516260207559565</Real>
+ <Real Name="Y">-0.89155680381272195</Real>
+ <Real Name="Z">1.9626024243687374</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">3.7665563169171561</Real>
- <Real Name="Y">-0.39046642710703217</Real>
- <Real Name="Z">-11.302551981627008</Real>
+ <Real Name="X">-10.991689448063681</Real>
+ <Real Name="Y">-17.399473852314976</Real>
+ <Real Name="Z">1.9943402280115583</Real>
</Vector>
<Vector>
- <Real Name="X">0.59642287858463539</Real>
- <Real Name="Y">-1.0524266610821005</Real>
- <Real Name="Z">-3.0806765020205016</Real>
+ <Real Name="X">-1.5304702532285459</Real>
+ <Real Name="Y">-2.0431421404374799</Real>
+ <Real Name="Z">-2.0385186389652117</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">1.8428940048234963</Real>
- <Real Name="Y">-23.46948311065135</Real>
- <Real Name="Z">4.6716980863526434</Real>
+ <Real Name="X">-7.0292328592073234</Real>
+ <Real Name="Y">-14.608255429729208</Real>
+ <Real Name="Z">3.679921612389506</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
+ <Real Name="X">-0.67546778632879001</Real>
+ <Real Name="Y">-0.07424836221296291</Real>
+ <Real Name="Z">0.089381774901316297</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-11.73096317750745</Real>
- <Real Name="Y">-23.472514874739037</Real>
- <Real Name="Z">-5.870091744290689</Real>
+ <Real Name="X">2.788509934829829</Real>
+ <Real Name="Y">-1.0153052278633954</Real>
+ <Real Name="Z">-0.5654353231810999</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-3.0565076595646632</Real>
- <Real Name="Y">-1.4103500790664754</Real>
- <Real Name="Z">-4.9677026084105016</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-5.3791654211430107</Real>
- <Real Name="Y">-7.4719620777067792</Real>
- <Real Name="Z">-13.196689216970519</Real>
+ <Real Name="X">10.457353888025052</Real>
+ <Real Name="Y">3.0002951075169739</Real>
+ <Real Name="Z">-2.4443752014337479</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-5.9374841241311893</Real>
- <Real Name="Y">-1.3438907014985126</Real>
- <Real Name="Z">-2.7775217946572655</Real>
+ <Real Name="X">-3.1793524477443595</Real>
+ <Real Name="Y">-0.77755793843714771</Real>
+ <Real Name="Z">0.99148224011632069</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-7.8144042169827745</Real>
- <Real Name="Y">-26.227146740505805</Real>
- <Real Name="Z">-19.226000503090088</Real>
+ <Real Name="X">3.3560643812645212</Real>
+ <Real Name="Y">-0.58087462987032856</Real>
+ <Real Name="Z">-2.8401295588358915</Real>
</Vector>
<Vector>
- <Real Name="X">-1.0880686956546695</Real>
- <Real Name="Y">-3.0797361566100099</Real>
- <Real Name="Z">-13.480051032538309</Real>
+ <Real Name="X">-0.12980239995164852</Real>
+ <Real Name="Y">-0.92250020419149636</Real>
+ <Real Name="Z">-0.37393805370732247</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-4.9973452358427064</Real>
- <Real Name="Y">-22.019795657632674</Real>
- <Real Name="Z">-3.5057718525584116</Real>
+ <Real Name="X">1.7975931361081829</Real>
+ <Real Name="Y">-20.275182172278267</Real>
+ <Real Name="Z">3.4378840352447644</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.48021537934312419</Real>
- <Real Name="Y">-0.1119184814167536</Real>
- <Real Name="Z">-0.55871213350419213</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-11.710963177954484</Real>
- <Real Name="Y">-22.602514869970666</Real>
- <Real Name="Z">-4.920091756211618</Real>
+ <Real Name="X">-13.406815060008512</Real>
+ <Real Name="Y">-19.465013333891342</Real>
+ <Real Name="Z">6.0748932006495915</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-4.2562713131673355</Real>
- <Real Name="Y">-3.1975379801333257</Real>
- <Real Name="Z">-12.696263461962817</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.083636781240502847</Real>
- <Real Name="Y">-0.683594730203958</Real>
- <Real Name="Z">-6.5236686696981163</Real>
+ <Real Name="X">0.44047122348806367</Real>
+ <Real Name="Y">0.3871114065335613</Real>
+ <Real Name="Z">2.3221153764227829</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">2</Int>
<Vector>
- <Real Name="X">-3.036507660011698</Real>
- <Real Name="Y">-0.54035007429810378</Real>
- <Real Name="Z">-4.0177026203314306</Real>
+ <Real Name="X">-3.4931516109310436</Real>
+ <Real Name="Y">-1.1695586621622649</Real>
+ <Real Name="Z">0.37948711624127879</Real>
</Vector>
<Vector>
- <Real Name="X">-4.719165394916967</Real>
- <Real Name="Y">-6.8019620610174787</Real>
- <Real Name="Z">-12.816689221738891</Real>
+ <Real Name="X">-6.1476176241634404</Real>
+ <Real Name="Y">-6.196261553099129</Real>
+ <Real Name="Z">0.61604971101077255</Real>
</Vector>
</Sequence>
</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">13</Int>
<Vector>
- <Real Name="X">-5.9174841245782241</Real>
- <Real Name="Y">-0.47389069673014106</Real>
- <Real Name="Z">-1.8275218065781944</Real>
+ <Real Name="X">-6.7856961418642161</Real>
+ <Real Name="Y">-1.1144460047659024</Real>
+ <Real Name="Z">1.6740807570530818</Real>
</Vector>
<Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-6.9844042336720751</Real>
- <Real Name="Y">-25.91714673812162</Real>
- <Real Name="Z">-18.496000484016601</Real>
+ <Real Name="X">-8.9307476765517411</Real>
+ <Real Name="Y">-21.749342315393726</Real>
+ <Real Name="Z">2.9757623819770487</Real>
</Vector>
<Vector>
- <Real Name="X">-0.37806871711234158</Real>
- <Real Name="Y">-3.0197361579511144</Real>
- <Real Name="Z">-13.130051038498774</Real>
+ <Real Name="X">-1.2435070807481936</Real>
+ <Real Name="Y">-2.5539276755468499</Real>
+ <Real Name="Z">-1.4344239512261392</Real>
</Vector>
<Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-4.7273452251138703</Real>
- <Real Name="Y">-21.039795638559188</Real>
- <Real Name="Z">-2.6757718692477122</Real>
+ <Real Name="X">-5.7112516981059507</Real>
+ <Real Name="Y">-18.260319287161511</Real>
+ <Real Name="Z">4.0572521792161034</Real>
</Vector>
<Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">-0.19021538768777446</Real>
- <Real Name="Y">-0.011918479926637485</Real>
- <Real Name="Z">0.12128787364836524</Real>
+ <Real Name="X">-0.5488175763921419</Real>
+ <Real Name="Y">-0.092810452766203616</Real>
+ <Real Name="Z">0.081070341914709868</Real>
</Vector>
<Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
+ <Real Name="X">0</Real>
+ <Real Name="Y">0</Real>
+ <Real Name="Z">0</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">0.78266792292938536</Real>
- <Real Name="Y">0.24701126089639641</Real>
- <Real Name="Z">0.075197087339731225</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.61956391875244121</Real>
- <Real Name="Y">0.25681538531643089</Real>
- <Real Name="Z">0.264650385589911</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-11.475149109556806</Real>
- <Real Name="Y">-9.7544516427343577</Real>
- <Real Name="Z">3.0247422457903341</Real>
- </Vector>
- <Vector>
- <Real Name="X">-11.858918281399532</Real>
- <Real Name="Y">-7.4199289605932677</Real>
- <Real Name="Z">3.011716132619819</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">0.80266792248235053</Real>
- <Real Name="Y">1.1170112656647679</Real>
- <Real Name="Z">1.0251970754188022</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">1.2795639449784848</Real>
- <Real Name="Y">0.92681540200573143</Real>
- <Real Name="Z">0.64465038082153936</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-10.645149126246107</Real>
- <Real Name="Y">-9.4444516403501719</Real>
- <Real Name="Z">3.7547422648638205</Real>
- </Vector>
- <Vector>
- <Real Name="X">-11.148918302857204</Real>
- <Real Name="Y">-7.3599289619343722</Real>
- <Real Name="Z">3.3617161266593545</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-22.79457410521962</Real>
- <Real Name="Y">-4.8554021376267826</Real>
- <Real Name="Z">5.6800905790772545</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-4.8643100721912402</Real>
- <Real Name="Y">-2.6516169976273649</Real>
- <Real Name="Z">-0.25116456753339361</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.09558489284628896</Real>
- <Real Name="Y">-0.56688346388984168</Real>
- <Real Name="Z">-0.94910028423615156</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Real Name="Z">0</Real>
</Vector>
<Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
+ <Real Name="X">-8.1581138200755436</Real>
+ <Real Name="Y">-14.70340061881376</Real>
+ <Real Name="Z">-8.9453847792568535</Real>
+ </Vector>
+ <Vector>
+ <Real Name="X">-8.4309497156824804</Real>
+ <Real Name="Y">-11.184451168201075</Real>
+ <Real Name="Z">-7.7012318674352152</Real>
</Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
<Real Name="Z">0</Real>
</Vector>
- <Vector>
- <Real Name="X">-3.5826533245421075</Real>
- <Real Name="Y">-9.5803366494364646</Real>
- <Real Name="Z">-23.575529237696852</Real>
- </Vector>
<Vector>
<Real Name="X">0</Real>
<Real Name="Y">0</Real>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-4.0944609423338374</Real>
- <Real Name="Y">-7.9446698242436193</Real>
- <Real Name="Z">-1.3877955568392644</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-22.774574105666655</Real>
- <Real Name="Y">-3.9854021328584111</Real>
- <Real Name="Z">6.6300905671563255</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-4.8443100726382751</Real>
- <Real Name="Y">-1.7816169928589933</Real>
- <Real Name="Z">0.69883542054567749</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.56441513337975469</Real>
- <Real Name="Y">0.10311655279945886</Real>
- <Real Name="Z">-0.56910028900452314</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.82999998331069946</Real>
- <Real Name="Y">0.31000000238418579</Real>
- <Real Name="Z">0.73000001907348633</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-3.8244609316050013</Real>
- <Real Name="Y">-6.964669805170133</Real>
- <Real Name="Z">-0.5577955735285649</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">0.63591768738012566</Real>
- <Real Name="Y">0.3087640761204955</Real>
- <Real Name="Z">0.03426844856107035</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.50339568398635848</Real>
- <Real Name="Y">0.32101923164553864</Real>
- <Real Name="Z">0.18363175660878781</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-9.3235586515149063</Real>
- <Real Name="Y">-12.193064553417946</Real>
- <Real Name="Z">3.2071979869138385</Real>
- </Vector>
- <Vector>
- <Real Name="X">-9.6353711036371195</Real>
- <Real Name="Y">-9.2749112007415846</Real>
- <Real Name="Z">3.0222260742447977</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">0.65591768693309083</Real>
- <Real Name="Y">1.1787640808888671</Real>
- <Real Name="Z">0.98426843664014141</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">1.1633957102124022</Real>
- <Real Name="Y">0.99101924833483923</Real>
- <Real Name="Z">0.56363175184041625</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">-8.4935586682042068</Real>
- <Real Name="Y">-11.88306455103376</Real>
- <Real Name="Z">3.9371980059873248</Real>
- </Vector>
- <Vector>
- <Real Name="X">-8.9253711250947916</Real>
- <Real Name="Y">-9.2149112020826891</Real>
- <Real Name="Z">3.3722260682843332</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.27000001072883606</Real>
- <Real Name="Y">0.98000001907348633</Real>
- <Real Name="Z">0.82999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
<Sequence Name="Forces">
<Int Name="Length">1</Int>
<Vector>
- <Real Name="X">-19.925252342514202</Real>
- <Real Name="Y">-4.9850434490087228</Real>
- <Real Name="Z">-9.1473548430064433</Real>
+ <Real Name="X">-16.205517527929572</Real>
+ <Real Name="Y">-7.3188043172213684</Real>
+ <Real Name="Z">-7.9336359387100472</Real>
</Vector>
</Sequence>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-18.520591460490941</Real>
- <Real Name="Y">-6.0692526720334774</Real>
- <Real Name="Z">5.0076479125818185</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-3.9522519336553823</Real>
- <Real Name="Y">-3.3145212470342056</Real>
- <Real Name="Z">0.041856812732197594</Real>
- </Vector>
- <Vector>
- <Real Name="X">-0.077662725437609784</Real>
- <Real Name="Y">-0.70860432986230215</Real>
- <Real Name="Z">-0.70184026829559087</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-3.326749515646243</Real>
- <Real Name="Y">-9.9308372803045231</Real>
- <Real Name="Z">-0.45425921737202102</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-18.500591460937976</Real>
- <Real Name="Y">-5.1992526672651058</Real>
- <Real Name="Z">5.9576479006608896</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">-3.9322519341024171</Real>
- <Real Name="Y">-2.444521242265834</Real>
- <Real Name="Z">0.99185680081126859</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.58233730078843393</Real>
- <Real Name="Y">-0.038604313173001614</Real>
- <Real Name="Z">-0.32184027306396246</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0.019999999552965164</Real>
- <Real Name="Y">0.87000000476837158</Real>
- <Real Name="Z">0.94999998807907104</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.6600000262260437</Real>
- <Real Name="Y">0.67000001668930054</Real>
- <Real Name="Z">0.37999999523162842</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.44999998807907104</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.93999999761581421</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.54000002145767212</Real>
- <Real Name="Y">0.75999999046325684</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.82999998331069946</Real>
- <Real Name="Y">0.31000000238418579</Real>
- <Real Name="Z">0.73000001907348633</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.70999997854232788</Real>
- <Real Name="Y">0.059999998658895493</Real>
- <Real Name="Z">0.34999999403953552</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.31999999284744263</Real>
- <Real Name="Y">0.34999999403953552</Real>
- <Real Name="Z">0.61000001430511475</Real>
- </Vector>
- <Vector>
- <Real Name="X">-3.0567495049174069</Real>
- <Real Name="Y">-8.9508372612310367</Real>
- <Real Name="Z">0.37574076593867844</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.10999999940395355</Real>
- <Real Name="Y">0.30000001192092896</Real>
- <Real Name="Z">0.41999998688697815</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.94999998807907104</Real>
- <Real Name="Y">0.68999999761581421</Real>
- <Real Name="Z">0.57999998331069946</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.28999999165534973</Real>
- <Real Name="Y">0.10000000149011612</Real>
- <Real Name="Z">0.68000000715255737</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.93999999761581421</Real>
- <Real Name="Y">0.62000000476837158</Real>
- <Real Name="Z">0.50999999046325684</Real>
- </Vector>
- <Vector>
- <Real Name="X">0.4699999988079071</Real>
- <Real Name="Y">0.039999999105930328</Real>
- <Real Name="Z">0.4699999988079071</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-11.577102289706572</Real>
- <Real Name="Y">0.84910120894795005</Real>
- <Real Name="Z">1.8482439089193421</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">2</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">2.0340570782897585</Real>
- <Real Name="Y">1.4319189829320136</Real>
- <Real Name="Z">-0.59251856152304705</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">13</Int>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">-1.0210446166718394</Real>
- <Real Name="Y">-16.393563534893939</Real>
- <Real Name="Z">2.0765205102067403</Real>
- </Vector>
- <Vector>
- <Real Name="X">-3.3498355821816856</Real>
- <Real Name="Y">-0.97018032158412315</Real>
- <Real Name="Z">0.58368499271815877</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- <Vector>
- <Real Name="X">0</Real>
- <Real Name="Y">0</Real>
- <Real Name="Z">0</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <Sequence Name="Forces">
- <Int Name="Length">1</Int>
- <Vector>
- <Real Name="X">-11.557102290153606</Real>
- <Real Name="Y">1.7191012137163217</Real>
- <Real Name="Z">2.7982438969984131</Real>
- </Vector>
- </Sequence>
-</ReferenceData>
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements test environment class which performs hardware enumeration for unit tests.
+ *
+ * \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_ewald
+ */
+
+#include "gmxpre.h"
+
+#include "testhardwarecontext.h"
+
+#include <memory>
+
+#include "gromacs/ewald/pme.h"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
+#include "gromacs/gpu_utils/gpu_utils.h"
+#include "gromacs/hardware/detecthardware.h"
+#include "gromacs/hardware/hw_info.h"
+#include "gromacs/utility/basenetwork.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/loggerbuilder.h"
+#include "gromacs/utility/physicalnodecommunicator.h"
+
+namespace gmx
+{
+namespace test
+{
+
+TestHardwareContext::TestHardwareContext(CodePath codePath, const char* description) :
+ codePath_(codePath),
+ description_(description)
+{
+ GMX_RELEASE_ASSERT(codePath == CodePath::CPU,
+ "A GPU code path should provide DeviceInformation to the "
+ "TestHerdwareContext constructor.");
+ deviceContext_ = nullptr;
+ deviceStream_ = nullptr;
+}
+
+TestHardwareContext::TestHardwareContext(CodePath codePath,
+ const char* description,
+ const DeviceInformation& deviceInfo) :
+ codePath_(codePath),
+ description_(description)
+{
+ GMX_RELEASE_ASSERT(codePath == CodePath::GPU,
+ "TestHardwareContext tries to construct DeviceContext and PmeGpuProgram "
+ "in CPU build.");
+ deviceContext_ = new DeviceContext(deviceInfo);
+ deviceStream_ = new DeviceStream(*deviceContext_, DeviceStreamPriority::Normal, false);
+ program_ = buildPmeGpuProgram(*deviceContext_);
+}
+
+TestHardwareContext::~TestHardwareContext()
+{
+ delete (deviceStream_);
+ delete (deviceContext_);
+}
+
+const DeviceInformation* TestHardwareContext::deviceInfo() const
+{
+ return &deviceContext_->deviceInfo();
+}
+
+const DeviceContext* TestHardwareContext::deviceContext() const
+{
+ return deviceContext_;
+}
+//! Get the device stream
+const DeviceStream* TestHardwareContext::deviceStream() const
+{
+ return deviceStream_;
+}
+
+const char* codePathToString(CodePath codePath)
+{
+ switch (codePath)
+ {
+ case CodePath::CPU: return "CPU";
+ case CodePath::GPU: return "GPU";
+ default: GMX_THROW(NotImplementedError("This CodePath should support codePathToString"));
+ }
+}
+
+} // namespace test
+} // namespace gmx
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_EWALD_TEST_HARDWARE_CONTEXT_H
+#define GMX_EWALD_TEST_HARDWARE_CONTEXT_H
+
+/*! \internal \file
+ * \brief
+ * Describes test environment class which performs hardware enumeration for unit tests.
+ *
+ * \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ * \ingroup module_ewald
+ */
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "gromacs/ewald/pme_gpu_program.h"
+#include "gromacs/utility/gmxassert.h"
+
+class DeviceContext;
+struct DeviceInformation;
+class DeviceStream;
+
+namespace gmx
+{
+namespace test
+{
+//! Hardware code path being tested
+enum class CodePath
+{
+ CPU,
+ GPU
+};
+
+//! Return a string useful for human-readable messages describing a \c codePath.
+const char* codePathToString(CodePath codePath);
+
+/*! \internal \brief
+ * A structure to describe a hardware context that persists over the lifetime
+ * of the test binary - an abstraction over PmeGpuProgram with a human-readable string.
+ */
+struct TestHardwareContext
+{
+ //! Hardware path for the code being tested.
+ CodePath codePath_;
+ //! Readable description
+ std::string description_;
+ //! Device context
+ DeviceContext* deviceContext_ = nullptr;
+ //! Device stream
+ DeviceStream* deviceStream_ = nullptr;
+ //! Persistent compiled GPU kernels for PME.
+ PmeGpuProgramStorage program_;
+
+public:
+ //! Retuns the code path for this context.
+ CodePath codePath() const { return codePath_; }
+ //! Returns a human-readable context description line
+ std::string description() const { return description_; }
+ //! Returns the device info pointer
+ const DeviceInformation* deviceInfo() const;
+ //! Get the device context
+ const DeviceContext* deviceContext() const;
+ //! Get the device stream
+ const DeviceStream* deviceStream() const;
+ //! Returns the persistent PME GPU kernels
+ const PmeGpuProgram* pmeGpuProgram() const { return program_.get(); }
+ //! Constructs the context for CPU builds
+ TestHardwareContext(CodePath codePath, const char* description);
+ //! Constructs the context for GPU builds
+ TestHardwareContext(CodePath codePath, const char* description, const DeviceInformation& deviceInfo);
+ //! Destructor
+ ~TestHardwareContext();
+};
+
+} // namespace test
+} // namespace gmx
+#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
namespace test
{
-TestHardwareContext::~TestHardwareContext() = default;
-
-const char* codePathToString(CodePath codePath)
-{
- switch (codePath)
- {
- case CodePath::CPU: return "CPU";
- case CodePath::GPU: return "GPU";
- default: GMX_THROW(NotImplementedError("This CodePath should support codePathToString"));
- }
-}
-
/* Implements the "construct on first use" idiom to avoid any static
* initialization order fiasco.
*
void PmeTestEnvironment::SetUp()
{
- hardwareContexts_.emplace_back(std::make_unique<TestHardwareContext>(CodePath::CPU, "", nullptr));
+ hardwareContexts_.emplace_back(std::make_unique<TestHardwareContext>(CodePath::CPU, "(CPU) "));
hardwareInfo_ = hardwareInit();
if (!pme_gpu_supports_build(nullptr) || !pme_gpu_supports_hardware(*hardwareInfo_, nullptr))
// Constructing contexts for all compatible GPUs - will be empty on non-GPU builds
for (int gpuIndex : getCompatibleGpus(hardwareInfo_->gpu_info))
{
- const gmx_device_info_t* deviceInfo = getDeviceInfo(hardwareInfo_->gpu_info, gpuIndex);
+ const DeviceInformation* deviceInfo = getDeviceInfo(hardwareInfo_->gpu_info, gpuIndex);
init_gpu(deviceInfo);
char stmp[200] = {};
get_gpu_device_info_string(stmp, hardwareInfo_->gpu_info, gpuIndex);
std::string description = "(GPU " + std::string(stmp) + ") ";
hardwareContexts_.emplace_back(std::make_unique<TestHardwareContext>(
- CodePath::GPU, description.c_str(), deviceInfo));
+ CodePath::GPU, description.c_str(), *deviceInfo));
}
}
+void PmeTestEnvironment::TearDown()
+{
+ hardwareContexts_.clear();
+}
+
} // namespace test
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/ewald/pme_gpu_program.h"
#include "gromacs/hardware/gpu_hw_info.h"
+#include "gromacs/utility/gmxassert.h"
+
+#include "testhardwarecontext.h"
struct gmx_hw_info_t;
{
namespace test
{
-//! Hardware code path being tested
-enum class CodePath
-{
- CPU,
- GPU
-};
-
-//! Return a string useful for human-readable messages describing a \c codePath.
-const char* codePathToString(CodePath codePath);
-
-/*! \internal \brief
- * A structure to describe a hardware context that persists over the lifetime
- * of the test binary - an abstraction over PmeGpuProgram with a human-readable string.
- */
-struct TestHardwareContext
-{
- //! Hardware path for the code being tested.
- CodePath codePath_;
- //! Readable description
- std::string description_;
- //! Device information pointer
- const gmx_device_info_t* deviceInfo_;
- //! Persistent compiled GPU kernels for PME.
- PmeGpuProgramStorage program_;
-
-public:
- //! Retuns the code path for this context.
- CodePath getCodePath() const { return codePath_; }
- //! Returns a human-readable context description line
- std::string getDescription() const { return description_; }
- //! Returns the device info pointer
- const gmx_device_info_t* getDeviceInfo() const { return deviceInfo_; }
- //! Returns the persistent PME GPU kernels
- PmeGpuProgramHandle getPmeGpuProgram() const { return program_.get(); }
- //! Constructs the context
- TestHardwareContext(CodePath codePath, const char* description, const gmx_device_info_t* deviceInfo) :
- codePath_(codePath),
- description_(description),
- deviceInfo_(deviceInfo),
- program_(buildPmeGpuProgram(deviceInfo_))
- {
- }
- ~TestHardwareContext();
-};
//! A container of handles to hardware contexts
typedef std::vector<std::unique_ptr<TestHardwareContext>> TestHardwareContexts;
public:
//! This is called by GTest framework once to query the hardware
void SetUp() override;
+ //! This is called by GTest framework once release the hardware
+ void TearDown() override;
//! Get available hardware contexts.
const TestHardwareContexts& getHardwareContexts() const { return hardwareContexts_; }
//! Get available hardware information.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2003 Erik Lindahl, David van der Spoel, University of Groningen.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2003 David van der Spoel, Erik Lindahl, University of Groningen.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2003 David van der Spoel, Erik Lindahl, University of Groningen.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(FFTUnitTests fft-test
- fft.cpp)
+ CPP_SOURCE_FILES
+ fft.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
break;
/* The RNG entries are no longer written,
* the next 4 lines are only for reading old files.
+ * It's OK that three case statements fall through.
*/
case estLD_RNG_NOTSUPPORTED:
- ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
- break;
case estLD_RNGI_NOTSUPPORTED:
- ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
- break;
case estMC_RNG_NOTSUPPORTED:
- ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
- break;
case estMC_RNGI_NOTSUPPORTED:
ret = do_cpte_ints(xd, part, i, sflags, 0, nullptr, list);
break;
gmx::MdModulesCheckpointReadingDataOnMaster mdModuleCheckpointReadingDataOnMaster = {
mdModuleCheckpointParameterTree, fileVersion
};
- mdModulesNotifier.notifier_.notify(mdModuleCheckpointReadingDataOnMaster);
+ mdModulesNotifier.checkpointingNotifications_.notify(mdModuleCheckpointReadingDataOnMaster);
}
}
gmx::KeyValueTreeBuilder builder;
gmx::MdModulesWriteCheckpointData mdModulesWriteCheckpoint = { builder.rootObject(),
headerContents.file_version };
- mdModulesNotifier.notifier_.notify(mdModulesWriteCheckpoint);
+ mdModulesNotifier.checkpointingNotifications_.notify(mdModulesWriteCheckpoint);
auto tree = builder.build();
gmx::FileIOXdrSerializer serializer(fp);
gmx::serializeKeyValueTree(tree, &serializer);
}
if (PAR(cr))
{
- gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr);
- gmx::MdModulesCheckpointReadingBroadcast broadcastCheckPointData = { *cr, headerContents.file_version };
- mdModulesNotifier.notifier_.notify(broadcastCheckPointData);
+ gmx_bcast(sizeof(headerContents.step), &headerContents.step, cr->mpi_comm_mygroup);
+ gmx::MdModulesCheckpointReadingBroadcast broadcastCheckPointData = {
+ cr->mpi_comm_mygroup, PAR(cr), headerContents.file_version
+ };
+ mdModulesNotifier.checkpointingNotifications_.notify(broadcastCheckPointData);
}
ir->bContinuation = TRUE;
if (ir->nsteps >= 0)
*/
struct MdModulesCheckpointReadingBroadcast
{
- //! The communication record
- const t_commrec& cr_;
+ //! The communicator
+ MPI_Comm communicator_;
+ //! Whether the run is executed in parallel
+ bool isParallelRun_;
//! The version of the read file version
int checkpointFileVersion_;
};
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const t_atoms* atoms,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box,
int nindex,
int index[])
case efENT:
case efPQR:
out = gmx_fio_fopen(outfile, "w");
- write_pdbfile_indexed(out, title, atoms, x, ePBC, box, ' ', -1, nindex, index, nullptr,
- ftp == efPQR);
+ write_pdbfile_indexed(out, title, atoms, x, pbcType, box, ' ', -1, nindex, index,
+ nullptr, ftp == efPQR);
gmx_fio_fclose(out);
break;
case efESP:
const t_atoms* atoms,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box)
{
FILE* out;
case efBRK:
case efENT:
out = gmx_fio_fopen(outfile, "w");
- write_pdbfile(out, title, atoms, x, ePBC, box, ' ', -1, nullptr);
+ write_pdbfile(out, title, atoms, x, pbcType, box, ' ', -1, nullptr);
gmx_fio_fclose(out);
break;
case efESP:
const gmx_mtop_t* mtop,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box)
{
int ftp;
*/
atoms = gmx_mtop_global_atoms(mtop);
- write_sto_conf(outfile, title, &atoms, x, v, ePBC, box);
+ write_sto_conf(outfile, title, &atoms, x, v, pbcType, box);
done_atom(&atoms);
break;
t_atoms* atoms,
rvec x[],
rvec* v,
- int* ePBC,
+ PbcType* pbcType,
matrix box)
{
FILE* in;
gmx_mem("Uninitialized array atom");
}
- if (ePBC)
+ if (pbcType)
{
- *ePBC = -1;
+ *pbcType = PbcType::Unset;
}
ftp = fn2ftp(infile);
break;
case efPDB:
case efBRK:
- case efENT: gmx_pdb_read_conf(infile, symtab, name, atoms, x, ePBC, box); break;
+ case efENT: gmx_pdb_read_conf(infile, symtab, name, atoms, x, pbcType, box); break;
case efESP: gmx_espresso_read_conf(infile, symtab, name, atoms, x, v, box); break;
default: gmx_incons("Not supported in read_stx_conf");
}
t_symtab* symtab,
char** name,
t_atoms* atoms,
- int* ePBC,
+ PbcType* pbcType,
rvec** x,
rvec** v,
matrix box)
{
bool haveTopology;
gmx_mtop_t mtop;
- readConfAndTopology(infile, &haveTopology, &mtop, ePBC, x, v, box);
+ readConfAndTopology(infile, &haveTopology, &mtop, pbcType, x, v, box);
*symtab = mtop.symtab;
*name = gmx_strdup(*mtop.name);
*atoms = gmx_mtop_global_atoms(&mtop);
{
snew(*v, natoms);
}
- read_stx_conf(infile, symtab, name, atoms, *x, (v == nullptr) ? nullptr : *v, ePBC, box);
+ read_stx_conf(infile, symtab, name, atoms, *x, (v == nullptr) ? nullptr : *v, pbcType, box);
if (xIsNull)
{
sfree(*x);
}
}
-void readConfAndTopology(const char* infile, bool* haveTopology, gmx_mtop_t* mtop, int* ePBC, rvec** x, rvec** v, matrix box)
+void readConfAndTopology(const char* infile,
+ bool* haveTopology,
+ gmx_mtop_t* mtop,
+ PbcType* pbcType,
+ rvec** x,
+ rvec** v,
+ matrix box)
{
GMX_RELEASE_ASSERT(mtop != nullptr, "readConfAndTopology requires mtop!=NULL");
- if (ePBC != nullptr)
+ if (pbcType != nullptr)
{
- *ePBC = -1;
+ *pbcType = PbcType::Unset;
}
*haveTopology = fn2bTPX(infile);
{
snew(*v, header.natoms);
}
- int natoms;
- int ePBC_tmp = read_tpx(infile, nullptr, box, &natoms, (x == nullptr) ? nullptr : *x,
- (v == nullptr) ? nullptr : *v, mtop);
- if (ePBC != nullptr)
+ int natoms;
+ PbcType pbcType_tmp = read_tpx(infile, nullptr, box, &natoms, (x == nullptr) ? nullptr : *x,
+ (v == nullptr) ? nullptr : *v, mtop);
+ if (pbcType != nullptr)
{
- *ePBC = ePBC_tmp;
+ *pbcType = pbcType_tmp;
}
}
else
open_symtab(&symtab);
- readConfAndAtoms(infile, &symtab, &name, &atoms, ePBC, x, v, box);
+ readConfAndAtoms(infile, &symtab, &name, &atoms, pbcType, x, v, box);
convertAtomsToMtop(&symtab, put_symtab(&symtab, name), &atoms, mtop);
sfree(name);
}
}
-gmx_bool read_tps_conf(const char* infile, t_topology* top, int* ePBC, rvec** x, rvec** v, matrix box, gmx_bool requireMasses)
+gmx_bool read_tps_conf(const char* infile, t_topology* top, PbcType* pbcType, rvec** x, rvec** v, matrix box, gmx_bool requireMasses)
{
bool haveTopology;
gmx_mtop_t mtop;
- readConfAndTopology(infile, &haveTopology, &mtop, ePBC, x, v, box);
+ readConfAndTopology(infile, &haveTopology, &mtop, pbcType, x, v, box);
*top = gmx_mtop_t_to_t_topology(&mtop, true);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_atoms;
struct t_symtab;
struct t_topology;
+enum class PbcType : int;
void write_sto_conf_indexed(const char* outfile,
const char* title,
const t_atoms* atoms,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box,
int nindex,
int index[]);
const t_atoms* atoms,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box);
/* write atoms, x, v (if .gro and not NULL) and box (if not NULL)
* to an STO (.gro or .pdb) file */
const gmx_mtop_t* mtop,
const rvec x[],
const rvec* v,
- int ePBC,
+ PbcType pbcType,
const matrix box);
/* As write_sto_conf, but uses a gmx_mtop_t struct */
* \param[in] infile Input file name
* \param[out] haveTopology true when a topology was read and stored in mtop
* \param[out] mtop The topology, either complete or only atom data
- * \param[out] ePBC Enum reporting the type of PBC
+ * \param[out] pbcType Enum reporting the type of PBC
* \param[in,out] x Coordinates will be stored when *x!=NULL
* \param[in,out] v Velocities will be stored when *v!=NULL
* \param[out] box Box dimensions
void readConfAndTopology(const char* infile,
bool* haveTopology,
gmx_mtop_t* mtop,
- int* ePBC,
+ PbcType* pbcType,
rvec** x,
rvec** v,
matrix box);
* \param[out] symtab The symbol table
* \param[out] name The title of the molecule, e.g. from pdb TITLE record
* \param[out] atoms The global t_atoms struct
- * \param[out] ePBC Enum reporting the type of PBC
+ * \param[out] pbcType Enum reporting the type of PBC
* \param[in,out] x Coordinates will be stored when *x!=NULL
* \param[in,out] v Velocities will be stored when *v!=NULL
* \param[out] box Box dimensions
t_symtab* symtab,
char** name,
t_atoms* atoms,
- int* ePBC,
+ PbcType* pbcType,
rvec** x,
rvec** v,
matrix box);
*
* \param[in] infile Input file name
* \param[out] top The topology, either complete or only atom data. Caller is
- * responsible for calling done_top(). \param[out] ePBC Enum reporting the type of PBC
+ * responsible for calling done_top().
+ * \param[out] pbcType Enum reporting the type of PBC
* \param[in,out] x Coordinates will be stored when *x!=NULL
* \param[in,out] v Velocities will be stored when *v!=NULL
* \param[out] box Box dimensions
*/
gmx_bool read_tps_conf(const char* infile,
struct t_topology* top,
- int* ePBC,
+ PbcType* pbcType,
rvec** x,
rvec** v,
matrix box,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2005, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2005, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
| with some routines to assist in this task (those are marked
| static and cannot be called from user programs)
*/
-#define MAXABS (INT_MAX - 2)
+
+// Integers above 2^24 do not have unique representations in
+// 32-bit floats ie with 24 bits of precision. We use maxAbsoluteInt
+// to check that float values can be transformed into an in-range
+// 32-bit integer. There is no need to ensure we are within the range
+// of ints with exact floating-point representations. However, we should
+// reject all floats above that which converts to an in-range 32-bit integer.
+const float maxAbsoluteInt = nextafterf(float(INT_MAX), 0.F); // NOLINT(cert-err58-cpp)
#ifndef SQR
# define SQR(x) ((x) * (x))
{
lf = *lfp * *precision - 0.5;
}
- if (std::fabs(lf) > MAXABS)
+ if (std::fabs(lf) > maxAbsoluteInt)
{
/* scaling would cause overflow */
errval = 0;
{
lf = *lfp * *precision - 0.5;
}
- if (std::fabs(lf) > MAXABS)
+ if (std::fabs(lf) > maxAbsoluteInt)
{
/* scaling would cause overflow */
errval = 0;
{
lf = *lfp * *precision - 0.5;
}
- if (std::abs(lf) > MAXABS)
+ if (std::abs(lf) > maxAbsoluteInt)
{
/* scaling would cause overflow */
errval = 0;
return 0;
}
- if (static_cast<float>(maxint[0]) - static_cast<float>(minint[0]) >= MAXABS
- || static_cast<float>(maxint[1]) - static_cast<float>(minint[1]) >= MAXABS
- || static_cast<float>(maxint[2]) - static_cast<float>(minint[2]) >= MAXABS)
+ if (static_cast<float>(maxint[0]) - static_cast<float>(minint[0]) >= maxAbsoluteInt
+ || static_cast<float>(maxint[1]) - static_cast<float>(minint[1]) >= maxAbsoluteInt
+ || static_cast<float>(maxint[2]) - static_cast<float>(minint[2]) >= maxAbsoluteInt)
{
/* turning value in unsigned by subtracting minint
* would cause overflow
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2014,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2014,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "oenv.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/smalloc.h"
{
explicit gmx_output_env_t(const gmx::IProgramContext& context) :
programContext(context),
- time_unit(time_ps),
+ timeUnit(gmx::TimeUnit::Picoseconds),
view(FALSE),
- xvg_format(exvgNONE),
+ xvgFormat(XvgFormat::None),
verbosity(0),
trajectory_io_verbosity(0)
{
const gmx::IProgramContext& programContext;
- /* the time unit, enum defined in oenv.h */
- time_unit_t time_unit;
+ /* the time unit, enum defined in timeunitmanager.h */
+ gmx::TimeUnit timeUnit;
/* view of file requested */
gmx_bool view;
/* xvg output format, enum defined in oenv.h */
- xvg_format_t xvg_format;
+ XvgFormat xvgFormat;
/* The level of verbosity for this program */
int verbosity;
/* The level of verbosity during trajectory I/O. Default=1, quiet=0. */
******************************************************************/
/* read only time names */
-/* These must correspond to the time units type time_unit_t in oenv.h */
-static const real timefactors[] = { real(0), real(1e3), real(1), real(1e-3),
- real(1e-6), real(1e-9), real(1e-12), real(0) };
-static const real timeinvfactors[] = { real(0), real(1e-3), real(1), real(1e3),
- real(1e6), real(1e9), real(1e12), real(0) };
-static const char* time_units_str[] = { nullptr, "fs", "ps", "ns", "us", "ms", "s" };
-static const char* time_units_xvgr[] = { nullptr, "fs", "ps", "ns", "\\mus", "ms", "s", nullptr };
+static const gmx::EnumerationArray<gmx::TimeUnit, real> c_picosecondsInTimeUnit = {
+ { real(1e3), real(1), real(1e-3), real(1e-6), real(1e-9), real(1e-12) }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, real> c_timeUnitsInPicoseconds = {
+ { real(1e-3), real(1), real(1e3), real(1e6), real(1e9), real(1e12) }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, const char*> c_timeUnitNames = {
+ { "fs", "ps", "ns", "us", "ms", "s" }
+};
+static const gmx::EnumerationArray<gmx::TimeUnit, const char*> c_timeUnitNamesForXvgr = {
+ { "fs", "ps", "ns", "\\mus", "ms", "s" }
+};
/***** OUTPUT_ENV MEMBER FUNCTIONS ******/
void output_env_init(gmx_output_env_t** oenvp,
const gmx::IProgramContext& context,
- time_unit_t tmu,
+ gmx::TimeUnit tmu,
gmx_bool view,
- xvg_format_t xvg_format,
+ XvgFormat xvgFormat,
int verbosity)
{
try
{
gmx_output_env_t* oenv = new gmx_output_env_t(context);
*oenvp = oenv;
- oenv->time_unit = tmu;
+ oenv->timeUnit = tmu;
oenv->view = view;
- oenv->xvg_format = xvg_format;
+ oenv->xvgFormat = xvgFormat;
oenv->verbosity = verbosity;
const char* env = getenv("GMX_TRAJECTORY_IO_VERBOSITY");
oenv->trajectory_io_verbosity = (env != nullptr ? strtol(env, nullptr, 10) : 1);
std::string output_env_get_time_unit(const gmx_output_env_t* oenv)
{
- return time_units_str[oenv->time_unit];
+ return c_timeUnitNames[oenv->timeUnit];
}
std::string output_env_get_time_label(const gmx_output_env_t* oenv)
{
- return gmx::formatString(
- "Time (%s)", time_units_str[oenv->time_unit] ? time_units_str[oenv->time_unit] : "ps");
+ return gmx::formatString("Time (%s)", c_timeUnitNames[oenv->timeUnit]);
}
std::string output_env_get_xvgr_tlabel(const gmx_output_env_t* oenv)
{
- return gmx::formatString(
- "Time (%s)", time_units_xvgr[oenv->time_unit] ? time_units_xvgr[oenv->time_unit] : "ps");
+ return gmx::formatString("Time (%s)", c_timeUnitNamesForXvgr[oenv->timeUnit]);
}
real output_env_get_time_factor(const gmx_output_env_t* oenv)
{
- return timefactors[oenv->time_unit];
+ return c_picosecondsInTimeUnit[oenv->timeUnit];
}
real output_env_get_time_invfactor(const gmx_output_env_t* oenv)
{
- return timeinvfactors[oenv->time_unit];
+ return c_timeUnitsInPicoseconds[oenv->timeUnit];
}
real output_env_conv_time(const gmx_output_env_t* oenv, real time)
{
- return time * timefactors[oenv->time_unit];
+ return time * c_picosecondsInTimeUnit[oenv->timeUnit];
}
void output_env_conv_times(const gmx_output_env_t* oenv, int n, real* time)
{
int i;
- double fact = timefactors[oenv->time_unit];
+ double fact = c_picosecondsInTimeUnit[oenv->timeUnit];
if (fact != 1.)
{
return oenv->view;
}
-xvg_format_t output_env_get_xvg_format(const gmx_output_env_t* oenv)
+XvgFormat output_env_get_xvg_format(const gmx_output_env_t* oenv)
{
- return oenv->xvg_format;
+ return oenv->xvgFormat;
}
const char* output_env_get_program_display_name(const gmx_output_env_t* oenv)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
There are still legacy functions for the program name, and the command
line, but the output_env versions are now preferred.*/
-typedef enum
+namespace gmx
{
- timeNULL,
- time_fs,
- time_ps,
- time_ns,
- time_us,
- time_ms,
- time_s
-} time_unit_t;
-/* the time units. For the time being, ps means no conversion. */
-
-typedef enum
+
+/*! \brief
+ * Time values for TimeUnitManager and legacy oenv module.
+ *
+ * \inpublicapi
+ */
+enum class TimeUnit : int
{
- exvgNULL,
- exvgXMGRACE,
- exvgXMGR,
- exvgNONE
-} xvg_format_t;
-/* the xvg output formattings */
+ Femtoseconds,
+ Picoseconds,
+ Nanoseconds,
+ Microseconds,
+ Milliseconds,
+ Seconds,
+ Count,
+ Default = Picoseconds
+};
+
+} // namespace gmx
+//! The xvg output format
+enum class XvgFormat : int
+{
+ // Select,
+ Xmgrace,
+ Xmgr,
+ None,
+ Count
+};
void output_env_init_default(gmx_output_env_t** oenvp);
/* initialize an output_env structure, with reasonable default settings.
gmx_bool output_env_get_view(const gmx_output_env_t* oenv);
/* Return TRUE when user requested viewing of the file */
-xvg_format_t output_env_get_xvg_format(const gmx_output_env_t* oenv);
+XvgFormat output_env_get_xvg_format(const gmx_output_env_t* oenv);
/* Returns enum (see above) for xvg output formatting */
/*! \brief
void output_env_init(gmx_output_env_t** oenvp,
const gmx::IProgramContext& context,
- time_unit_t tmu,
+ gmx::TimeUnit tmu,
gmx_bool view,
- xvg_format_t xvg_format,
+ XvgFormat xvgFormat,
int verbosity);
/* initialize an output_env structure, setting the command line,
the default time value a gmx_boolean view that is set to TRUE when the
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
-void gmx_write_pdb_box(FILE* out, int ePBC, const matrix box)
+void gmx_write_pdb_box(FILE* out, PbcType pbcType, const matrix box)
{
real alpha, beta, gamma;
- if (ePBC == -1)
+ if (pbcType == PbcType::Unset)
{
- ePBC = guess_ePBC(box);
+ pbcType = guessPbcType(box);
}
- if (ePBC == epbcNONE)
+ if (pbcType == PbcType::No)
{
return;
}
gamma = 90;
}
fprintf(out, "REMARK THIS IS A SIMULATION BOX\n");
- if (ePBC != epbcSCREW)
+ if (pbcType != PbcType::Screw)
{
fprintf(out, "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s%4d\n", 10 * norm(box[XX]),
10 * norm(box[YY]), 10 * norm(box[ZZ]), alpha, beta, gamma, "P 1", 1);
}
}
-static void read_cryst1(char* line, int* ePBC, matrix box)
+static void read_cryst1(char* line, PbcType* pbcType, matrix box)
{
#define SG_SIZE 11
- char sa[12], sb[12], sc[12], sg[SG_SIZE + 1], ident;
- double fa, fb, fc, alpha, beta, gamma, cosa, cosb, cosg, sing;
- int syma, symb, symc;
- int ePBC_file;
+ char sa[12], sb[12], sc[12], sg[SG_SIZE + 1], ident;
+ double fa, fb, fc, alpha, beta, gamma, cosa, cosb, cosg, sing;
+ int syma, symb, symc;
+ PbcType pbcTypeFile;
sscanf(line, "%*s%s%s%s%lf%lf%lf", sa, sb, sc, &alpha, &beta, &gamma);
- ePBC_file = -1;
+ pbcTypeFile = PbcType::Unset;
if (strlen(line) >= 55)
{
strncpy(sg, line + 55, SG_SIZE);
sscanf(sg, "%c %d %d %d", &ident, &syma, &symb, &symc);
if (ident == 'P' && syma == 1 && symb <= 1 && symc <= 1)
{
- fc = strtod(sc, nullptr) * 0.1;
- ePBC_file = (fc > 0 ? epbcXYZ : epbcXY);
+ fc = strtod(sc, nullptr) * 0.1;
+ pbcTypeFile = (fc > 0 ? PbcType::Xyz : PbcType::XY);
}
if (ident == 'P' && syma == 21 && symb == 1 && symc == 1)
{
- ePBC_file = epbcSCREW;
+ pbcTypeFile = PbcType::Screw;
}
}
- if (ePBC)
+ if (pbcType)
{
- *ePBC = ePBC_file;
+ *pbcType = pbcTypeFile;
}
if (box)
fa = strtod(sa, nullptr) * 0.1;
fb = strtod(sb, nullptr) * 0.1;
fc = strtod(sc, nullptr) * 0.1;
- if (ePBC_file == epbcSCREW)
+ if (pbcTypeFile == PbcType::Screw)
{
fa *= 0.5;
}
const char* title,
const t_atoms* atoms,
const rvec x[],
- int ePBC,
+ PbcType pbcType,
const matrix box,
char chainid,
int model_nr,
fprintf(out, "TITLE %s\n", (title && title[0]) ? title : gmx::bromacs().c_str());
if (box && ((norm2(box[XX]) != 0.0F) || (norm2(box[YY]) != 0.0F) || (norm2(box[ZZ]) != 0.0F)))
{
- gmx_write_pdb_box(out, ePBC, box);
+ gmx_write_pdb_box(out, pbcType, box);
}
if (atoms->havePdbInfo)
{
const char* title,
const t_atoms* atoms,
const rvec x[],
- int ePBC,
+ PbcType pbcType,
const matrix box,
char chainid,
int model_nr,
{
index[i] = i;
}
- write_pdbfile_indexed(out, title, atoms, x, ePBC, box, chainid, model_nr, atoms->nr, index,
+ write_pdbfile_indexed(out, title, atoms, x, pbcType, box, chainid, model_nr, atoms->nr, index,
conect, false);
sfree(index);
}
std::strcpy(buf, nm);
trim(buf);
- if (buf[0] == 'H')
- {
- return TRUE;
- }
- else if ((std::isdigit(buf[0])) && (buf[1] == 'H'))
- {
- return TRUE;
- }
- return FALSE;
+ return ((buf[0] == 'H') || ((std::isdigit(buf[0]) != 0) && (buf[1] == 'H')));
}
gmx_bool is_dummymass(const char* nm)
t_atoms* atoms,
t_symtab* symtab,
rvec x[],
- int* ePBC,
+ PbcType* pbcType,
matrix box,
gmx_bool bChange,
gmx_conect conect)
int natom, chainnum;
gmx_bool bStop = FALSE;
- if (ePBC)
+ if (pbcType)
{
/* Only assume pbc when there is a CRYST1 entry */
- *ePBC = epbcNONE;
+ *pbcType = PbcType::No;
}
if (box != nullptr)
{
}
break;
- case epdbCRYST1: read_cryst1(line, ePBC, box); break;
+ case epdbCRYST1: read_cryst1(line, pbcType, box); break;
case epdbTITLE:
case epdbHEADER:
}
}
-void gmx_pdb_read_conf(const char* infile, t_symtab* symtab, char** name, t_atoms* atoms, rvec x[], int* ePBC, matrix box)
+void gmx_pdb_read_conf(const char* infile, t_symtab* symtab, char** name, t_atoms* atoms, rvec x[], PbcType* pbcType, matrix box)
{
FILE* in = gmx_fio_fopen(infile, "r");
char title[STRLEN];
- read_pdbfile(in, title, nullptr, atoms, symtab, x, ePBC, box, TRUE, nullptr);
+ read_pdbfile(in, title, nullptr, atoms, symtab, x, pbcType, box, TRUE, nullptr);
if (name != nullptr)
{
*name = gmx_strdup(title);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_atoms;
struct t_symtab;
struct t_topology;
+enum class PbcType : int;
typedef struct gmx_conect_t* gmx_conect;
/* set read_pdbatoms to read upto 'TER' or 'ENDMDL' (default, bSet=FALSE).
This function is fundamentally broken as far as thread-safety is concerned.*/
-void gmx_write_pdb_box(FILE* out, int ePBC, const matrix box);
+void gmx_write_pdb_box(FILE* out, PbcType pbcType, const matrix box);
/* write the box in the CRYST1 record,
- * with ePBC=-1 the pbc is guessed from the box
+ * with pbcType=PbcType::Unset the pbc is guessed from the box
* This function is fundamentally broken as far as thread-safety is concerned.
*/
const char* title,
const t_atoms* atoms,
const rvec x[],
- int ePBC,
+ PbcType pbcType,
const matrix box,
char chain,
int model_nr,
const char* title,
const t_atoms* atoms,
const rvec x[],
- int ePBC,
+ PbcType pbcType,
const matrix box,
char chain,
int model_nr,
struct t_atoms* atoms,
struct t_symtab* symtab,
rvec x[],
- int* ePBC,
+ PbcType* pbcType,
matrix box,
gmx_bool bChange,
gmx_conect conect);
/* Function returns number of atoms found.
- * ePBC and gmx_conect structure may be NULL.
+ * pbcType and gmx_conect structure may be NULL.
*/
-void gmx_pdb_read_conf(const char* infile, t_symtab* symtab, char** name, t_atoms* atoms, rvec x[], int* ePBC, matrix box);
+void gmx_pdb_read_conf(const char* infile,
+ t_symtab* symtab,
+ char** name,
+ t_atoms* atoms,
+ rvec x[],
+ PbcType* pbcType,
+ matrix box);
/* Read a pdb file and extract ATOM and HETATM fields.
* Read a box from the CRYST1 line, return 0 box when no CRYST1 is found.
- * ePBC may be NULL.
+ * pbcType may be NULL.
*
* If name is not nullptr, gmx_strdup the title string into it. */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-set(test_sources
- confio.cpp
- filemd5.cpp
- mrcserializer.cpp
- mrcdensitymap.cpp
- mrcdensitymapheader.cpp
- readinp.cpp
- fileioxdrserializer.cpp
- )
if (GMX_USE_TNG)
- list(APPEND test_sources tngio.cpp)
+ set(tng_sources tngio.cpp)
endif()
-gmx_add_unit_test(FileIOTests fileio-test ${test_sources})
+gmx_add_unit_test(FileIOTests fileio-test
+ CPP_SOURCE_FILES
+ confio.cpp
+ filemd5.cpp
+ mrcserializer.cpp
+ mrcdensitymap.cpp
+ mrcdensitymapheader.cpp
+ readinp.cpp
+ fileioxdrserializer.cpp
+ ${tng_sources}
+ xvgio.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/fileio/filetypes.h"
#include "gromacs/math/vec.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/atoms.h"
#include "gromacs/topology/symtab.h"
#include "gromacs/topology/topology.h"
void writeReferenceFile()
{
write_sto_conf(referenceFilename_.c_str(), *refTop_->name, &refTop_->atoms,
- as_rvec_array(refX_.data()), nullptr, -1, refBox_);
+ as_rvec_array(refX_.data()), nullptr, PbcType::Unset, refBox_);
}
void readReferenceFileTps()
{
snew(testTop_, 1);
- int ePBC = -2;
- read_tps_conf(referenceFilename_.c_str(), testTop_, &ePBC, &testX_, nullptr, testBox_, FALSE);
+ PbcType pbcType = PbcType::Unset;
+ read_tps_conf(referenceFilename_.c_str(), testTop_, &pbcType, &testX_, nullptr, testBox_, FALSE);
}
void testTopologies()
void writeTestFileAndTest()
{
write_sto_conf(testFilename_.c_str(), *testTop_->name, &testTop_->atoms, testX_, nullptr,
- -1, testBox_);
+ PbcType::Unset, testBox_);
testFilesEqual(referenceFilename_, testFilename_);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements tests for xvg file operations
+ *
+ * \author Joe Jordan <ejjordan@kth.se>
+ */
+#include "gmxpre.h"
+
+#include <numeric>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/fileio/xvgr.h"
+#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/textwriter.h"
+
+#include "testutils/testfilemanager.h"
+#include "testutils/testoptions.h"
+
+namespace gmx
+{
+namespace test
+{
+
+class XvgioTest : public ::testing::Test
+{
+public:
+ XvgioTest() { referenceFilename_ = fileManager_.getTemporaryFilePath("ref.xvg"); }
+
+ const std::string& referenceFilename() const { return referenceFilename_; }
+
+ const std::string& referenceContents() const { return referenceContents_; }
+
+ void useStringAsXvgFile(const std::string& xvgString) { referenceContents_ = xvgString; }
+
+ void writeXvgFile()
+ {
+ gmx::TextWriter::writeFileFromString(referenceFilename(), referenceContents());
+ }
+
+ static void compareValues(basic_mdspan<const double, dynamicExtents2D> ref,
+ basic_mdspan<const double, dynamicExtents2D> test)
+ {
+ // The xvg reading routines use a column-major layout, while we would
+ // like to enforce row major behaviour everywhere else. This requires
+ // this test to swap the orders between reference data and test data.
+ // Hence, we compare extent(0) with extent(1) and [i][j] with [j][i].
+ EXPECT_EQ(ref.extent(0), test.extent(1));
+ EXPECT_EQ(ref.extent(1), test.extent(0));
+
+ for (std::ptrdiff_t i = 0; i < ref.extent(0); i++)
+ {
+ for (std::ptrdiff_t j = 0; j < ref.extent(1); j++)
+ {
+ EXPECT_DOUBLE_EQ(ref[i][j], test[j][i]);
+ }
+ }
+ }
+
+private:
+ gmx::test::TestFileManager fileManager_;
+ std::string referenceFilename_;
+ std::string referenceContents_;
+};
+
+TEST_F(XvgioTest, readXvgIntWorks)
+{
+ useStringAsXvgFile(
+ "1 2 3\n"
+ "4 5 6\n");
+ writeXvgFile();
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgTestData = readXvgData(referenceFilename());
+
+ const int numRows = 2;
+ const int numColumns = 3;
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgRefData(numRows, numColumns);
+ std::iota(begin(xvgRefData), end(xvgRefData), 1);
+
+ compareValues(xvgRefData.asConstView(), xvgTestData.asConstView());
+}
+
+TEST_F(XvgioTest, readXvgRealWorks)
+{
+ useStringAsXvgFile(
+ "1.1 2.2\n"
+ "3.3 4.4\n"
+ "5.5 6.6\n");
+ writeXvgFile();
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgTestData = readXvgData(referenceFilename());
+
+ const int numRows = 3;
+ const int numColumns = 2;
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgRefData(numRows, numColumns);
+ std::generate(begin(xvgRefData), end(xvgRefData), [n = 0.0]() mutable {
+ n += 1.1;
+ return n;
+ });
+ compareValues(xvgRefData.asConstView(), xvgTestData.asConstView());
+}
+
+TEST_F(XvgioTest, readXvgIgnoreCommentLineWorks)
+{
+ useStringAsXvgFile(
+ "1 2 3\n"
+ "#comment\n"
+ "4 5 6\n");
+ writeXvgFile();
+
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgTestData = readXvgData(referenceFilename());
+
+ const int numRows = 2;
+ const int numColumns = 3;
+ MultiDimArray<std::vector<double>, dynamicExtents2D> xvgRefData(numRows, numColumns);
+ std::iota(begin(xvgRefData), end(xvgRefData), 1);
+
+ compareValues(xvgRefData.asConstView(), xvgTestData.asConstView());
+}
+
+// TODO Remove this test once all calls to read_xvg have been ported to readXvgData
+TEST_F(XvgioTest, readXvgDeprecatedWorks)
+{
+ useStringAsXvgFile(
+ "1 2 3\n"
+ "4 5 6\n");
+ writeXvgFile();
+ std::vector<std::vector<double>> xvgData = { { 1, 4 }, { 2, 5 }, { 3, 6 } };
+
+ double** xvgTestData = nullptr;
+ int testNumColumns;
+ int testNumRows = read_xvg(referenceFilename().c_str(), &xvgTestData, &testNumColumns);
+
+ double** xvgRefData = nullptr;
+ int refNumColumns = 3;
+ int refNumRows = 2;
+
+ EXPECT_EQ(refNumColumns, testNumColumns);
+ EXPECT_EQ(refNumRows, testNumRows);
+
+ // Set the reference data
+ snew(xvgRefData, refNumColumns);
+ for (int column = 0; column < refNumColumns; column++)
+ {
+ snew(xvgRefData[column], refNumRows);
+ for (int row = 0; row < refNumRows; row++)
+ {
+ xvgRefData[column][row] = xvgData[column][row];
+ }
+ }
+
+ // Check that the reference and test data match
+ for (int column = 0; column < refNumColumns; column++)
+ {
+ for (int row = 0; row < refNumRows; row++)
+ {
+ EXPECT_EQ(xvgRefData[column][row], xvgTestData[column][row]);
+ }
+ }
+
+ // Free the reference and test data memory
+ for (int column = 0; column < refNumColumns; column++)
+ {
+ sfree(xvgRefData[column]);
+ sfree(xvgTestData[column]);
+ }
+ sfree(xvgRefData);
+ sfree(xvgTestData);
+}
+
+} // namespace test
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
tpxv_GenericInternalParameters, /**< Added internal parameters for mdrun modules*/
tpxv_VSite2FD, /**< Added 2FD type virtual site */
tpxv_AddSizeField, /**< Added field with information about the size of the serialized tpr file in bytes, excluding the header */
- tpxv_Count /**< the total number of tpxv versions */
+ tpxv_StoreNonBondedInteractionExclusionGroup, /**< Store the non bonded interaction exclusion group in the topology */
+ tpxv_Count /**< the total number of tpxv versions */
};
/*! \brief Version number of the file format written to run input
{
fepvals->sc_r_power = 6.0;
}
+ if (fepvals->sc_r_power != 6.0)
+ {
+ gmx_fatal(FARGS, "sc-r-power=48 is no longer supported");
+ }
serializer->doReal(&fepvals->sc_sigma);
if (serializer->reading())
{
real dummy_rlistlong = -1;
serializer->doReal(&dummy_rlistlong);
- if (ir->rlist > 0 && (dummy_rlistlong == 0 || dummy_rlistlong > ir->rlist))
- {
- // Get mdrun to issue an error (regardless of
- // ir->cutoff_scheme).
- ir->useTwinRange = true;
- }
- else
- {
- // grompp used to set rlistlong actively. Users were
- // probably also confused and set rlistlong == rlist.
- // However, in all remaining cases, it is safe to let
- // mdrun proceed normally.
- ir->useTwinRange = false;
- }
+ ir->useTwinRange = (ir->rlist > 0 && (dummy_rlistlong == 0 || dummy_rlistlong > ir->rlist));
+ // When true, this forces mdrun to issue an error (regardless of
+ // ir->cutoff_scheme).
+ //
+ // Otherwise, grompp used to set rlistlong actively. Users
+ // were probably also confused and set rlistlong == rlist.
+ // However, in all remaining cases, it is safe to let
+ // mdrun proceed normally.
}
}
else
if (file_version >= 79)
{
serializer->doBool(&ir->bExpanded);
- if (ir->bExpanded)
- {
- ir->bExpanded = TRUE;
- }
- else
- {
- ir->bExpanded = FALSE;
- }
}
if (ir->bExpanded)
{
}
}
- /* QMMM stuff */
+ /* QMMM reading - despite defunct we require reading for backwards
+ * compability and correct serialization
+ */
{
serializer->doBool(&ir->bQMMM);
- serializer->doInt(&ir->QMMMscheme);
- serializer->doReal(&ir->scalefactor);
+ int qmmmScheme;
+ serializer->doInt(&qmmmScheme);
+ real unusedScalefactor;
+ serializer->doReal(&unusedScalefactor);
+
+ // this is still used in Mimic
serializer->doInt(&ir->opts.ngQM);
- if (serializer->reading())
- {
- snew(ir->opts.QMmethod, ir->opts.ngQM);
- snew(ir->opts.QMbasis, ir->opts.ngQM);
- snew(ir->opts.QMcharge, ir->opts.ngQM);
- snew(ir->opts.QMmult, ir->opts.ngQM);
- snew(ir->opts.bSH, ir->opts.ngQM);
- snew(ir->opts.CASorbitals, ir->opts.ngQM);
- snew(ir->opts.CASelectrons, ir->opts.ngQM);
- snew(ir->opts.SAon, ir->opts.ngQM);
- snew(ir->opts.SAoff, ir->opts.ngQM);
- snew(ir->opts.SAsteps, ir->opts.ngQM);
- }
if (ir->opts.ngQM > 0 && ir->bQMMM)
{
- serializer->doIntArray(ir->opts.QMmethod, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.QMbasis, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.QMcharge, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.QMmult, ir->opts.ngQM);
- serializer->doBoolArray(ir->opts.bSH, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.CASorbitals, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.CASelectrons, ir->opts.ngQM);
- serializer->doRealArray(ir->opts.SAon, ir->opts.ngQM);
- serializer->doRealArray(ir->opts.SAoff, ir->opts.ngQM);
- serializer->doIntArray(ir->opts.SAsteps, ir->opts.ngQM);
/* We leave in dummy i/o for removed parameters to avoid
- * changing the tpr format for every QMMM change.
+ * changing the tpr format.
*/
- std::vector<int> dummy(ir->opts.ngQM, 0);
- serializer->doIntArray(dummy.data(), ir->opts.ngQM);
- serializer->doIntArray(dummy.data(), ir->opts.ngQM);
+ std::vector<int> dummyIntVec(4 * ir->opts.ngQM, 0);
+ serializer->doIntArray(dummyIntVec.data(), dummyIntVec.size());
+ dummyIntVec.clear();
+
+ // std::vector<bool> has no data()
+ std::vector<char> dummyBoolVec(ir->opts.ngQM * sizeof(bool) / sizeof(char));
+ serializer->doBoolArray(reinterpret_cast<bool*>(dummyBoolVec.data()), dummyBoolVec.size());
+ dummyBoolVec.clear();
+
+ dummyIntVec.resize(2 * ir->opts.ngQM, 0);
+ serializer->doIntArray(dummyIntVec.data(), dummyIntVec.size());
+ dummyIntVec.clear();
+
+ std::vector<real> dummyRealVec(2 * ir->opts.ngQM, 0);
+ serializer->doRealArray(dummyRealVec.data(), dummyRealVec.size());
+ dummyRealVec.clear();
+
+ dummyIntVec.resize(3 * ir->opts.ngQM, 0);
+ serializer->doIntArray(dummyIntVec.data(), dummyIntVec.size());
+ dummyIntVec.clear();
}
/* end of QMMM stuff */
}
break;
case F_CBTDIHS: serializer->doRealArray(iparams->cbtdihs.cbtcA, NR_CBTDIHS); break;
case F_RBDIHS:
- serializer->doRealArray(iparams->rbdihs.rbcA, NR_RBDIHS);
- serializer->doRealArray(iparams->rbdihs.rbcB, NR_RBDIHS);
- break;
+ // Fall-through intended
case F_FOURDIHS:
/* Fourier dihedrals are internally represented
* as Ryckaert-Bellemans since those are faster to compute.
else
{
do_ilist(serializer, &ilist);
- if (file_version < 78 && j == F_SETTLE && ilist.size() > 0)
+ if (file_version < 78 && j == F_SETTLE && !ilist.empty())
{
add_settle_atoms(&ilist);
}
serializer->doIntArray(block->index, block->nr + 1);
}
-static void do_blocka(gmx::ISerializer* serializer, t_blocka* block)
+static void doListOfLists(gmx::ISerializer* serializer, gmx::ListOfLists<int>* listOfLists)
{
- serializer->doInt(&block->nr);
- serializer->doInt(&block->nra);
+ int numLists = listOfLists->ssize();
+ serializer->doInt(&numLists);
+ int numElements = listOfLists->elementsView().ssize();
+ serializer->doInt(&numElements);
if (serializer->reading())
{
- block->nalloc_index = block->nr + 1;
- snew(block->index, block->nalloc_index);
- block->nalloc_a = block->nra;
- snew(block->a, block->nalloc_a);
+ std::vector<int> listRanges(numLists + 1);
+ serializer->doIntArray(listRanges.data(), numLists + 1);
+ std::vector<int> elements(numElements);
+ serializer->doIntArray(elements.data(), numElements);
+ *listOfLists = gmx::ListOfLists<int>(std::move(listRanges), std::move(elements));
+ }
+ else
+ {
+ serializer->doIntArray(const_cast<int*>(listOfLists->listRangesView().data()), numLists + 1);
+ serializer->doIntArray(const_cast<int*>(listOfLists->elementsView().data()), numElements);
}
- serializer->doIntArray(block->index, block->nr + 1);
- serializer->doIntArray(block->a, block->nra);
}
/* This is a primitive routine to make it possible to translate atomic numbers
sfree(cgs.index);
/* This used to be in the atoms struct */
- do_blocka(serializer, &molt->excls);
+ doListOfLists(serializer, &molt->excls);
}
static void do_molblock(gmx::ISerializer* serializer, gmx_molblock_t* molb, int numAtomsPerMolecule)
{
const InteractionList& il = (*ilist)[F_DISRES];
- if (il.size() > 0)
+ if (!il.empty())
{
gmx::ArrayRef<const int> a = il.iatoms;
int npair = 0;
mtop->haveMoleculeIndices = true;
+ if (file_version >= tpxv_StoreNonBondedInteractionExclusionGroup)
+ {
+ std::int64_t intermolecularExclusionGroupSize = gmx::ssize(mtop->intermolecularExclusionGroup);
+ serializer->doInt64(&intermolecularExclusionGroupSize);
+ GMX_RELEASE_ASSERT(intermolecularExclusionGroupSize >= 0,
+ "Number of atoms with excluded intermolecular non-bonded interactions "
+ "is negative.");
+ mtop->intermolecularExclusionGroup.resize(intermolecularExclusionGroupSize); // no effect when writing
+ serializer->doIntArray(mtop->intermolecularExclusionGroup.data(),
+ mtop->intermolecularExclusionGroup.size());
+ }
+
if (serializer->reading())
{
close_symtab(&(mtop->symtab));
* \param[in] tpx The file header data.
* \param[in,out] ir Datastructure with simulation parameters.
*/
-static int do_tpx_ir(gmx::ISerializer* serializer, TpxFileHeader* tpx, t_inputrec* ir)
+static PbcType do_tpx_ir(gmx::ISerializer* serializer, TpxFileHeader* tpx, t_inputrec* ir)
{
- int ePBC;
+ PbcType pbcType;
gmx_bool bPeriodicMols;
/* Starting with tpx version 26, we have the inputrec
*
*
*/
- ePBC = -1;
+ pbcType = PbcType::Unset;
bPeriodicMols = FALSE;
do_test(serializer, tpx->bIr, ir);
/* Removed the pbc info from do_inputrec, since we always want it */
if (!serializer->reading())
{
- ePBC = ir->ePBC;
+ pbcType = ir->pbcType;
bPeriodicMols = ir->bPeriodicMols;
}
- serializer->doInt(&ePBC);
+ serializer->doInt(reinterpret_cast<int*>(&pbcType));
serializer->doBool(&bPeriodicMols);
}
if (tpx->fileGeneration <= tpx_generation && ir)
do_inputrec(serializer, ir, tpx->fileVersion);
if (tpx->fileVersion < 53)
{
- ePBC = ir->ePBC;
+ pbcType = ir->pbcType;
bPeriodicMols = ir->bPeriodicMols;
}
}
if (serializer->reading() && ir && tpx->fileVersion >= 53)
{
/* We need to do this after do_inputrec, since that initializes ir */
- ir->ePBC = ePBC;
+ ir->pbcType = pbcType;
ir->bPeriodicMols = bPeriodicMols;
}
}
- return ePBC;
+ return pbcType;
}
/*! \brief
{
if (tpx->fileVersion < 57)
{
- if (mtop->moltype[0].ilist[F_DISRES].size() > 0)
+ if (!mtop->moltype[0].ilist[F_DISRES].empty())
{
ir->eDisre = edrSimple;
}
* \param[in,out] v Individual velocities for processing, deprecated.
* \param[in,out] mtop Global topology.
*/
-static int do_tpx_body(gmx::ISerializer* serializer,
- TpxFileHeader* tpx,
- t_inputrec* ir,
- t_state* state,
- rvec* x,
- rvec* v,
- gmx_mtop_t* mtop)
+static PbcType do_tpx_body(gmx::ISerializer* serializer,
+ TpxFileHeader* tpx,
+ t_inputrec* ir,
+ t_state* state,
+ rvec* x,
+ rvec* v,
+ gmx_mtop_t* mtop)
{
if (state)
{
{
do_tpx_state_second(serializer, tpx, state, x, v);
}
- int ePBC = do_tpx_ir(serializer, tpx, ir);
+ PbcType pbcType = do_tpx_ir(serializer, tpx, ir);
if (serializer->reading())
{
do_tpx_finalize(tpx, ir, state, mtop);
}
- return ePBC;
+ return pbcType;
}
/*! \brief
* \param[in,out] ir Datastructures with simulation parameters.
* \param[in,out] mtop Global topology.
*/
-static int do_tpx_body(gmx::ISerializer* serializer, TpxFileHeader* tpx, t_inputrec* ir, gmx_mtop_t* mtop)
+static PbcType do_tpx_body(gmx::ISerializer* serializer, TpxFileHeader* tpx, t_inputrec* ir, gmx_mtop_t* mtop)
{
return do_tpx_body(serializer, tpx, ir, nullptr, nullptr, nullptr, mtop);
}
partialDeserializedTpr.header = *tpx;
doTpxBodyBuffer(serializer, partialDeserializedTpr.body);
- partialDeserializedTpr.ePBC =
+ partialDeserializedTpr.pbcType =
completeTprDeserialization(&partialDeserializedTpr, ir, state, x, v, mtop);
}
else
{
- partialDeserializedTpr.ePBC = do_tpx_body(serializer, tpx, ir, state, x, v, mtop);
+ partialDeserializedTpr.pbcType = do_tpx_body(serializer, tpx, ir, state, x, v, mtop);
}
// Update header to system info for communication to nodes.
// As we only need to communicate the inputrec and mtop to other nodes,
close_tpx(fio);
}
-int completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
- t_inputrec* ir,
- t_state* state,
- rvec* x,
- rvec* v,
- gmx_mtop_t* mtop)
+PbcType completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
+ t_inputrec* ir,
+ t_state* state,
+ rvec* x,
+ rvec* v,
+ gmx_mtop_t* mtop)
{
// Long-term we should move to use little endian in files to avoid extra byte swapping,
// but since we just used the default XDR format (which is big endian) for the TPR
return do_tpx_body(&tprBodyDeserializer, &partialDeserializedTpr->header, ir, state, x, v, mtop);
}
-int completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
- t_inputrec* ir,
- gmx_mtop_t* mtop)
+PbcType completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
+ t_inputrec* ir,
+ gmx_mtop_t* mtop)
{
return completeTprDeserialization(partialDeserializedTpr, ir, nullptr, nullptr, nullptr, mtop);
}
return partialDeserializedTpr;
}
-int read_tpx(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, gmx_mtop_t* mtop)
+PbcType read_tpx(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, gmx_mtop_t* mtop)
{
t_fileio* fio;
t_state state;
{
copy_mat(state.box, box);
}
- return partialDeserializedTpr.ePBC;
+ return partialDeserializedTpr.pbcType;
}
-int read_tpx_top(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, t_topology* top)
+PbcType read_tpx_top(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, t_topology* top)
{
gmx_mtop_t mtop;
- int ePBC;
+ PbcType pbcType;
- ePBC = read_tpx(fn, ir, box, natoms, x, v, &mtop);
+ pbcType = read_tpx(fn, ir, box, natoms, x, v, &mtop);
*top = gmx_mtop_t_to_t_topology(&mtop, true);
- return ePBC;
+ return pbcType;
}
gmx_bool fn2bTPX(const char* file)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
#include "gromacs/math/vectypes.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
//! The file body.
std::vector<char> body;
//! Flag for PBC needed by legacy implementation.
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
};
/*
*
* \returns PBC flag.
*/
-int completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
- t_inputrec* ir,
- t_state* state,
- rvec* x,
- rvec* v,
- gmx_mtop_t* mtop);
+PbcType completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
+ t_inputrec* ir,
+ t_state* state,
+ rvec* x,
+ rvec* v,
+ gmx_mtop_t* mtop);
//! Overload for final TPR deserialization when not using state vectors.
-int completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
- t_inputrec* ir,
- gmx_mtop_t* mtop);
+PbcType completeTprDeserialization(PartialDeserializedTprFile* partialDeserializedTpr,
+ t_inputrec* ir,
+ gmx_mtop_t* mtop);
/*! \brief
* Read a file to set up a simulation and close it after reading.
* \param[out] x Positions to be filled from file, or nullptr.
* \param[out] v Velocities to be filled from file, or nullptr.
* \param[out] mtop Topology to be populated, or nullptr.
- * \returns ir->ePBC if it was read from the file.
+ * \returns ir->pbcType if it was read from the file.
*/
-int read_tpx(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, gmx_mtop_t* mtop);
+PbcType read_tpx(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, gmx_mtop_t* mtop);
-int read_tpx_top(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, t_topology* top);
+PbcType read_tpx_top(const char* fn, t_inputrec* ir, matrix box, int* natoms, rvec* x, rvec* v, t_topology* top);
/* As read_tpx, but for the old t_topology struct */
gmx_bool fn2bTPX(const char* file);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
fr->v = nullptr;
fr->f = nullptr;
clear_mat(fr->box);
- fr->bPBC = FALSE;
- fr->ePBC = -1;
+ fr->bPBC = FALSE;
+ fr->pbcType = PbcType::Unset;
}
}
-void set_trxframe_ePBC(t_trxframe* fr, int ePBC)
+void setTrxFramePbcType(t_trxframe* fr, PbcType pbcType)
{
- fr->bPBC = (ePBC == -1);
- fr->ePBC = ePBC;
+ fr->bPBC = (pbcType == PbcType::Unset);
+ fr->pbcType = pbcType;
}
int write_trxframe_indexed(t_trxstatus* status, const t_trxframe* fr, int nind, const int* ind, gmx_conect gc)
}
else
{
- write_pdbfile_indexed(gmx_fio_getfp(status->fio), title, fr->atoms, fr->x, -1,
- fr->box, ' ', fr->step, nind, ind, gc, FALSE);
+ write_pdbfile_indexed(gmx_fio_getfp(status->fio), title, fr->atoms, fr->x,
+ PbcType::Unset, fr->box, ' ', fr->step, nind, ind, gc, FALSE);
}
break;
case efG96:
else
{
write_pdbfile(gmx_fio_getfp(status->fio), title, fr->atoms, fr->x,
- fr->bPBC ? fr->ePBC : -1, fr->box, ' ', fr->step, gc);
+ fr->bPBC ? fr->pbcType : PbcType::Unset, fr->box, ' ', fr->step, gc);
}
break;
case efG96: write_g96_conf(gmx_fio_getfp(status->fio), title, fr, -1, nullptr); break;
// Initiate model_nr to -1 rather than NOTSET.
// It is not worthwhile introducing extra variables in the
// read_pdbfile call to verify that a model_nr was read.
- int ePBC, model_nr = -1, na;
- char title[STRLEN], *time, *step;
- double dbl;
+ PbcType pbcType;
+ int model_nr = -1, na;
+ char title[STRLEN], *time, *step;
+ double dbl;
atoms.nr = fr->natoms;
atoms.atom = nullptr;
/* the other pointers in atoms should not be accessed if these are NULL */
snew(symtab, 1);
open_symtab(symtab);
- na = read_pdbfile(fp, title, &model_nr, &atoms, symtab, fr->x, &ePBC, boxpdb, TRUE, nullptr);
+ na = read_pdbfile(fp, title, &model_nr, &atoms, symtab, fr->x, &pbcType, boxpdb, TRUE, nullptr);
free_symtab(symtab);
sfree(symtab);
- set_trxframe_ePBC(fr, ePBC);
+ setTrxFramePbcType(fr, pbcType);
if (nframes_read(status) == 0)
{
fprintf(stderr, " '%s', %d atoms\n", title, fr->natoms);
/***** T O P O L O G Y S T U F F ******/
-t_topology* read_top(const char* fn, int* ePBC)
+t_topology* read_top(const char* fn, PbcType* pbcType)
{
- int epbc, natoms;
+ int natoms;
+ PbcType pbcTypeFile;
t_topology* top;
snew(top, 1);
- epbc = read_tpx_top(fn, nullptr, nullptr, &natoms, nullptr, nullptr, top);
- if (ePBC)
+ pbcTypeFile = read_tpx_top(fn, nullptr, nullptr, &natoms, nullptr, nullptr, top);
+ if (pbcType)
{
- *ePBC = epbc;
+ *pbcType = pbcTypeFile;
}
return top;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* and all data to zero.
*/
-void set_trxframe_ePBC(struct t_trxframe* fr, int ePBC);
-/* Set the type of periodic boundary conditions, ePBC=-1 is not set */
+void setTrxFramePbcType(struct t_trxframe* fr, PbcType pbcType);
+/* Set the type of periodic boundary conditions, pbcType=PbcType::Unset is not set */
int nframes_read(t_trxstatus* status);
/* Returns the number of frames read from the trajectory */
void rewind_trj(t_trxstatus* status);
/* Rewind trajectory file as opened with read_first_x */
-struct t_topology* read_top(const char* fn, int* ePBC);
+struct t_topology* read_top(const char* fn, PbcType* pbcType);
/* Extract a topology data structure from a topology file.
- * If ePBC!=NULL *ePBC gives the pbc type.
+ * If pbcType!=NULL *pbcType gives the pbc type.
*/
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2012,2013,2014,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/fileio/gmxfio.h"
#include "gromacs/fileio/oenv.h"
#include "gromacs/math/vec.h"
+#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/binaryinformation.h"
#include "gromacs/utility/coolstuff.h"
#include "gromacs/utility/cstringutil.h"
gmx_bool output_env_get_print_xvgr_codes(const gmx_output_env_t* oenv)
{
- int xvg_format;
+ XvgFormat xvgFormat = output_env_get_xvg_format(oenv);
- xvg_format = output_env_get_xvg_format(oenv);
-
- return (xvg_format == exvgXMGRACE || xvg_format == exvgXMGR);
+ return (xvgFormat == XvgFormat::Xmgrace || xvgFormat == XvgFormat::Xmgr);
}
static char* xvgrstr(const std::string& gmx, const gmx_output_env_t* oenv, char* buf, int buflen)
const char* sym[] = { "beta", "chi", "delta", "eta", "lambda", "mu",
"omega", "phi", "psi", "rho", "theta", nullptr };
const char symc[] = { 'b', 'c', 'd', 'h', 'l', 'm', 'w', 'f', 'y', 'r', 'q', '\0' };
- int xvgf;
gmx_bool bXVGR;
int g, b, i;
char c;
- xvgf = output_env_get_xvg_format(oenv);
- bXVGR = (xvgf == exvgXMGRACE || xvgf == exvgXMGR);
+ XvgFormat xvgf = output_env_get_xvg_format(oenv);
+ bXVGR = (xvgf == XvgFormat::Xmgrace || xvgf == XvgFormat::Xmgr);
g = 0;
b = 0;
/* Backward compatibility for xmgr normal font "\4" */
switch (xvgf)
{
- case exvgXMGRACE: sprintf(buf + b, "%s", "\\f{}"); break;
- case exvgXMGR: sprintf(buf + b, "%s", "\\4"); break;
+ case XvgFormat::Xmgrace: sprintf(buf + b, "%s", "\\f{}"); break;
+ case XvgFormat::Xmgr: sprintf(buf + b, "%s", "\\4"); break;
default: buf[b] = '\0'; break;
}
g++;
/* Backward compatibility for xmgr symbol font "\8" */
switch (xvgf)
{
- case exvgXMGRACE: sprintf(buf + b, "%s", "\\x"); break;
- case exvgXMGR: sprintf(buf + b, "%s", "\\8"); break;
+ case XvgFormat::Xmgrace: sprintf(buf + b, "%s", "\\x"); break;
+ case XvgFormat::Xmgr: sprintf(buf + b, "%s", "\\8"); break;
default: buf[b] = '\0'; break;
}
g++;
}
switch (xvgf)
{
- case exvgXMGRACE: sprintf(buf + b, "%s%c%s", "\\x", c, "\\f{}"); break;
- case exvgXMGR: sprintf(buf + b, "%s%c%s", "\\8", c, "\\4"); break;
+ case XvgFormat::Xmgrace:
+ sprintf(buf + b, "%s%c%s", "\\x", c, "\\f{}");
+ break;
+ case XvgFormat::Xmgr: sprintf(buf + b, "%s%c%s", "\\8", c, "\\4"); break;
default:
std::strncat(buf + b, &gmx[g], std::strlen(sym[i]));
b += std::strlen(sym[i]);
switch (exvg_graph_type)
{
case exvggtXNY:
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
fprintf(fp, "@TYPE nxy\n");
}
{
if (!stringIsEmpty(setname[i]))
{
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
fprintf(out, "@ legend string %d \"%s\"\n", i, xvgrstr(setname[i], oenv, buf, STRLEN));
}
{
if (setname[i])
{
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
fprintf(out, "@ legend string %d \"%s\"\n", i + nr_first,
xvgrstr(setname[i], oenv, buf, STRLEN));
for (i = 0; (ptr[i] != '\0'); i++)
{
is[cur] = std::isspace(ptr[i]);
- if ((0 == i) && !is[cur])
- {
- n++;
- }
- else if ((i > 0) && (!is[cur] && is[prev]))
+ if (((0 == i) && !is[cur]) || ((i > 0) && (!is[cur] && is[prev])))
{
n++;
}
int read_xvg(const char* fn, double*** y, int* ny)
{
- return read_xvg_legend(fn, y, ny, nullptr, nullptr);
+ gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> xvgData =
+ readXvgData(std::string(fn));
+
+ int numColumns = xvgData.extent(0);
+ int numRows = xvgData.extent(1);
+
+ double** yy = nullptr;
+ snew(yy, numColumns);
+ for (int column = 0; column < numColumns; column++)
+ {
+ snew(yy[column], numRows);
+ for (int row = 0; row < numRows; row++)
+ {
+ yy[column][row] = xvgData.asConstView()[column][row];
+ }
+ }
+
+ *y = yy;
+ *ny = numColumns;
+ int nx = numRows;
+ return nx;
+}
+
+gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> readXvgData(const std::string& fn)
+{
+ FILE* fp = gmx_fio_fopen(fn.c_str(), "r");
+ char* ptr;
+ char* base = nullptr;
+ char* fmt = nullptr;
+ char* tmpbuf;
+ int len = STRLEN;
+
+ //! This only gets properly set after the first line of data is read
+ int numColumns = 0;
+ int numRows = 0;
+ snew(tmpbuf, len);
+ std::vector<double> xvgData;
+
+ for (int line = 0; (ptr = fgets3(fp, &tmpbuf, &len, 10 * STRLEN)) != nullptr && ptr[0] != '&'; ++line)
+ {
+ trim(ptr);
+ if (ptr[0] == '@' || ptr[0] == '#')
+ {
+ continue;
+ }
+ ++numRows;
+ if (numColumns == 0)
+ {
+ numColumns = wordcount(ptr);
+ if (numColumns == 0)
+ {
+ return {}; // There are no columns and hence no data to process
+ }
+ snew(fmt, 3 * numColumns + 1);
+ snew(base, 3 * numColumns + 1);
+ }
+ /* Initiate format string */
+ fmt[0] = '\0';
+ base[0] = '\0';
+ int columnCount = 0;
+ for (columnCount = 0; (columnCount < numColumns); columnCount++)
+ {
+ double lf;
+ std::strcpy(fmt, base);
+ std::strcat(fmt, "%lf");
+ int rval = sscanf(ptr, fmt, &lf);
+ if ((rval == EOF) || (rval == 0))
+ {
+ break;
+ }
+ xvgData.push_back(lf);
+ srenew(fmt, 3 * (numColumns + 1) + 1);
+ srenew(base, 3 * numColumns + 1);
+ std::strcat(base, "%*s");
+ }
+
+ if (columnCount != numColumns)
+ {
+ fprintf(stderr, "Only %d columns on line %d in file %s\n", columnCount, line, fn.c_str());
+ for (; (columnCount < numColumns); columnCount++)
+ {
+ xvgData.push_back(0.0);
+ }
+ }
+ }
+ gmx_fio_fclose(fp);
+
+ sfree(tmpbuf);
+ sfree(base);
+ sfree(fmt);
+
+ gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> xvgDataAsArray(numRows, numColumns);
+ std::copy(std::begin(xvgData), std::end(xvgData), begin(xvgDataAsArray.asView()));
+
+ gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> xvgDataAsArrayTransposed(
+ numColumns, numRows);
+ for (std::ptrdiff_t row = 0; row < numRows; ++row)
+ {
+ for (std::ptrdiff_t column = 0; column < numColumns; ++column)
+ {
+ xvgDataAsArrayTransposed(column, row) = xvgDataAsArray(row, column);
+ }
+ }
+
+ return xvgDataAsArrayTransposed;
}
void write_xvg(const char* fn, const char* title, int nx, int ny, real** y, const char** leg, const gmx_output_env_t* oenv)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <string>
#include <vector>
+#include "gromacs/math/multidimarray.h"
+#include "gromacs/mdspan/extensions.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
* 0 is the first y legend, the legend string will be NULL when not present.
*/
+/* \brief Read only the data from an xvg file for post processing.
+ *
+ * Note: this function is deprecated in favor of readXvg, which is
+ * used under the hood in this function.
+ *
+ * \param[out] nx Number of rows.
+ * \param[in] fn Xvg file to read.
+ * \param[in/out] y Pointer to 2D array (allocated by the routine).
+ * \param[in/out] ny Number of columns.
+ *
+ * Todo: Port all read_xvg calls to use readXvgData
+ */
int read_xvg(const char* fn, double*** y, int* ny);
-/* As read_xvg_legend, but does not read legends. */
+
+/* \brief Read only the data from an xvg file for post processing.
+ *
+ * \param[out] XvgData Data in row major.
+ * \param[in] fn Xvg file to read.
+ */
+gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> readXvgData(const std::string& fn);
+
void write_xvg(const char* fn,
const char* title,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
trans += 1.0;
}
- else if (angle > 270 && angle < 330)
- {
- gauche += 1.0;
- }
- else if (angle < 90 && angle > 30)
+ else if ((angle > 270 && angle < 330) || (angle < 90 && angle > 30))
{
gauche += 1.0;
}
if (pbc)
{
- set_pbc(pbc, -1, box);
+ set_pbc(pbc, PbcType::Unset, box);
}
if (bAngles)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
|| (std::strcmp(*(atoms->atomname[i]), "SD") == 0)
|| (std::strcmp(*(atoms->atomname[i]), "OD1") == 0)
|| (std::strcmp(*(atoms->atomname[i]), "ND1") == 0))
- {
+ { // NOLINT bugprone-branch-clone
atm.Cn[4] = i;
}
/* by grs - split the Cn[4] into 2 bits to check allowing dih to H */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real ymin, ymax, xsp, ysp;
out = gmx_ffopen(file, "w");
- if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
{
fprintf(out, "@ autoscale onread none\n");
}
static void project(const char* trajfile,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
matrix topbox,
const char* projfile,
const char* twodplotfile,
if (top)
{
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, nat);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, nat);
}
for (i = 0; i < nat; i++)
}
else
{
- write_sto_conf(threedplotfile, str, &atoms, x, nullptr, ePBC, box);
+ write_sto_conf(threedplotfile, str, &atoms, x, nullptr, pbcType, box);
}
done_atom(&atoms);
}
#define NPA asize(pa)
t_topology top;
- int ePBC = -1;
- const t_atoms* atoms = nullptr;
+ PbcType pbcType = PbcType::Unset;
+ const t_atoms* atoms = nullptr;
rvec * xtop, *xref1, *xref2, *xrefp = nullptr;
gmx_bool bDMR1, bDMA1, bDMR2, bDMA2;
int nvec1, nvec2, *eignr1 = nullptr, *eignr2 = nullptr;
}
else
{
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, topbox, bM);
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, topbox, bM);
atoms = &top.atoms;
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, atoms->nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, atoms->nr);
gmx_rmpbc(gpbc, atoms->nr, topbox, xtop);
/* Fitting is only required for the projection */
if (bProj && bFit1)
if (bProj)
{
- project(bTraj ? opt2fn("-f", NFILE, fnm) : nullptr, bTop ? &top : nullptr, ePBC, topbox,
+ project(bTraj ? opt2fn("-f", NFILE, fnm) : nullptr, bTop ? &top : nullptr, pbcType, topbox,
ProjOnVecFile, TwoDPlotFile, ThreeDPlotFile, FilterFile, skip, ExtremeFile,
bFirstLastSet, max, nextr, atoms, natoms, index, bFit1, xrefp, nfit, ifit, w_rls,
sqrtm, xav1, eignr1, eigvec1, noutvec, outvec, bSplit, oenv);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
tau2 = fitparm[2];
}
fprintf(stdout, "Set %3d: err.est. %g a %g tau1 %g tau2 %g\n", s + 1, ee, a, tau1, tau2);
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
fprintf(fp, "@ legend string %d \"av %f\"\n", 2 * s, av[s]);
fprintf(fp, "@ legend string %d \"ee %6g\"\n", 2 * s + 1,
optimal_error_estimate(sig[s], fitparm, n * dt));
}
- else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+ else if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
{
fprintf(fp, "@ s%d legend \"av %f\"\n", 2 * s, av[s]);
fprintf(fp, "@ s%d legend \"ee %6g\"\n", 2 * s + 1,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
mult = 3;
maxang = 180.0;
break;
- case 'd': break;
+ case 'd': // Intended fall through
case 'i': break;
case 'r': bRb = TRUE; break;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_trxstatus* status;
t_trxstatus* fpdb;
t_topology top;
- int ePBC;
+ PbcType pbcType;
rvec* xtop;
matrix box;
t_trxframe fr;
return 0;
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, box, TRUE);
bKink = opt2bSet("-ok", NFILE, fnm) || opt2bSet("-okr", NFILE, fnm) || opt2bSet("-okl", NFILE, fnm);
if (bKink)
}
read_first_frame(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &fr, TRX_NEED_X);
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, fr.natoms);
do
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real bfac_init,
t_atoms* atoms,
const rvec x[],
- int ePBC,
+ PbcType pbcType,
matrix box,
gmx_bool bPhi,
gmx_bool bPsi,
fprintf(fp,
"REMARK "
"B-factor field contains negative of dihedral order parameters\n");
- write_pdbfile(fp, nullptr, atoms, x, ePBC, box, ' ', 0, nullptr);
+ write_pdbfile(fp, nullptr, atoms, x, pbcType, box, ' ', 0, nullptr);
x0 = y0 = z0 = 1000.0;
for (i = 0; (i < atoms->nr); i++)
{
FILE* log;
int nlist, idum, nbin;
rvec* x;
- int ePBC;
+ PbcType pbcType;
matrix box;
char grpname[256];
t_dlist* dlist;
/* Find the chi angles using atoms struct and a list of amino acids */
t_topology* top;
snew(top, 1);
- read_tps_conf(ftp2fn(efSTX, NFILE, fnm), top, &ePBC, &x, nullptr, box, FALSE);
+ read_tps_conf(ftp2fn(efSTX, NFILE, fnm), top, &pbcType, &x, nullptr, box, FALSE);
t_atoms& atoms = top->atoms;
if (atoms.pdbinfo == nullptr)
{
/* Order parameters */
order_params(log, opt2fn("-o", NFILE, fnm), maxchi, nlist, dlist, ftp2fn_null(efPDB, NFILE, fnm),
- bfac_init, &atoms, x, ePBC, box, bPhi, bPsi, bChi, oenv);
+ bfac_init, &atoms, x, pbcType, box, bPhi, bPsi, bChi, oenv);
/* Print ramachandran maps! */
if (bRama)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_mat * rms, *orig = nullptr;
real* eigenvalues;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms useatoms;
real* eigenvectors;
if (bReadTraj)
{
/* don't read mass-database as masses (and top) are not used */
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtps, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtps, nullptr, box, TRUE);
if (bPBC)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, top.atoms.nr);
}
fprintf(stderr, "\nSelect group for least squares fit%s:\n", bReadMat ? "" : " and RMSD calculation");
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2007, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* Topology stuff */
t_trxframe fr;
TpxFileHeader tpxh;
- gmx_mtop_t* mtop = nullptr;
- int ePBC = -1;
+ gmx_mtop_t* mtop = nullptr;
+ PbcType pbcType = PbcType::Unset;
int ii, jj;
real temp, tfac;
/* Cluster size distribution (matrix) */
{
gmx_fatal(FARGS, "tpr (%d atoms) and trajectory (%d atoms) do not match!", tpxh.natoms, natoms);
}
- ePBC = read_tpx(tpr, nullptr, nullptr, &natoms, nullptr, nullptr, mtop);
+ pbcType = read_tpx(tpr, nullptr, nullptr, &natoms, nullptr, nullptr, mtop);
}
if (ndf <= -1)
{
{
if (bPBC)
{
- set_pbc(&pbc, ePBC, fr.box);
+ set_pbc(&pbc, pbcType, fr.box);
}
max_clust_size = 1;
max_clust_ind = -1;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
FILE* fp;
char * name1, *name2;
t_topology *top1, *top2;
- int ePBC1, ePBC2;
+ PbcType pbcType1, pbcType2;
t_atoms * atoms1, *atoms2;
int warn = 0;
int at;
/* reading reference structure from first structure file */
fprintf(stderr, "\nReading first structure file\n");
snew(top1, 1);
- read_tps_conf(conf1file, top1, &ePBC1, &x1, &v1, box1, TRUE);
+ read_tps_conf(conf1file, top1, &pbcType1, &x1, &v1, box1, TRUE);
atoms1 = &(top1->atoms);
fprintf(stderr, "%s\nContaining %d atoms in %d residues\n", *top1->name, atoms1->nr, atoms1->nres);
/* reading second structure file */
fprintf(stderr, "\nReading second structure file\n");
snew(top2, 1);
- read_tps_conf(conf2file, top2, &ePBC2, &x2, &v2, box2, TRUE);
+ read_tps_conf(conf2file, top2, &pbcType2, &x2, &v2, box2, TRUE);
atoms2 = &(top2->atoms);
fprintf(stderr, "%s\nContaining %d atoms in %d residues\n", *top2->name, atoms2->nr, atoms2->nres);
fp = gmx_ffopen(outfile, "w");
if (!bOne)
{
- write_pdbfile(fp, *top1->name, atoms1, x1, ePBC1, box1, ' ', 1, nullptr);
+ write_pdbfile(fp, *top1->name, atoms1, x1, pbcType1, box1, ' ', 1, nullptr);
}
- write_pdbfile(fp, *top2->name, atoms2, x2, ePBC2, box2, ' ', bOne ? -1 : 2, nullptr);
+ write_pdbfile(fp, *top2->name, atoms2, x2, pbcType2, box2, ' ', bOne ? -1 : 2, nullptr);
gmx_ffclose(fp);
break;
case efGRO:
fprintf(stderr, "WARNING: cannot write the reference structure to %s file\n",
ftp2ext(fn2ftp(outfile)));
}
- write_sto_conf(outfile, *top2->name, atoms2, x2, v2, ePBC2, box2);
+ write_sto_conf(outfile, *top2->name, atoms2, x2, v2, pbcType2, box2);
break;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
FILE* out = nullptr; /* initialization makes all compilers happy */
t_trxstatus* status;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
rvec * x, *xread, *xref, *xav, *xproj;
matrix box, zerobox;
xpmfile = opt2fn_null("-xpm", NFILE, fnm);
xpmafile = opt2fn_null("-xpma", NFILE, fnm);
- read_tps_conf(fitfile, &top, &ePBC, &xref, nullptr, box, TRUE);
+ read_tps_conf(fitfile, &top, &pbcType, &xref, nullptr, box, TRUE);
atoms = &top.atoms;
if (bFit)
/* Prepare reference frame */
if (bPBC)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, atoms->nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, atoms->nr);
gmx_rmpbc(gpbc, atoms->nr, box, xref);
}
if (bFit)
}
}
write_sto_conf_indexed(opt2fn("-av", NFILE, fnm), "Average structure", atoms, xread, nullptr,
- epbcNONE, zerobox, natoms, index);
+ PbcType::No, zerobox, natoms, index);
sfree(xread);
fprintf(stderr, "Constructing covariance matrix (%dx%d) ...\n", static_cast<int>(ndim),
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2008,2009,2010,2011,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2008,2009,2010,2011,2012 by the GROMACS development team.
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
static void calc_mj(t_topology top,
- int ePBC,
+ PbcType pbcType,
matrix box,
gmx_bool bNoJump,
int isize,
if (!bNoJump)
{
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
}
clear_rvec(tmp);
gmx_bool bNoJump,
gmx_bool bACF,
gmx_bool bINT,
- int ePBC,
+ PbcType pbcType,
t_topology top,
t_trxframe fr,
real temp,
clear_rvec(mjd_tmp);
clear_rvec(mdvec);
clear_rvec(tmp);
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, fr.natoms);
do
{
gmx_rmpbc_trxfr(gpbc, &fr);
- calc_mj(top, ePBC, fr.box, bNoJump, nmols, indexm, fr.x, mtrans[nfr], mass2, qmol);
+ calc_mj(top, pbcType, fr.box, bNoJump, nmols, indexm, fr.x, mtrans[nfr], mass2, qmol);
for (i = 0; i < isize; i++)
{
int flags = 0;
gmx_bool bACF;
gmx_bool bINT;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
int nmols;
int i;
real* qmol;
bACF = opt2bSet("-caf", NFILE, fnm);
bINT = opt2bSet("-mc", NFILE, fnm);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, nullptr, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, nullptr, nullptr, box, TRUE);
indexfn = ftp2fn_null(efNDX, NFILE, fnm);
snew(grpname, 1);
/* System information is read and prepared, dielectric() processes the frames
* and calculates the requested quantities */
- dielectric(fmj, fmd, outf, fcur, mcor, fmjdsp, bNoJump, bACF, bINT, ePBC, top, fr, temp, bfit, efit,
+ dielectric(fmj, fmd, outf, fcur, mcor, fmjdsp, bNoJump, bACF, bINT, pbcType, top, fr, temp, bfit, efit,
bvit, evit, status, isize, nmols, nshift, index0, indexm, mass2, qmol, eps_rf, oenv);
xvgrclose(fmj);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
double*** slDensity,
int* nslices,
t_topology* top,
- int ePBC,
+ PbcType pbcType,
int axis,
int nr_grps,
real* slWidth,
snew((*slDensity)[i], *nslices);
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, top->atoms.nr);
/*********** Start processing trajectory ***********/
do
{
double*** slDensity,
int* nslices,
t_topology* top,
- int ePBC,
+ PbcType pbcType,
int axis,
int nr_grps,
real* slWidth,
snew((*slDensity)[i], *nslices);
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, top->atoms.nr);
/*********** Start processing trajectory ***********/
snew(den_val, top->atoms.nr);
int* ngx; /* sizes of groups */
t_electron* el_tab; /* tabel with nr. of electrons*/
t_topology* top; /* topology */
- int ePBC;
+ PbcType pbcType;
int* index_center; /* index for centering group */
int** index; /* indices for all groups */
/* Calculate axis */
axis = toupper(axtitle[0]) - 'X';
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType); /* read topology file */
snew(grpname, ngrps);
snew(index, ngrps);
nr_electrons = get_electrons(&el_tab, ftp2fn(efDAT, NFILE, fnm));
fprintf(stderr, "Read %d atomtypes from datafile\n", nr_electrons);
- calc_electron_density(ftp2fn(efTRX, NFILE, fnm), index, ngx, &density, &nslices, top, ePBC,
- axis, ngrps, &slWidth, el_tab, nr_electrons, bCenter, index_center,
- ncenter, bRelative, oenv);
+ calc_electron_density(ftp2fn(efTRX, NFILE, fnm), index, ngx, &density, &nslices, top,
+ pbcType, axis, ngrps, &slWidth, el_tab, nr_electrons, bCenter,
+ index_center, ncenter, bRelative, oenv);
}
else
{
- calc_density(ftp2fn(efTRX, NFILE, fnm), index, ngx, &density, &nslices, top, ePBC, axis,
+ calc_density(ftp2fn(efTRX, NFILE, fnm), index, ngx, &density, &nslices, top, pbcType, axis,
ngrps, &slWidth, bCenter, index_center, ncenter, bRelative, oenv, dens_opt);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
FILE* fp;
t_trxstatus* status;
t_topology top;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
rvec * x, xcom[2], direction, center, dx;
matrix box;
real t, m, mtot;
if (ftp2bSet(efTPS, NFILE, fnm) || !ftp2bSet(efNDX, NFILE, fnm))
{
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, bRadial);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x, nullptr, box, bRadial);
}
if (!bRadial)
{
}
else
{
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (i = 0; i < 2; i++)
{
if (gnx[i] == 1)
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int* zslices,
int* tblock,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
int axis,
gmx_bool bCenter,
gmx_bool bps1d,
/****Start trajectory processing***/
/*Initialize Densdevel and PBC-remove*/
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, top->atoms.nr);
*Densdevel = nullptr;
gmx_output_env_t* oenv;
t_topology* top;
char** grpname;
- int ePBC, *ngx;
+ PbcType pbcType;
+ int* ngx;
static real binw = 0.2;
static real binwz = 0.05;
static real dens1 = 0.00;
bRawOut = opt2bSet("-or", NFILE, fnm);
bGraph = opt2bSet("-og", NFILE, fnm);
bOut = opt2bSet("-o", NFILE, fnm);
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType);
snew(grpname, 1);
snew(index, 1);
snew(ngx, 1);
get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, ngx, index, grpname);
density_in_time(ftp2fn(efTRX, NFILE, fnm), index, ngx, binw, binwz, nsttblock, &Densmap,
- &xslices, &yslices, &zslices, &tblock, top, ePBC, axis, bCenter, b1d, oenv);
+ &xslices, &yslices, &zslices, &tblock, top, pbcType, axis, bCenter, b1d, oenv);
if (ftorder > 0)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const int mindex[],
rvec x[],
rvec mu[],
- int ePBC,
+ PbcType pbcType,
const matrix box,
const t_atom* atom,
const int* nAtom)
}
}
}
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
grp0 = 0;
grp1 = ncos - 1;
for (i = 0; i < ngrp[grp0]; i++)
}
static void do_dip(const t_topology* top,
- int ePBC,
+ PbcType pbcType,
real volume,
const char* fn,
const char* out_mtot,
gkrbin = mk_gkrbin(rcut, rcmax, bPhi, ndegrees);
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natom);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natom);
/* Start while loop over frames */
t0 = t;
if (bGkr)
{
- do_gkr(gkrbin, ncos, gnx, molindex, mols->index, x, dipole, ePBC, box, atom, gkatom);
+ do_gkr(gkrbin, ncos, gnx, molindex, mols->index, x, dipole, pbcType, box, atom, gkatom);
}
if (bTotal)
int npargs;
t_pargs* ppa;
t_topology* top;
- int ePBC;
+ PbcType pbcType;
int k, natoms;
matrix box;
}
snew(top, 1);
- ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top);
+ pbcType = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top);
snew(gnx, ncos);
snew(grpname, ncos);
}
nFF[0] = nFA;
nFF[1] = nFB;
- do_dip(top, ePBC, det(box), ftp2fn(efTRX, NFILE, fnm), opt2fn("-o", NFILE, fnm),
+ do_dip(top, pbcType, det(box), ftp2fn(efTRX, NFILE, fnm), opt2fn("-o", NFILE, fnm),
opt2fn("-eps", NFILE, fnm), opt2fn("-a", NFILE, fnm), opt2fn("-d", NFILE, fnm),
opt2fn_null("-cos", NFILE, fnm), opt2fn_null("-dip3d", NFILE, fnm),
opt2fn_null("-adip", NFILE, fnm), bPairs, corrtype[0], opt2fn("-c", NFILE, fnm), bGkr,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/force.h"
#include "gromacs/mdlib/mdatoms.h"
+#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/fcdata.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/rmpbc.h"
#include "gromacs/topology/index.h"
fprintf(fp, "\n");
}
-static void check_viol(FILE* log,
- t_ilist* disres,
- t_iparams forceparams[],
- rvec x[],
- rvec4 f[],
- t_pbc* pbc,
- t_graph* g,
- t_dr_result dr[],
- int clust_id,
- int isize,
- const int index[],
- real vvindex[],
- t_fcdata* fcd)
+static void check_viol(FILE* log,
+ const InteractionList& disres,
+ gmx::ArrayRef<const t_iparams> forceparams,
+ rvec x[],
+ rvec4 f[],
+ t_pbc* pbc,
+ t_dr_result dr[],
+ int clust_id,
+ int isize,
+ const int index[],
+ real vvindex[],
+ t_fcdata* fcd)
{
- t_iatom* forceatoms;
int i, j, nat, n, type, nviol, ndr, label;
real rt, mviol, tviol, viol, lam, dvdl, drt;
rvec* fshift;
{
reset5();
}
- forceatoms = disres->iatoms;
+ gmx::ArrayRef<const int> forceatoms = disres.iatoms;
for (j = 0; (j < isize); j++)
{
vvindex[j] = 0;
// The label for a distance restraint should be at most one larger
// than the previous label.
int label_old = forceparams[forceatoms[0]].disres.label;
- for (i = 0; (i < disres->nr); i += nat)
+ for (i = 0; (i < disres.size()); i += nat)
{
type = forceatoms[i];
label = forceparams[type].disres.label;
}
// Get offset for label index
label_old = forceparams[forceatoms[0]].disres.label;
- for (i = 0; (i < disres->nr);)
+ for (i = 0; (i < disres.size());)
{
type = forceatoms[i];
n = 0;
do
{
n += nat;
- } while (((i + n) < disres->nr)
+ } while (((i + n) < disres.size())
&& (forceparams[forceatoms[i + n]].disres.label == label + label_old));
calc_disres_R_6(nullptr, nullptr, n, &forceatoms[i], x, pbc, fcd, nullptr);
dr[clust_id].aver_6[ndr] += fcd->disres.Rt_6[label];
snew(fshift, SHIFTS);
- ta_disres(n, &forceatoms[i], forceparams, x, f, fshift, pbc, g, lam, &dvdl, nullptr, fcd, nullptr);
+ ta_disres(n, &forceatoms[i], forceparams.data(), x, f, fshift, pbc, lam, &dvdl, nullptr,
+ fcd, nullptr);
sfree(fshift);
viol = fcd->disres.sumviol;
if (bFirst)
{
- fprintf(stderr, "\nThere are %d restraints and %d pairs\n", ndr, disres->nr / nat);
+ fprintf(stderr, "\nThere are %d restraints and %d pairs\n", ndr, disres.size() / nat);
bFirst = FALSE;
}
if (ntop)
return bIC;
}
-static void dump_stats(FILE* log,
- int nsteps,
- const t_disresdata& dd,
- const t_ilist* disres,
- t_iparams ip[],
- t_dr_result* dr,
- int isize,
- int index[],
- t_atoms* atoms)
+static void dump_stats(FILE* log,
+ int nsteps,
+ const t_disresdata& dd,
+ const InteractionList& disres,
+ gmx::ArrayRef<const t_iparams> ip,
+ t_dr_result* dr,
+ int isize,
+ int index[],
+ t_atoms* atoms)
{
t_dr_stats* drs;
fprintf(log, "++++++++++++++ STATISTICS ++++++++++++++++++++++++\n");
snew(drs, dd.nres);
const int nra = interaction_function[F_DISRES].nratoms + 1;
- for (int j = 0; j < disres->nr; j += nra)
+ for (int j = 0; j < disres.size(); j += nra)
{
// Note that the restraint i can be used by multiple pairs
- const int i = disres->iatoms[j] - dd.type_min;
+ const int i = disres.iatoms[j] - dd.type_min;
GMX_RELEASE_ASSERT(i >= 0 && i < dd.nres, "The restraint index should be in range");
- drs[i].label = ip[disres->iatoms[j]].disres.label;
+ drs[i].label = ip[disres.iatoms[j]].disres.label;
drs[i].bCore = is_core(drs[i].label, isize, index);
- drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
+ drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
drs[i].r = dr->aver1[i] / nsteps;
drs[i].rT3 = gmx::invcbrt(dr->aver_3[i] / nsteps);
drs[i].rT6 = gmx::invsixthroot(dr->aver_6[i] / nsteps);
drs[i].violT6 = std::max(0.0, static_cast<double>(drs[i].rT6 - drs[i].up1));
if (atoms)
{
- int j1 = disres->iatoms[j + 1];
- int j2 = disres->iatoms[j + 2];
+ int j1 = disres.iatoms[j + 1];
+ int j2 = disres.iatoms[j + 2];
atoms->pdbinfo[j1].bfac += drs[i].violT3 * 5;
atoms->pdbinfo[j2].bfac += drs[i].violT3 * 5;
}
sfree(drs);
}
-static void dump_clust_stats(FILE* fp,
- const t_disresdata& dd,
- const t_ilist* disres,
- t_iparams ip[],
- t_blocka* clust,
- t_dr_result dr[],
- char* clust_name[],
- int isize,
- int index[])
+static void dump_clust_stats(FILE* fp,
+ const t_disresdata& dd,
+ const InteractionList& disres,
+ gmx::ArrayRef<const t_iparams> ip,
+ t_blocka* clust,
+ t_dr_result dr[],
+ char* clust_name[],
+ int isize,
+ int index[])
{
int k, nra, mmm = 0;
double sumV, maxV, sumVT3, sumVT6, maxVT3, maxVT6;
for (int j = 0; j < dd.nres; j += nra)
{
// Note that the restraint i can be used by multiple pairs
- const int i = disres->iatoms[j] - dd.type_min;
+ const int i = disres.iatoms[j] - dd.type_min;
if (restraintHasBeenProcessed[i])
{
continue;
}
- drs[i].label = ip[disres->iatoms[j]].disres.label;
+ drs[i].label = ip[disres.iatoms[j]].disres.label;
drs[i].bCore = is_core(drs[i].label, isize, index);
- drs[i].up1 = ip[disres->iatoms[j]].disres.up1;
+ drs[i].up1 = ip[disres.iatoms[j]].disres.up1;
drs[i].r = dr[k].aver1[i] / dr[k].nframes;
if ((dr[k].aver_3[i] <= 0) || !std::isfinite(dr[k].aver_3[i]))
{
dr->averv = 0;
}
-static void dump_disre_matrix(const char* fn,
- t_dr_result* dr,
- int ndr,
- int nsteps,
- t_idef* idef,
- const gmx_mtop_t* mtop,
- real max_dr,
- int nlevels,
- gmx_bool bThird)
+static void dump_disre_matrix(const char* fn,
+ t_dr_result* dr,
+ int ndr,
+ int nsteps,
+ const InteractionDefinitions& idef,
+ const gmx_mtop_t* mtop,
+ real max_dr,
+ int nlevels,
+ gmx_bool bThird)
{
FILE* fp;
int* resnr;
snew(matrix[i], n_res);
}
nratoms = interaction_function[F_DISRES].nratoms;
- nra = (idef->il[F_DISRES].nr / (nratoms + 1));
+ nra = (idef.il[F_DISRES].size() / (nratoms + 1));
snew(ptr, nra + 1);
index = 0;
nlabel = 0;
ptr[0] = 0;
snew(w_dr, ndr);
- for (i = 0; (i < idef->il[F_DISRES].nr); i += nratoms + 1)
+ for (i = 0; (i < idef.il[F_DISRES].size()); i += nratoms + 1)
{
- tp = idef->il[F_DISRES].iatoms[i];
- label = idef->iparams[tp].disres.label;
+ tp = idef.il[F_DISRES].iatoms[i];
+ label = idef.iparams[tp].disres.label;
if (label != index)
{
{
for (j = ptr[i]; (j < ptr[i + 1]); j += nratoms + 1)
{
- tp = idef->il[F_DISRES].iatoms[j];
- ai = idef->il[F_DISRES].iatoms[j + 1];
- aj = idef->il[F_DISRES].iatoms[j + 2];
+ tp = idef.il[F_DISRES].iatoms[j];
+ ai = idef.il[F_DISRES].iatoms[j + 1];
+ aj = idef.il[F_DISRES].iatoms[j + 2];
ri = resnr[ai];
rj = resnr[aj];
{
fprintf(debug, "DR %d, atoms %d, %d, distance %g\n", i, ai, aj, rav);
}
- rviol = std::max(0.0_real, rav - idef->iparams[tp].disres.up1);
+ rviol = std::max(0.0_real, rav - idef.iparams[tp].disres.up1);
matrix[ri][rj] += w_dr[i] * rviol;
matrix[rj][ri] += w_dr[i] * rviol;
hi = std::max(hi, matrix[ri][rj]);
"Use inverse third power averaging or linear for matrix output" }
};
- FILE *out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
- gmx_localtop_t top;
- t_fcdata fcd;
- t_graph* g;
- int i, j, kkk;
- t_trxstatus* status;
- real t;
- rvec * x, *xav = nullptr;
- rvec4* f;
- matrix box;
- gmx_bool bPDB;
- int isize;
- int * index = nullptr, *ind_fit = nullptr;
- char* grpname;
+ FILE * out = nullptr, *aver = nullptr, *numv = nullptr, *maxxv = nullptr, *xvg = nullptr;
+ t_fcdata fcd;
+ int i, j, kkk;
+ t_trxstatus* status;
+ real t;
+ rvec * x, *xav = nullptr;
+ rvec4* f;
+ matrix box;
+ gmx_bool bPDB;
+ int isize;
+ int * index = nullptr, *ind_fit = nullptr;
+ char* grpname;
t_cluster_ndx* clust = nullptr;
t_dr_result dr, *dr_clust = nullptr;
char** leg;
atoms->havePdbInfo = TRUE;
}
+ gmx_localtop_t top(topInfo.mtop()->ffparams);
gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
- g = nullptr;
pbc_null = nullptr;
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
- if (ir->bPeriodicMols)
- {
- pbc_null = &pbc;
- }
- else
- {
- g = mk_graph(fplog, &top.idef, 0, ntopatoms, FALSE, FALSE);
- }
+ pbc_null = &pbc;
}
if (ftp2bSet(efNDX, NFILE, fnm))
}
ir->dr_tau = 0.0;
- init_disres(fplog, topInfo.mtop(), ir, nullptr, nullptr, &fcd, nullptr, FALSE);
+ init_disres(fplog, topInfo.mtop(), ir, DisResRunMode::AnalysisTool, DDRole::Master,
+ NumRanks::Single, MPI_COMM_NULL, nullptr, &fcd, nullptr, FALSE);
int natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
snew(f, 5 * natoms);
auto mdAtoms = gmx::makeMDAtoms(fplog, *topInfo.mtop(), *ir, false);
atoms2md(topInfo.mtop(), ir, -1, nullptr, ntopatoms, mdAtoms.get());
update_mdatoms(mdAtoms->mdatoms(), ir->fepvals->init_lambda);
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
- gpbc = gmx_rmpbc_init(&top.idef, ir->ePBC, natoms);
+ gpbc = gmx_rmpbc_init(top.idef, ir->pbcType, natoms);
}
j = 0;
do
{
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
if (ir->bPeriodicMols)
{
- set_pbc(&pbc, ir->ePBC, box);
+ set_pbc(&pbc, ir->pbcType, box);
}
else
{
}
my_clust = clust->inv_clust[j];
range_check(my_clust, 0, clust->clust->nr);
- check_viol(fplog, &(top.idef.il[F_DISRES]), top.idef.iparams, x, f, pbc_null, g,
- dr_clust, my_clust, isize, index, vvindex, &fcd);
+ check_viol(fplog, top.idef.il[F_DISRES], top.idef.iparams, x, f, pbc_null, dr_clust,
+ my_clust, isize, index, vvindex, &fcd);
}
else
{
- check_viol(fplog, &(top.idef.il[F_DISRES]), top.idef.iparams, x, f, pbc_null, g, &dr, 0,
+ check_viol(fplog, top.idef.il[F_DISRES], top.idef.iparams, x, f, pbc_null, &dr, 0,
isize, index, vvindex, &fcd);
}
if (bPDB)
j++;
} while (read_next_x(oenv, status, &t, x, box));
close_trx(status);
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
gmx_rmpbc_done(gpbc);
}
if (clust)
{
- dump_clust_stats(fplog, fcd.disres, &(top.idef.il[F_DISRES]), top.idef.iparams,
- clust->clust, dr_clust, clust->grpname, isize, index);
+ dump_clust_stats(fplog, fcd.disres, top.idef.il[F_DISRES], top.idef.iparams, clust->clust,
+ dr_clust, clust->grpname, isize, index);
}
else
{
- dump_stats(fplog, j, fcd.disres, &(top.idef.il[F_DISRES]), top.idef.iparams, &dr, isize,
- index, bPDB ? atoms.get() : nullptr);
+ dump_stats(fplog, j, fcd.disres, top.idef.il[F_DISRES], top.idef.iparams, &dr, isize, index,
+ bPDB ? atoms.get() : nullptr);
if (bPDB)
{
write_sto_conf(opt2fn("-q", NFILE, fnm), "Coloured by average violation in Angstrom",
- atoms.get(), xav, nullptr, ir->ePBC, box);
+ atoms.get(), xav, nullptr, ir->pbcType, box);
}
- dump_disre_matrix(opt2fn_null("-x", NFILE, fnm), &dr, fcd.disres.nres, j, &top.idef,
+ dump_disre_matrix(opt2fn_null("-x", NFILE, fnm), &dr, fcd.disres.nres, j, top.idef,
topInfo.mtop(), max_dr, nlevels, bThird);
xvgrclose(out);
xvgrclose(aver);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
for (i = 0; (i < atoms->nr); i++)
{
- if (std::strcmp(*(atoms->atomname[i]), "OXT") == 0)
- {
- *atoms->atomname[i] = OOO;
- }
- else if (std::strcmp(*(atoms->atomname[i]), "O1") == 0)
- {
- *atoms->atomname[i] = OOO;
- }
- else if (std::strcmp(*(atoms->atomname[i]), "OC1") == 0)
+ if ((std::strcmp(*(atoms->atomname[i]), "OXT") == 0)
+ || (std::strcmp(*(atoms->atomname[i]), "O1") == 0)
+ || (std::strcmp(*(atoms->atomname[i]), "OC1") == 0))
{
*atoms->atomname[i] = OOO;
}
const char * fnSCount, *fnArea, *fnTArea, *fnAArea;
const char* leg[] = { "Phobic", "Phylic" };
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
t_matrix mat;
int nres, nr0, naccr, nres_plus_separators;
fnAArea = opt2fn_null("-aa", NFILE, fnm);
bDoAccSurf = ((fnArea != nullptr) || (fnTArea != nullptr) || (fnAArea != nullptr));
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xp, nullptr, box, FALSE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xp, nullptr, box, FALSE);
atoms = &(top.atoms);
check_oo(atoms);
bPhbres = bPhobics(atoms);
accr = nullptr;
naccr = 0;
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
do
{
t = output_env_conv_time(oenv, t);
}
gmx_rmpbc(gpbc, natoms, box, x);
tapein = gmx_ffopen(pdbfile, "w");
- write_pdbfile_indexed(tapein, nullptr, atoms, x, ePBC, box, ' ', -1, gnx, index, nullptr, FALSE);
+ write_pdbfile_indexed(tapein, nullptr, atoms, x, pbcType, box, ' ', -1, gnx, index, nullptr, FALSE);
gmx_ffclose(tapein);
/* strip_dssp returns the number of lines found in the dssp file, i.e.
* the number of residues plus the separator lines */
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/units.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/index.h"
#include "gromacs/topology/topology.h"
#include "gromacs/trajectory/trajectoryframe.h"
};
FILE * fp, *fplog;
t_topology top;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
t_trxframe fr;
matrix box;
int gnx;
please_cite(fplog, "Pascal2011a");
please_cite(fplog, "Caleman2011b");
- read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, nullptr, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &pbcType, nullptr, nullptr, box, TRUE);
/* Handle index groups */
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &grpNatoms, &index, &grpname);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int natoms;
/*we rely on PBC autodetection (...currently)*/
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
real * rvalues = nullptr, *kappa2values = nullptr, *rhist = nullptr, *khist = nullptr;
t_pbc* pbc = nullptr;
if (bPBCdist)
{
- set_pbc(pbc, ePBC, fr.box);
+ set_pbc(pbc, pbcType, fr.box);
pbc_dx(pbc, donpos, accpos, dist);
}
else
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
if (output_env_get_print_xvgr_codes(oenv))
{
char str1[STRLEN], str2[STRLEN];
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
sprintf(str1, "@ legend string ");
sprintf(str2, " ");
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/do_fit.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/rmpbc.h"
#include "gromacs/topology/index.h"
#include "gromacs/topology/topology.h"
const char * topfile, *lowfile, *highfile;
gmx_bool bTop = FALSE;
t_topology top;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
rvec* xtop;
matrix topbox, *box, boxf;
char* grpname;
}
if (topfile)
{
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, topbox, TRUE);
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, topbox, TRUE);
if (bTop)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, top.atoms.nr);
gmx_rmpbc(gpbc, top.atoms.nr, topbox, xtop);
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
FILE* out;
t_trxstatus* status;
t_topology top;
- int ePBC;
+ PbcType pbcType;
rvec * x, *x_s;
rvec xcm, gvec, gvec1;
matrix box, trans;
printf("Will print radius normalised by charge\n");
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x, nullptr, box, TRUE);
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
if (nmol > gnx || gnx % nmol != 0)
}
if (nz == 0)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
}
do
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real* slWidth,
int* nslices,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
int axis,
gmx_bool bMicel,
int micel[],
teller = 0;
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
/*********** Start processing trajectory ***********/
do
{
int ngx, /* nr. of atomsin sol group */
nmic = 0; /* nr. of atoms in micelle */
t_topology* top; /* topology */
- int ePBC;
+ PbcType pbcType;
int * index, /* indices for solvent group */
*micelle = nullptr;
gmx_bool bMicel = FALSE; /* think we're a micel */
}
bMicel = opt2bSet("-nm", NFILE, fnm);
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType); /* read topology file */
rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &ngx, &index, &grpname);
}
calc_h2order(ftp2fn(efTRX, NFILE, fnm), index, ngx, &slDipole, &slOrder, &slWidth, &nslices,
- top, ePBC, axis, bMicel, micelle, nmic, oenv);
+ top, pbcType, axis, bMicel, micelle, nmic, oenv);
h2order_plot(slDipole, slOrder, opt2fn("-o", NFILE, fnm), nslices, slWidth, oenv);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_fatal(FARGS, "Topology (%d atoms) does not match trajectory (%d atoms)", top.atoms.nr, natoms);
}
- bBox = (ir->ePBC != epbcNONE);
+ bBox = (ir->pbcType != PbcType::No);
grid = init_grid(bBox, box, (rcut > r2cut) ? rcut : r2cut, ngrid);
nabin = static_cast<int>(acut / abin);
nrbin = static_cast<int>(rcut / rbin);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int i, j, nall, nbb, nca, teller;
int * bbindex, *caindex, *allindex;
t_topology* top;
- int ePBC;
+ PbcType pbcType;
rvec * x, *xref;
real t;
real rms;
bRange = (opt2parg_bSet("-ahxstart", asize(pa), pa) && opt2parg_bSet("-ahxend", asize(pa), pa));
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType);
natoms = read_first_x(oenv, &status, opt2fn("-f", NFILE, fnm), &t, &x, box);
pr_bb(stdout, nres, bb);
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
teller = 0;
do
if (teller == 1)
{
write_sto_conf(opt2fn("-cz", NFILE, fnm), "Helix fitted to Z-Axis", &(top->atoms),
- x, nullptr, ePBC, box);
+ x, nullptr, pbcType, box);
}
xf[efhRAD].val = radius(xf[efhRAD].fp2, nca, caindex, x);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_pbc pbc;
matrix A;
- FILE *fpaxis, *fpcenter, *fptilt, *fprotation;
- FILE *fpradius, *fprise, *fptwist;
- FILE *fptheta1, *fptheta2, *fptheta3;
- FILE* fpbending;
- int ePBC;
+ FILE * fpaxis, *fpcenter, *fptilt, *fprotation;
+ FILE * fpradius, *fprise, *fptwist;
+ FILE * fptheta1, *fptheta2, *fptheta3;
+ FILE* fpbending;
+ PbcType pbcType;
gmx_output_env_t* oenv;
gmx_rmpbc_t gpbc = nullptr;
return 0;
}
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType);
for (i = 0; i < 3; i++)
{
unitaxes[1][1] = 1;
unitaxes[2][2] = 1;
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
do
{
/* initialisation for correct distance calculations */
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
/* make molecules whole again */
gmx_rmpbc(gpbc, natoms, box, x);
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/smalloc.h"
static void find_tetra_order_grid(t_topology top,
- int ePBC,
+ PbcType pbcType,
int natoms,
matrix box,
rvec x[],
snew(skmol, maxidx);
/* Must init pbc every step because of pressure coupling */
- set_pbc(&pbc, ePBC, box);
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ set_pbc(&pbc, pbcType, box);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
gmx_rmpbc(gpbc, natoms, box, x);
*sgmean = 0.0;
{
FILE * fpsg = nullptr, *fpsk = nullptr;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_trxstatus* status;
int natoms;
real t;
* i.e 1D Row-major order in (t,x,y) */
- read_tps_conf(fnTPS, &top, &ePBC, &xtop, nullptr, box, FALSE);
+ read_tps_conf(fnTPS, &top, &pbcType, &xtop, nullptr, box, FALSE);
*nslicex = static_cast<int>(box[XX][XX] / binw + onehalf); /*Calculate slicenr from binwidth*/
*nslicey = static_cast<int>(box[YY][YY] / binw + onehalf);
}
}
- find_tetra_order_grid(top, ePBC, natoms, box, x, isize[0], index[0], &sg, &sk, *nslicex,
+ find_tetra_order_grid(top, pbcType, natoms, box, x, isize[0], index[0], &sg, &sk, *nslicex,
*nslicey, nslicez, sg_grid, sk_grid);
GMX_RELEASE_ASSERT(sk_fravg != nullptr, "Trying to dereference NULL sk_fravg pointer");
for (i = 0; i < *nslicex; i++)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*to read topology file*/
t_topology top;
- int ePBC;
+ PbcType pbcType;
matrix topbox;
rvec* xtop;
gmx_bool bFit1;
read_eigenvectors(EigvecFile, &nav, &bFit1, &xref1, &edi_params.fitmas, &xav1,
&edi_params.pcamas, &nvec1, &eignr1, &eigvec1, &eigval1);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, topbox, false);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, topbox, false);
atoms = &top.atoms;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real trunc,
real** mdmat,
int** nmat,
- int ePBC,
+ PbcType pbcType,
matrix box)
{
int i, j, resi, resj;
t_pbc pbc;
rvec ddx;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
trunc2 = gmx::square(trunc);
for (resi = 0; (resi < nres); resi++)
{
FILE * out = nullptr, *fp;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms useatoms;
int isize;
int* index;
fprintf(stderr, "Will calculate number of different contacts\n");
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, FALSE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x, nullptr, box, FALSE);
fprintf(stderr, "Select group for analysis\n");
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
rhi.g = 0.0;
rhi.b = 0.0;
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, trxnat);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, trxnat);
if (bFrames)
{
{
gmx_rmpbc(gpbc, trxnat, box, x);
nframes++;
- calc_mat(nres, natoms, rndx, x, index, truncate, mdmat, nmat, ePBC, box);
+ calc_mat(nres, natoms, rndx, x, index, truncate, mdmat, nmat, pbcType, box);
for (i = 0; (i < nres); i++)
{
for (j = 0; (j < natoms); j++)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/smalloc.h"
-static void periodic_dist(int ePBC, matrix box, rvec x[], int n, const int index[], real* rmin, real* rmax, int* min_ind)
+static void
+periodic_dist(PbcType pbcType, matrix box, rvec x[], int n, const int index[], real* rmin, real* rmax, int* min_ind)
{
#define NSHIFT_MAX 26
int nsz, nshift, sx, sy, sz, i, j, s;
rvec shift[NSHIFT_MAX], d0, d;
sqr_box = std::min(norm2(box[XX]), norm2(box[YY]));
- if (ePBC == epbcXYZ)
+ if (pbcType == PbcType::Xyz)
{
sqr_box = std::min(sqr_box, norm2(box[ZZ]));
nsz = 1;
}
- else if (ePBC == epbcXY)
+ else if (pbcType == PbcType::XY)
{
nsz = 0;
}
else
{
- gmx_fatal(FARGS, "pbc = %s is not supported by g_mindist", epbc_names[ePBC]);
+ gmx_fatal(FARGS, "pbc = %s is not supported by g_mindist", c_pbcTypeNames[pbcType].c_str());
}
nshift = 0;
static void periodic_mindist_plot(const char* trxfn,
const char* outfn,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
int n,
int index[],
gmx_bool bSplit,
if (nullptr != top)
{
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
}
bFirst = TRUE;
gmx_rmpbc(gpbc, natoms, box, x);
}
- periodic_dist(ePBC, box, x, n, index, &rmin, &rmax, ind_min);
+ periodic_dist(pbcType, box, x, n, index, &rmin, &rmax, ind_min);
if (rmin < rmint)
{
rmint = rmin;
static void calc_dist(real rcut,
gmx_bool bPBC,
- int ePBC,
+ PbcType pbcType,
matrix box,
rvec x[],
int nx1,
/* Must init pbc every step because of pressure coupling */
if (bPBC)
{
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
}
if (index2)
{
int nres,
int* residue,
gmx_bool bPBC,
- int ePBC,
+ PbcType pbcType,
gmx_bool bGroup,
gmx_bool bEachResEachTime,
gmx_bool bPrintResName,
{
if (ng == 1)
{
- calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup,
+ calc_dist(rcut, bPBC, pbcType, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup,
&dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
fprintf(dist, " %12e", bMin ? dmin : dmax);
if (num)
{
for (k = i + 1; (k < ng); k++)
{
- calc_dist(rcut, bPBC, ePBC, box, x0, gnx[i], gnx[k], index[i], index[k],
+ calc_dist(rcut, bPBC, pbcType, box, x0, gnx[i], gnx[k], index[i], index[k],
bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
fprintf(dist, " %12e", bMin ? dmin : dmax);
if (num)
GMX_RELEASE_ASSERT(ng > 1, "Must have more than one group when not using -matrix");
for (i = 1; (i < ng); i++)
{
- calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup,
+ calc_dist(rcut, bPBC, pbcType, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup,
&dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2);
fprintf(dist, " %12e", bMin ? dmin : dmax);
if (num)
{
for (j = 0; j < nres; j++)
{
- calc_dist(rcut, bPBC, ePBC, box, x0, residue[j + 1] - residue[j], gnx[i],
+ calc_dist(rcut, bPBC, pbcType, box, x0, residue[j + 1] - residue[j], gnx[i],
&(index[0][residue[j]]), index[i], bGroup, &dmin, &dmax, &nmin,
&nmax, &min1r, &min2r, &max1r, &max2r);
mindres[i - 1][j] = std::min(mindres[i - 1][j], dmin);
{ "-printresname", FALSE, etBOOL, { &bPrintResName }, "Write residue names" }
};
gmx_output_env_t* oenv;
- t_topology* top = nullptr;
- int ePBC = -1;
- rvec* x = nullptr;
+ t_topology* top = nullptr;
+ PbcType pbcType = PbcType::Unset;
+ rvec* x = nullptr;
matrix box;
gmx_bool bTop = FALSE;
if (tpsfnm || resfnm || !ndxfnm)
{
snew(top, 1);
- bTop = read_tps_conf(tpsfnm, top, &ePBC, &x, nullptr, box, FALSE);
+ bTop = read_tps_conf(tpsfnm, top, &pbcType, &x, nullptr, box, FALSE);
if (bPI && !bTop)
{
printf("\nWARNING: Without a run input file a trajectory with broken molecules will "
if (bPI)
{
- periodic_mindist_plot(trxfnm, distfnm, top, ePBC, gnx[0], index[0], bSplit, oenv);
+ periodic_mindist_plot(trxfnm, distfnm, top, pbcType, gnx[0], index[0], bSplit, oenv);
}
else
{
dist_plot(trxfnm, atmfnm, distfnm, numfnm, resfnm, oxfnm, rcutoff, bMat,
top ? &(top->atoms) : nullptr, ng, index, gnx, grpname, bSplit, !bMax, nres,
- residues, bPBC, ePBC, bGroup, bEachResEachTime, bPrintResName, oenv);
+ residues, bPBC, pbcType, bGroup, bEachResEachTime, bPrintResName, oenv);
}
do_view(oenv, distfnm, "-nxy");
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const int* molindex,
const t_topology* top,
rvec* x,
- int ePBC,
+ PbcType pbcType,
matrix box,
const gmx_output_env_t* oenv)
{
{
pdbinfo[i].bfac *= scale;
}
- write_sto_conf(fn_pdb, "molecular MSD", &top->atoms, x, nullptr, ePBC, box);
+ write_sto_conf(fn_pdb, "molecular MSD", &top->atoms, x, nullptr, pbcType, box);
}
}
static int corr_loop(t_corr* curr,
const char* fn,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
gmx_bool bMol,
int gnx[],
int* index[],
if (bMol)
{
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
}
/* the loop over all frames */
real t_pdb,
int nrgrp,
t_topology* top,
- int ePBC,
+ PbcType pbcType,
gmx_bool bTen,
gmx_bool bMW,
gmx_bool bRmCOMM,
msd = std::make_unique<t_corr>(nrgrp, type, axis, dim_factor, mol_file == nullptr ? 0 : gnx[0],
bTen, bMW, dt, top, beginfit, endfit);
- nat_trx = corr_loop(msd.get(), trx_file, top, ePBC, mol_file ? gnx[0] != 0 : false, gnx.data(),
+ nat_trx = corr_loop(msd.get(), trx_file, top, pbcType, mol_file ? gnx[0] != 0 : false, gnx.data(),
index, (mol_file != nullptr) ? calc1_mol : (bMW ? calc1_mw : calc1_norm),
bTen, gnx_com, index_com, dt, t_pdb, pdb_file ? &x : nullptr, box, oenv);
{
snew(top->atoms.pdbinfo, top->atoms.nr);
}
- printmol(msd.get(), mol_file, pdb_file, index[0], top, x, ePBC, box, oenv);
+ printmol(msd.get(), mol_file, pdb_file, index[0], top, x, pbcType, box, oenv);
top->atoms.nr = i;
}
#define NFILE asize(fnm)
t_topology top;
- int ePBC;
+ PbcType pbcType;
matrix box;
const char * trx_file, *tps_file, *ndx_file, *msd_file, *mol_file, *pdb_file;
rvec* xdum;
gmx_fatal(FARGS, "Can only calculate the full tensor for 3D msd");
}
- bTop = read_tps_conf(tps_file, &top, &ePBC, &xdum, nullptr, box, bMW || bRmCOMM);
+ bTop = read_tps_conf(tps_file, &top, &pbcType, &xdum, nullptr, box, bMW || bRmCOMM);
if (mol_file && !bTop)
{
gmx_fatal(FARGS, "Could not read a topology from %s. Try a tpr file instead.", tps_file);
}
- do_corr(trx_file, ndx_file, msd_file, mol_file, pdb_file, t_pdb, ngroup, &top, ePBC, bTen, bMW,
- bRmCOMM, type, dim_factor, axis, dt, beginfit, endfit, oenv);
+ do_corr(trx_file, ndx_file, msd_file, mol_file, pdb_file, t_pdb, ngroup, &top, pbcType, bTen,
+ bMW, bRmCOMM, type, dim_factor, axis, dt, beginfit, endfit, oenv);
done_top(&top);
view_all(oenv, NFILE, fnm);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_trxstatus* out;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
rvec * xtop, *xref, *xav, *xout1, *xout2;
gmx_bool bDMR, bDMA, bFit;
read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit, &xref, &bDMR, &xav, &bDMA, &nvec,
&eignr, &eigvec, &eigval);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, box, bDMA);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, box, bDMA);
atoms = &top.atoms;
printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n", natoms);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
static int get_bounds(real** bounds, int** index, int** dr_pair, int* npairs, gmx_localtop_t* top)
{
- t_functype* functype;
- t_iparams* ip;
- int i, j, k, type, ftype, natom;
- t_ilist* disres;
- t_iatom* iatom;
- real* b;
- int * ind, *pair;
- int nb, label1;
-
- functype = top->idef.functype;
- ip = top->idef.iparams;
+ int i, j, k, type, ftype, natom;
+ real* b;
+ int * ind, *pair;
+ int nb, label1;
+
+ gmx::ArrayRef<const t_functype> functype = top->idef.functype;
+ gmx::ArrayRef<const t_iparams> iparams = top->idef.iparams;
/* Count how many distance restraint there are... */
- nb = top->idef.il[F_DISRES].nr;
+ nb = top->idef.il[F_DISRES].size();
if (nb == 0)
{
gmx_fatal(FARGS, "No distance restraints in topology!\n");
/* Fill the bound array */
nb = 0;
- for (i = 0; (i < top->idef.ntypes); i++)
+ for (gmx::index i = 0; i < functype.ssize(); i++)
{
ftype = functype[i];
if (ftype == F_DISRES)
{
- label1 = ip[i].disres.label;
- b[nb] = ip[i].disres.up1;
+ label1 = iparams[i].disres.label;
+ b[nb] = iparams[i].disres.up1;
ind[nb] = label1;
nb++;
}
*bounds = b;
/* Fill the index array */
- label1 = -1;
- disres = &(top->idef.il[F_DISRES]);
- iatom = disres->iatoms;
- for (i = j = k = 0; (i < disres->nr);)
+ label1 = -1;
+ const InteractionList& disres = top->idef.il[F_DISRES];
+ gmx::ArrayRef<const int> iatom = disres.iatoms;
+ for (i = j = k = 0; (i < disres.size());)
{
type = iatom[i];
- ftype = top->idef.functype[type];
+ ftype = functype[type];
natom = interaction_function[ftype].nratoms + 1;
- if (label1 != top->idef.iparams[type].disres.label)
+ if (label1 != iparams[type].disres.label)
{
pair[j] = k;
- label1 = top->idef.iparams[type].disres.label;
+ label1 = iparams[type].disres.label;
j++;
}
k++;
FILE /* *out = NULL,*/ *out_disre = nullptr, *fp_pairs = nullptr, *fort = nullptr,
*fodt = nullptr, *foten = nullptr;
- ener_file_t fp;
- int timecheck = 0;
- gmx_localtop_t top;
- gmx_enxnm_t* enm = nullptr;
- t_enxframe fr;
- int nre, teller, teller_disre;
- int nor = 0, nex = 0, norfr = 0, enx_i = 0;
+ ener_file_t fp;
+ int timecheck = 0;
+ gmx_enxnm_t* enm = nullptr;
+ t_enxframe fr;
+ int nre, teller, teller_disre;
+ int nor = 0, nex = 0, norfr = 0, enx_i = 0;
real *bounds = nullptr, *violaver = nullptr, *oobs = nullptr, *orient = nullptr, *odrms = nullptr;
int * index = nullptr, *pair = nullptr, norsel = 0, *orsel = nullptr, *or_label = nullptr;
int nbounds = 0, npairs;
t_inputrec irInstance;
t_inputrec* ir = &irInstance;
init_enxframe(&fr);
- gmx::TopologyInformation topInfo;
+ gmx::TopologyInformation topInfo;
+ std::unique_ptr<gmx_localtop_t> top;
if (!bDisRe)
{
if (bORIRE || bOTEN)
{
{
topInfo.fillFromInputFile(ftp2fn(efTPR, NFILE, fnm));
- gmx_mtop_generate_local_top(*topInfo.mtop(), &top, ir->efep != efepNO);
+ top = std::make_unique<gmx_localtop_t>(topInfo.mtop()->ffparams);
+ gmx_mtop_generate_local_top(*topInfo.mtop(), top.get(), ir->efep != efepNO);
}
- nbounds = get_bounds(&bounds, &index, &pair, &npairs, &top);
+ nbounds = get_bounds(&bounds, &index, &pair, &npairs, top.get());
snew(violaver, npairs);
out_disre = xvgropen(opt2fn("-o", NFILE, fnm), "Sum of Violations", "Time (ps)", "nm", oenv);
xvgr_legend(out_disre, 2, drleg, oenv);
blk_disre = find_block_id_enxframe(&fr, enxDISRE, nullptr);
if (bDisRe && bDRAll && !leg && blk_disre)
{
- t_iatom* fa;
- t_iparams* ip;
-
- fa = top.idef.il[F_DISRES].iatoms;
- ip = top.idef.iparams;
+ const InteractionList& ilist = top->idef.il[F_DISRES];
+ gmx::ArrayRef<const int> fa = ilist.iatoms;
+ const t_iparams* ip = top->idef.iparams.data();
if (blk_disre->nsub != 2 || (blk_disre->sub[0].nr != blk_disre->sub[1].nr))
{
gmx_incons("Number of disre sub-blocks not equal to 2");
}
ndisre = blk_disre->sub[0].nr;
- if (ndisre != top.idef.il[F_DISRES].nr / 3)
+ if (ndisre != ilist.size() / 3)
{
gmx_fatal(FARGS,
"Number of disre pairs in the energy file (%d) does not match the "
"number in the run input file (%d)\n",
- ndisre, top.idef.il[F_DISRES].nr / 3);
+ ndisre, ilist.size() / 3);
}
snew(pairleg, ndisre);
int molb = 0;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_trxstatus* out;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
rvec * xtop, *xref, *xav, *xout;
int nvec, *eignr = nullptr;
read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit, &xref, &bDMR, &xav, &bDMA, &nvec,
&eignr, &eigvec, &eigval);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, box, bDMA);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, box, bDMA);
/* Find vectors and phases */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* P.J. van Maaren, November 2005 Added tetrahedral stuff */
/****************************************************************************/
-static void find_nearest_neighbours(int ePBC,
+static void find_nearest_neighbours(PbcType pbcType,
int natoms,
matrix box,
rvec x[],
snew(skmol, maxidx);
/* Must init pbc every step because of pressure coupling */
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
gmx_rmpbc(gpbc, natoms, box, x);
{
FILE * fpsg = nullptr, *fpsk = nullptr;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_trxstatus* status;
int natoms;
real t;
gmx_rmpbc_t gpbc = nullptr;
- read_tps_conf(fnTPS, &top, &ePBC, &xtop, nullptr, box, FALSE);
+ read_tps_conf(fnTPS, &top, &pbcType, &xtop, nullptr, box, FALSE);
snew(sg_slice, nslice);
snew(sk_slice, nslice);
fpsk = xvgropen(skfn, "S\\sk\\N Distance Order Parameter", "Time (ps)", "S\\sk\\N", oenv);
/* loop over frames */
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
nframes = 0;
do
{
- find_nearest_neighbours(ePBC, natoms, box, x, isize[0], index[0], &sg, &sk, nslice,
+ find_nearest_neighbours(pbcType, natoms, box, x, isize[0], index[0], &sg, &sk, nslice,
slice_dim, sg_slice, sk_slice, gpbc);
for (i = 0; (i < nslice); i++)
{
gmx_bool bSliced,
gmx_bool bUnsat,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
int ngrps,
int axis,
gmx_bool permolecule,
teller = 0;
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
/*********** Start processing trajectory ***********/
do
{
}
teller++;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
gmx_rmpbc_copy(gpbc, natoms, box, x0, x1);
/* Now loop over all groups. There are ngrps groups, the order parameter can
}
write_sto_conf(opt2fn("-ob", nfile, fnm), "Order parameters", &useatoms, frout.x, nullptr,
- frout.ePBC, frout.box);
+ frout.pbcType, frout.box);
sfree(frout.x);
done_atom(&useatoms);
char** grpname; /* groupnames */
int ngrps, /* nr. of groups */
i, axis = 0; /* normal axis */
- t_topology* top; /* topology */
- int ePBC;
- int * index, /* indices for a */
- *a; /* atom numbers in each group */
- t_blocka* block; /* data from index file */
+ t_topology* top; /* topology */
+ PbcType pbcType; /* type of periodic boundary conditions */
+ int * index, /* indices for a */
+ *a; /* atom numbers in each group */
+ t_blocka* block; /* data from index file */
t_filenm fnm[] = {
/* files for g_order */
{ efTRX, "-f", nullptr, ffREAD }, /* trajectory file */
fprintf(stderr, "Taking carbons as unsaturated!\n");
}
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType); /* read topology file */
block = init_index(ftp2fn(efNDX, NFILE, fnm), &grpname);
index = block->index; /* get indices from t_block block */
print_types(index, a, ngrps, grpname, top);
calc_order(ftp2fn(efTRX, NFILE, fnm), index, a, &order, &slOrder, &slWidth, nslices,
- bSliced, bUnsat, top, ePBC, ngrps, axis, permolecule, radial, distcalc,
+ bSliced, bUnsat, top, pbcType, ngrps, axis, permolecule, radial, distcalc,
opt2fn_null("-nr", NFILE, fnm), &distvals, oenv);
if (radial)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_topology* top;
gmx_output_env_t* oenv;
- int ePBC;
+ PbcType pbcType;
int isize, *index, nmol, *molind, mol, nat_min = 0, nat_max = 0;
char* grpname;
t_trxstatus* status;
}
snew(top, 1);
- ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top);
+ pbcType = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top);
fprintf(stderr, "Select a group of polymer mainchain atoms:\n");
get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
sum_gyro_tot = 0;
sum_pers_tot = 0;
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
do
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
double*** slField,
int* nslices,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
int axis,
int nr_grps,
double* slWidth,
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
/*********** Start processing trajectory ***********/
do
char** grpname; /* groupnames */
int* ngx; /* sizes of groups */
t_topology* top; /* topology */
- int ePBC;
+ PbcType pbcType;
int** index; /* indices for all groups */
t_filenm fnm[] = {
/* files for g_order */
/* Calculate axis */
axis = toupper(axtitle[0]) - 'X';
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); /* read topology file */
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType); /* read topology file */
snew(grpname, ngrps);
snew(index, ngrps);
calc_potential(ftp2fn(efTRX, NFILE, fnm), index, ngx, &potential, &charge, &field, &nslices,
- top, ePBC, axis, ngrps, &slWidth, fudge_z, bSpherical, bCorrect, oenv);
+ top, pbcType, axis, ngrps, &slWidth, fudge_z, bSpherical, bCorrect, oenv);
plot_potential(potential, charge, field, opt2fn("-o", NFILE, fnm), opt2fn("-oc", NFILE, fnm),
opt2fn("-of", NFILE, fnm), nslices, ngrps, grpname, slWidth, oenv);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_pargs pa[] = { { "-foo", FALSE, etBOOL, { &foo }, "Dummy option to avoid empty array" } };
t_trxstatus* status;
t_topology top;
- int ePBC;
+ PbcType pbcType;
real t;
rvec* x;
}
sfree(legend);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, nullptr, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, nullptr, nullptr, box, TRUE);
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
do
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_bool bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass;
gmx_bool bFit, bReset;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_iatom* iatom = nullptr;
matrix box = { { 0 } };
}
}
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xp, nullptr, box, TRUE);
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xp, nullptr, box, TRUE);
snew(w_rls, top.atoms.nr);
snew(w_rms, top.atoms.nr);
/* Prepare reference frame */
if (bPBC)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, top.atoms.nr);
gmx_rmpbc(gpbc, top.atoms.nr, box, xp);
}
if (bReset)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/strdb.h"
-static void calc_dist(int nind, const int index[], const rvec x[], int ePBC, matrix box, real** d)
+static void calc_dist(int nind, const int index[], const rvec x[], PbcType pbcType, matrix box, real** d)
{
int i, j;
rvec dx;
real temp2;
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (i = 0; (i < nind - 1); i++)
{
const real* xi = x[index[i]];
static void calc_dist_tot(int nind,
const int index[],
rvec x[],
- int ePBC,
+ PbcType pbcType,
matrix box,
real** d,
real** dtot,
rvec dx;
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (i = 0; (i < nind - 1); i++)
{
xi = x[index[i]];
real t;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
matrix box;
rvec* x;
}
/* get topology and index */
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, FALSE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x, nullptr, box, FALSE);
if (!bPBC)
{
- ePBC = epbcNONE;
+ pbcType = PbcType::No;
}
atoms = &(top.atoms);
}
/*set box type*/
- calc_dist(isize, index, x, ePBC, box, d_r);
+ calc_dist(isize, index, x, pbcType, box, d_r);
sfree(x);
/*open output files*/
do
{
- calc_dist_tot(isize, index, x, ePBC, box, d, dtot, dtot2, bNMR, dtot1_3, dtot1_6);
+ calc_dist_tot(isize, index, x, pbcType, box, d, dtot, dtot2, bNMR, dtot1_3, dtot1_6);
rmsnow = rms_diff(isize, d, d_r);
fprintf(fp, "%g %g\n", t, rmsnow);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real t, *w_rls;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms * pdbatoms, *refatoms;
matrix box, pdbbox;
devfn = opt2fn_null("-od", NFILE, fnm);
dirfn = opt2fn_null("-dir", NFILE, fnm);
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xref, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xref, nullptr, box, TRUE);
const char* title = *top.name;
snew(w_rls, top.atoms.nr);
if (bFit)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natom);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natom);
}
/* Now read the trj again to compute fluctuations */
{
rvec_inc(pdbx[index[i]], xcm);
}
- write_sto_conf_indexed(opt2fn("-oq", NFILE, fnm), title, pdbatoms, pdbx, nullptr, ePBC,
+ write_sto_conf_indexed(opt2fn("-oq", NFILE, fnm), title, pdbatoms, pdbx, nullptr, pbcType,
pdbbox, isize, index);
}
if (opt2bSet("-ox", NFILE, fnm))
}
}
/* Write a .pdb file with B-factors and optionally anisou records */
- write_sto_conf_indexed(opt2fn("-ox", NFILE, fnm), title, pdbatoms, bFactorX, nullptr, ePBC,
- pdbbox, isize, index);
+ write_sto_conf_indexed(opt2fn("-ox", NFILE, fnm), title, pdbatoms, bFactorX, nullptr,
+ pbcType, pdbbox, isize, index);
sfree(bFactorX);
}
if (bAniso)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real t, t0, t1, dt;
gmx_rmpbc_t gpbc = nullptr;
t_topology* top;
- int ePBC;
+ PbcType pbcType;
t_filenm fnm[] = { { efTRX, "-f", nullptr, ffREAD },
{ efTPR, nullptr, nullptr, ffREAD },
{ efNDX, nullptr, nullptr, ffREAD },
"these can not be atom doublets\n");
}
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType);
snew(c1, nvec);
for (i = 0; (i < nvec); i++)
natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
snew(x_s, natoms);
- gpbc = gmx_rmpbc_init(&(top->idef), ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&(top->idef), pbcType, natoms);
/* Start the loop over frames */
t0 = t;
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2009-2017, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int* index,
gmx_bool bMW,
const t_topology* top,
- int ePBC,
+ PbcType pbcType,
rvec* x_ref)
{
int natoms, nfr_all, nfr, i, j, a, r, c, min_fr;
w_rls[a] = (bMW ? top->atoms.atom[index[a]].m : 1.0);
tot_mass += w_rls[a];
}
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, natoms);
do
{
FILE* out;
t_trxstatus* status;
t_topology top;
- int ePBC;
+ PbcType pbcType;
rvec * x_ref, *x;
matrix box, R;
real t;
return 0;
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x_ref, nullptr, box, bMW);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x_ref, nullptr, box, bMW);
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, top.atoms.nr);
gmx_rmpbc(gpbc, top.atoms.nr, box, x_ref);
if (reffit[0][0] != 'n')
{
get_refx(oenv, ftp2fn(efTRX, NFILE, fnm), reffit[0][2] == 'z' ? 3 : 2, skip, gnx, index,
- bMW, &top, ePBC, x_ref);
+ bMW, &top, pbcType, x_ref);
}
natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int nset[3] = { 0, 0, 0 };
t_topology* top;
- int ePBC;
+ PbcType pbcType;
char* buf;
t_trxstatus* status;
int i, j, k, m, nnn, teller, ncg;
return 0;
}
- top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);
+ top = read_top(ftp2fn(efTPR, NFILE, fnm), &pbcType);
cg = mk_charge(&top->atoms, &ncg);
snew(cgdist, ncg);
snew(nWithin, ncg);
srenew(time, teller + 1);
time[teller] = t;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
for (i = 0; (i < ncg); i++)
{
}
else
{
- if (output_env_get_xvg_format(oenv) == exvgXMGR)
+ if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgr)
{
fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf);
}
- else if (output_env_get_xvg_format(oenv) == exvgXMGRACE)
+ else if (output_env_get_xvg_format(oenv) == XvgFormat::Xmgrace)
{
fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gmxana/gstat.h"
#include "gromacs/gmxana/nsfactor.h"
#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/rmpbc.h"
#include "gromacs/topology/index.h"
#include "gromacs/topology/topology.h"
t_topology* top = nullptr;
gmx_rmpbc_t gpbc = nullptr;
gmx_bool bFFT = FALSE, bDEBYE = FALSE;
- gmx_bool bMC = FALSE;
- int ePBC = -1;
+ gmx_bool bMC = FALSE;
+ PbcType pbcType = PbcType::Unset;
matrix box;
rvec* x;
int natoms;
snew(grpname, 1);
snew(index, 1);
- read_tps_conf(fnTPX, top, &ePBC, &x, nullptr, box, TRUE);
+ read_tps_conf(fnTPX, top, &pbcType, &x, nullptr, box, TRUE);
printf("\nPlease select group for SANS spectra calculation:\n");
get_index(&(top->atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, grpname);
/* Prepare reference frame */
if (bPBC)
{
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, top->atoms.nr);
gmx_rmpbc(gpbc, top->atoms.nr, box, x);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int gmx_sorient(int argc, char* argv[])
{
t_topology top;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
t_trxstatus* status;
int natoms;
real t;
bTPS = (opt2bSet("-s", NFILE, fnm) || !opt2bSet("-n", NFILE, fnm) || bCom);
if (bTPS)
{
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, box, bCom);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, box, bCom);
}
/* get index groups */
rmin2 = gmx::square(rmin);
rmax2 = gmx::square(rmax);
- rcut = 0.99 * std::sqrt(max_cutoff2(guess_ePBC(box), box));
+ rcut = 0.99 * std::sqrt(max_cutoff2(guessPbcType(box), box));
if (rcut == 0)
{
rcut = 10 * rmax;
if (bTPS)
{
/* make molecules whole again */
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
}
/* start analysis of trajectory */
do
gmx_rmpbc(gpbc, natoms, box, x);
}
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
n = 0;
inp = 0;
for (p = 0; (p < nrefgrp); p++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2007,2008,2009,2010,2011 by the GROMACS development team.
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
double MINBIN[3];
double MAXBIN[3];
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_trxframe fr;
rvec* xtop;
matrix box, box_pbc;
return 0;
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, box, TRUE);
sfree(xtop);
atoms = &(top.atoms);
if (bPBC)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
}
/* This is the main loop over frames */
do
if (bPBC)
{
gmx_rmpbc_trxfr(gpbc, &fr);
- set_pbc(&pbc, ePBC, box_pbc);
+ set_pbc(&pbc, pbcType, box_pbc);
}
for (i = 0; i < nidx; i++)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
-static void calc_com_pbc(int nrefat, const t_topology* top, rvec x[], t_pbc* pbc, const int index[], rvec xref, int ePBC)
+static void calc_com_pbc(int nrefat, const t_topology* top, rvec x[], t_pbc* pbc, const int index[], rvec xref, PbcType pbcType)
{
const real tol = 1e-4;
gmx_bool bChanged;
}
svmul(1 / mtot, xref, xref);
/* Now check if any atom is more than half the box from the COM */
- if (ePBC != epbcNONE)
+ if (pbcType != PbcType::No)
{
iter = 0;
do
}
snew(top, 1);
- // TODO: Only ePBC is used, not the full inputrec.
+ // TODO: Only pbcType is used, not the full inputrec.
t_inputrec irInstance;
t_inputrec* ir = &irInstance;
read_tpx_top(ftp2fn(efTPR, NFILE, fnm), ir, box, &natoms, nullptr, nullptr, top);
/* initialize reading trajectory: */
natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
- rcut = 0.99 * std::sqrt(max_cutoff2(ir->ePBC, box));
+ rcut = 0.99 * std::sqrt(max_cutoff2(ir->pbcType, box));
if (rcut == 0)
{
rcut = 10 * rmax;
molindex = top->mols.index;
atom = top->atoms.atom;
- gpbc = gmx_rmpbc_init(&top->idef, ir->ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top->idef, ir->pbcType, natoms);
/* start analysis of trajectory */
do
/* make molecules whole again */
gmx_rmpbc(gpbc, natoms, box, x);
- set_pbc(&pbc, ir->ePBC, box);
+ set_pbc(&pbc, ir->pbcType, box);
if (bCom)
{
- calc_com_pbc(nrefat, top, x, &pbc, index[0], xref, ir->ePBC);
+ calc_com_pbc(nrefat, top, x, &pbc, index[0], xref, ir->pbcType);
}
for (m = 0; m < isize[1]; m++)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
};
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_trxframe fr;
matrix box;
gmx_bool bTop;
return 0;
}
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, nullptr, nullptr, box, TRUE);
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, nullptr, nullptr, box, TRUE);
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
if (bMol)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const char* xname,
const char* title,
t_atoms* atoms,
- int ePBC,
+ PbcType pbcType,
matrix box,
int isize,
int* index,
atoms->pdbinfo[index[i]].bfac = sum[index[i]][onedim] * scale;
}
}
- write_sto_conf_indexed(fname, title, atoms, x, nullptr, ePBC, box, isize, index);
+ write_sto_conf_indexed(fname, title, atoms, x, nullptr, pbcType, box, isize, index);
}
}
FILE * outx = nullptr, *outv = nullptr, *outf = nullptr, *outb = nullptr, *outt = nullptr;
FILE * outekt = nullptr, *outekr = nullptr;
t_topology top;
- int ePBC;
+ PbcType pbcType;
real * mass, time;
const char* indexfn;
t_trxframe fr;
}
std::string sffmt6 = gmx::formatString("%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, topbox,
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, topbox,
bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR));
sfree(xtop);
if ((bMol || bCV || bCF) && !bTop)
if (bCom && bPBC)
{
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, fr.natoms);
}
do
{
if (nr_xfr > 1)
{
- if (ePBC != epbcNONE && !bNoJump)
+ if (pbcType != PbcType::No && !bNoJump)
{
fprintf(stderr,
"\nWARNING: More than one frame was used for option -cv or -cf\n"
if (bCV)
{
write_pdb_bfac(opt2fn("-cv", NFILE, fnm), opt2fn("-av", NFILE, fnm), "average velocity",
- &(top.atoms), ePBC, topbox, isize[0], index[0], nr_xfr, sumx, nr_vfr, sumv,
- bDim, scale, oenv);
+ &(top.atoms), pbcType, topbox, isize[0], index[0], nr_xfr, sumx, nr_vfr,
+ sumv, bDim, scale, oenv);
}
if (bCF)
{
write_pdb_bfac(opt2fn("-cf", NFILE, fnm), opt2fn("-af", NFILE, fnm), "average force",
- &(top.atoms), ePBC, topbox, isize[0], index[0], nr_xfr, sumx, nr_ffr, sumf,
- bDim, scale, oenv);
+ &(top.atoms), pbcType, topbox, isize[0], index[0], nr_xfr, sumx, nr_ffr,
+ sumf, bDim, scale, oenv);
}
/* view it */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_trxstatus* status;
gmx_bool bNShell, bPDBout;
t_topology top;
- int ePBC;
+ PbcType pbcType;
rvec * x, *xsol, xcom, dx;
matrix box;
t_pbc pbc;
return 0;
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, TRUE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &x, nullptr, box, TRUE);
sfree(x);
/* get index groups */
}
out = open_trx(opt2fn("-o", NFILE, fnm), "w");
}
- gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
+ gpbc = gmx_rmpbc_init(&top.idef, pbcType, natoms);
do
{
gmx_rmpbc(gpbc, natoms, box, x);
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
if (ref_a == -1)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_output_env_t* oenv;
const char * matfile, *otfile, *orfile;
t_topology top;
- int ePBC;
+ PbcType pbcType;
matrix boxtop, box, *sbox, avbox, corr;
rvec * xtop, *x, **sx;
int isize, nalloc, nallocn;
exit(0);
}
- read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, nullptr, boxtop, FALSE);
+ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, &xtop, nullptr, boxtop, FALSE);
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
nalloc = 0;
fprintf(stderr, "\rProcessing frame %d", f);
fflush(stderr);
}
- if (ePBC != epbcNONE)
+ if (pbcType != PbcType::No)
{
/* Scale all the configuration to the average box */
gmx::invertBoxMatrix(sbox[f], corr);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/units.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/index.h"
#include "gromacs/topology/topology.h"
#include "gromacs/trajectory/trajectoryframe.h"
};
t_topology top;
- int ePBC = -1;
+ PbcType pbcType = PbcType::Unset;
t_trxframe fr;
matrix box;
gmx_bool bTPS = FALSE, bTop = FALSE;
if (bTPS)
{
- bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, nullptr, nullptr, box, TRUE);
+ bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &pbcType, nullptr, nullptr, box, TRUE);
get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);
}
else
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_dih* dd;
gmx_rmpbc_t gpbc = nullptr;
- gpbc = gmx_rmpbc_init(xr->idef, xr->ePBC, xr->natoms);
+ gpbc = gmx_rmpbc_init(xr->idef, xr->pbcType, xr->natoms);
gmx_rmpbc(gpbc, xr->natoms, xr->box, xr->x);
gmx_rmpbc_done(gpbc);
t_topology* top;
real t;
- top = read_top(topfile, &xr->ePBC);
+ top = read_top(topfile, &xr->pbcType);
/*get_dih2(xr,top->idef.functype,&(top->idef.bondeds),&(top->atoms));*/
get_dih(xr, &(top->atoms));
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
rvec* x;
matrix box;
t_idef* idef;
- int ePBC;
+ PbcType pbcType;
gmx_output_env_t* oenv;
} t_xrama;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
char** grpname;
int** index;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_trxframe fr;
reduced_atom_t** red;
structure_factor* sf;
sf->energy = energy;
/* Read the topology informations */
- read_tps_conf(fnTPS, &top, &ePBC, &xtop, nullptr, box, TRUE);
+ read_tps_conf(fnTPS, &top, &pbcType, &xtop, nullptr, box, TRUE);
sfree(xtop);
/* groups stuff... */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
set(exename gmxana-test)
-
-gmx_add_gtest_executable(
- ${exename}
- entropy.cpp
- gmx_traj.cpp
- gmx_mindist.cpp
- gmx_msd.cpp
- )
-gmx_register_gtest_test(GmxAnaTest ${exename} INTEGRATION_TEST)
+gmx_add_gtest_executable(${exename}
+ CPP_SOURCE_FILES
+ entropy.cpp
+ gmx_traj.cpp
+ gmx_mindist.cpp
+ gmx_msd.cpp
+ )
+gmx_register_gtest_test(GmxAnaTest ${exename} INTEGRATION_TEST IGNORE_LEAKS)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2009,2010,2012,2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2009,2010,2012,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif
}
-void gmx_barrier(const t_commrec gmx_unused* cr)
+void gmx_barrier(MPI_Comm gmx_unused communicator)
{
#if !GMX_MPI
GMX_RELEASE_ASSERT(false, "Invalid call to gmx_barrier");
#else
- MPI_Barrier(cr->mpi_comm_mygroup);
+ MPI_Barrier(communicator);
#endif
}
-void gmx_bcast(int gmx_unused nbytes, void gmx_unused* b, const t_commrec gmx_unused* cr)
+void gmx_bcast(int gmx_unused nbytes, void gmx_unused* b, MPI_Comm gmx_unused communicator)
{
#if !GMX_MPI
GMX_RELEASE_ASSERT(false, "Invalid call to gmx_bcast");
#else
- MPI_Bcast(b, nbytes, MPI_BYTE, MASTERRANK(cr), cr->mpi_comm_mygroup);
-#endif
-}
-
-void gmx_bcast_sim(int gmx_unused nbytes, void gmx_unused* b, const t_commrec gmx_unused* cr)
-{
-#if !GMX_MPI
- GMX_RELEASE_ASSERT(false, "Invalid call to gmx_bcast_sim");
-#else
- MPI_Bcast(b, nbytes, MPI_BYTE, MASTERRANK(cr), cr->mpi_comm_mysim);
+ MPI_Bcast(b, nbytes, MPI_BYTE, 0, communicator);
#endif
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void gmx_setup_nodecomm(FILE* fplog, struct t_commrec* cr);
/* Sets up fast global communication for clusters with multi-core nodes */
-void gmx_barrier(const struct t_commrec* cr);
-/* Wait till all processes in cr->mpi_comm_mygroup have reached the barrier */
+//! Wait until all processes in communicator have reached the barrier
+void gmx_barrier(MPI_Comm communicator);
-void gmx_bcast(int nbytes, void* b, const struct t_commrec* cr);
-/* Broadcast nbytes bytes from the master to cr->mpi_comm_mygroup */
-
-void gmx_bcast_sim(int nbytes, void* b, const struct t_commrec* cr);
-/* Broadcast nbytes bytes from the sim master to cr->mpi_comm_mysim */
+//! Broadcast nbytes bytes from the master to communicator
+void gmx_bcast(int nbytes, void* b, MPI_Comm communicator);
void gmx_sumi(int nr, int r[], const struct t_commrec* cr);
/* Calculate the global sum of an array of ints */
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "nb_free_energy.h"
+#include "config.h"
+
#include <cmath>
#include <algorithm>
#include "gromacs/math/vec.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
+#include "gromacs/simd/simd.h"
#include "gromacs/utility/fatalerror.h"
-//! Enum for templating the soft-core treatment in the kernel
-enum class SoftCoreTreatment
-{
- None, //!< No soft-core
- RPower6, //!< Soft-core with r-power = 6
- RPower48 //!< Soft-core with r-power = 48
-};
-
-//! Most treatments are fine with float in mixed-precision mode.
-template<SoftCoreTreatment softCoreTreatment>
-struct SoftCoreReal
+//! Scalar (non-SIMD) data types.
+struct ScalarDataTypes
{
- //! Real type for soft-core calculations
- using Real = real;
+ using RealType = real; //!< The data type to use as real.
+ using IntType = int; //!< The data type to use as int.
+ static constexpr int simdRealWidth = 1; //!< The width of the RealType.
+ static constexpr int simdIntWidth = 1; //!< The width of the IntType.
};
-//! This treatment requires double precision for some computations.
-template<>
-struct SoftCoreReal<SoftCoreTreatment::RPower48>
+#if GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
+//! SIMD data types.
+struct SimdDataTypes
{
- //! Real type for soft-core calculations
- using Real = double;
+ using RealType = gmx::SimdReal; //!< The data type to use as real.
+ using IntType = gmx::SimdInt32; //!< The data type to use as int.
+ static constexpr int simdRealWidth = GMX_SIMD_REAL_WIDTH; //!< The width of the RealType.
+ static constexpr int simdIntWidth = GMX_SIMD_FINT32_WIDTH; //!< The width of the IntType.
};
+#endif
//! Computes r^(1/p) and 1/r^(1/p) for the standard p=6
-template<SoftCoreTreatment softCoreTreatment>
-static inline void pthRoot(const real r, real* pthRoot, real* invPthRoot)
-{
- *invPthRoot = gmx::invsqrt(std::cbrt(r));
- *pthRoot = 1 / (*invPthRoot);
-}
-
-// We need a double version to make the specialization below work
-#if !GMX_DOUBLE
-//! Computes r^(1/p) and 1/r^(1/p) for the standard p=6
-template<SoftCoreTreatment softCoreTreatment>
-static inline void pthRoot(const double r, real* pthRoot, double* invPthRoot)
+template<class RealType>
+static inline void pthRoot(const RealType r, RealType* pthRoot, RealType* invPthRoot)
{
*invPthRoot = gmx::invsqrt(std::cbrt(r));
*pthRoot = 1 / (*invPthRoot);
}
-#endif
-//! Computes r^(1/p) and 1/r^(1/p) for p=48
-template<>
-inline void pthRoot<SoftCoreTreatment::RPower48>(const double r, real* pthRoot, double* invPthRoot)
+template<class RealType>
+static inline RealType calculateRinv6(const RealType rinvV)
{
- *pthRoot = std::pow(r, 1.0 / 48.0);
- *invPthRoot = 1 / (*pthRoot);
+ RealType rinv6 = rinvV * rinvV;
+ return (rinv6 * rinv6 * rinv6);
}
-template<SoftCoreTreatment softCoreTreatment>
-static inline real calculateSigmaPow(const real sigma6)
-{
- if (softCoreTreatment == SoftCoreTreatment::RPower6)
- {
- return sigma6;
- }
- else
- {
- real sigmaPow = sigma6 * sigma6; /* sigma^12 */
- sigmaPow = sigmaPow * sigmaPow; /* sigma^24 */
- sigmaPow = sigmaPow * sigmaPow; /* sigma^48 */
- return (sigmaPow);
- }
-}
-
-template<SoftCoreTreatment softCoreTreatment, class SCReal>
-static inline real calculateRinv6(const SCReal rinvV)
-{
- if (softCoreTreatment == SoftCoreTreatment::RPower6)
- {
- return rinvV;
- }
- else
- {
- real rinv6 = rinvV * rinvV;
- return (rinv6 * rinv6 * rinv6);
- }
-}
-
-static inline real calculateVdw6(const real c6, const real rinv6)
+template<class RealType>
+static inline RealType calculateVdw6(const RealType c6, const RealType rinv6)
{
return (c6 * rinv6);
}
-static inline real calculateVdw12(const real c12, const real rinv6)
+template<class RealType>
+static inline RealType calculateVdw12(const RealType c12, const RealType rinv6)
{
return (c12 * rinv6 * rinv6);
}
/* reaction-field electrostatics */
-template<class SCReal>
-static inline SCReal
-reactionFieldScalarForce(const real qq, const real rinv, const SCReal r, const real krf, const real two)
+template<class RealType>
+static inline RealType reactionFieldScalarForce(const RealType qq,
+ const RealType rinv,
+ const RealType r,
+ const real krf,
+ const real two)
{
return (qq * (rinv - two * krf * r * r));
}
-template<class SCReal>
-static inline real
-reactionFieldPotential(const real qq, const real rinv, const SCReal r, const real krf, const real potentialShift)
+template<class RealType>
+static inline RealType reactionFieldPotential(const RealType qq,
+ const RealType rinv,
+ const RealType r,
+ const real krf,
+ const real potentialShift)
{
return (qq * (rinv + krf * r * r - potentialShift));
}
/* Ewald electrostatics */
-static inline real ewaldScalarForce(const real coulomb, const real rinv)
+template<class RealType>
+static inline RealType ewaldScalarForce(const RealType coulomb, const RealType rinv)
{
return (coulomb * rinv);
}
-static inline real ewaldPotential(const real coulomb, const real rinv, const real potentialShift)
+template<class RealType>
+static inline RealType ewaldPotential(const RealType coulomb, const RealType rinv, const real potentialShift)
{
return (coulomb * (rinv - potentialShift));
}
/* cutoff LJ */
-static inline real lennardJonesScalarForce(const real v6, const real v12)
+template<class RealType>
+static inline RealType lennardJonesScalarForce(const RealType v6, const RealType v12)
{
return (v12 - v6);
}
-static inline real lennardJonesPotential(const real v6,
- const real v12,
- const real c6,
- const real c12,
- const real repulsionShift,
- const real dispersionShift,
- const real onesixth,
- const real onetwelfth)
+template<class RealType>
+static inline RealType lennardJonesPotential(const RealType v6,
+ const RealType v12,
+ const RealType c6,
+ const RealType c12,
+ const real repulsionShift,
+ const real dispersionShift,
+ const real onesixth,
+ const real onetwelfth)
{
return ((v12 + c12 * repulsionShift) * onetwelfth - (v6 + c6 * dispersionShift) * onesixth);
}
}
/* LJ Potential switch */
-template<class SCReal>
-static inline SCReal potSwitchScalarForceMod(const SCReal fScalarInp,
- const real potential,
- const real sw,
- const SCReal r,
- const real rVdw,
- const real dsw,
- const real zero)
+template<class RealType>
+static inline RealType potSwitchScalarForceMod(const RealType fScalarInp,
+ const RealType potential,
+ const RealType sw,
+ const RealType r,
+ const RealType rVdw,
+ const RealType dsw,
+ const real zero)
{
if (r < rVdw)
{
- SCReal fScalar = fScalarInp * sw - r * potential * dsw;
+ real fScalar = fScalarInp * sw - r * potential * dsw;
return (fScalar);
}
return (zero);
}
-template<class SCReal>
-static inline real
-potSwitchPotentialMod(const real potentialInp, const real sw, const SCReal r, const real rVdw, const real zero)
+template<class RealType>
+static inline RealType potSwitchPotentialMod(const RealType potentialInp,
+ const RealType sw,
+ const RealType r,
+ const RealType rVdw,
+ const real zero)
{
if (r < rVdw)
{
//! Templated free-energy non-bonded kernel
-template<SoftCoreTreatment softCoreTreatment, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald, bool elecInteractionTypeIsEwald, bool vdwModifierIsPotSwitch>
+template<typename DataTypes, bool useSoftCore, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald, bool elecInteractionTypeIsEwald, bool vdwModifierIsPotSwitch>
static void nb_free_energy_kernel(const t_nblist* gmx_restrict nlist,
rvec* gmx_restrict xx,
gmx::ForceWithShiftForces* forceWithShiftForces,
nb_kernel_data_t* gmx_restrict kernel_data,
t_nrnb* gmx_restrict nrnb)
{
- using SCReal = typename SoftCoreReal<softCoreTreatment>::Real;
-
- constexpr bool useSoftCore = (softCoreTreatment != SoftCoreTreatment::None);
-
#define STATE_A 0
#define STATE_B 1
#define NSTATES 2
+ using RealType = typename DataTypes::RealType;
+ using IntType = typename DataTypes::IntType;
+
+ /* FIXME: How should these be handled with SIMD? */
constexpr real onetwelfth = 1.0 / 12.0;
constexpr real onesixth = 1.0 / 6.0;
constexpr real zero = 0.0;
const int* typeA = mdatoms->typeA;
const int* typeB = mdatoms->typeB;
const int ntype = fr->ntype;
- const real* nbfp = fr->nbfp;
+ const real* nbfp = fr->nbfp.data();
const real* nbfp_grid = fr->ljpme_c6grid;
real* Vv = kernel_data->energygrp_vdw;
const real lambda_coul = kernel_data->lambda[efptCOUL];
GMX_RELEASE_ASSERT(!(vdwInteractionTypeIsEwald && vdwModifierIsPotSwitch),
"Can not apply soft-core to switched Ewald potentials");
- SCReal dvdl_coul = 0; /* Needs double for sc_power==48 */
- SCReal dvdl_vdw = 0; /* Needs double for sc_power==48 */
+ real dvdl_coul = 0;
+ real dvdl_vdw = 0;
/* Lambda factor for state A, 1-lambda*/
real LFC[NSTATES], LFV[NSTATES];
DLF[STATE_B] = 1;
real lfac_coul[NSTATES], dlfac_coul[NSTATES], lfac_vdw[NSTATES], dlfac_vdw[NSTATES];
- constexpr real sc_r_power = (softCoreTreatment == SoftCoreTreatment::RPower48 ? 48.0_real : 6.0_real);
+ constexpr real sc_r_power = 6.0_real;
for (int i = 0; i < NSTATES; i++)
{
lfac_coul[i] = (lam_power == 2 ? (1 - LFC[i]) * (1 - LFC[i]) : (1 - LFC[i]));
for (int k = nj0; k < nj1; k++)
{
- int tj[NSTATES];
- const int jnr = jjnr[k];
- const int j3 = 3 * jnr;
- real c6[NSTATES], c12[NSTATES], qq[NSTATES], Vcoul[NSTATES], Vvdw[NSTATES];
- real r, rinv, rp, rpm2;
- real alpha_vdw_eff, alpha_coul_eff, sigma_pow[NSTATES];
- const real dx = ix - x[j3];
- const real dy = iy - x[j3 + 1];
- const real dz = iz - x[j3 + 2];
- const real rsq = dx * dx + dy * dy + dz * dz;
- SCReal FscalC[NSTATES], FscalV[NSTATES]; /* Needs double for sc_power==48 */
-
- if (rsq >= rcutoff_max2)
+ int tj[NSTATES];
+ const int jnr = jjnr[k];
+ const int j3 = 3 * jnr;
+ RealType c6[NSTATES], c12[NSTATES], qq[NSTATES], Vcoul[NSTATES], Vvdw[NSTATES];
+ RealType r, rinv, rp, rpm2;
+ RealType alpha_vdw_eff, alpha_coul_eff, sigma6[NSTATES];
+ const RealType dx = ix - x[j3];
+ const RealType dy = iy - x[j3 + 1];
+ const RealType dz = iz - x[j3 + 2];
+ const RealType rsq = dx * dx + dy * dy + dz * dz;
+ RealType FscalC[NSTATES], FscalV[NSTATES];
+ /* Check if this pair on the exlusions list.*/
+ const bool bPairIncluded = nlist->excl_fep == nullptr || nlist->excl_fep[k];
+
+ if (rsq >= rcutoff_max2 && bPairIncluded)
{
/* We save significant time by skipping all code below.
* Note that with soft-core interactions, the actual cut-off
* check might be different. But since the soft-core distance
* is always larger than r, checking on r here is safe.
+ * Exclusions outside the cutoff can not be skipped as
+ * when using Ewald: the reciprocal-space
+ * Ewald component still needs to be subtracted.
*/
+
continue;
}
npair_within_cutoff++;
r = 0;
}
- if (softCoreTreatment == SoftCoreTreatment::None)
+ if (useSoftCore)
+ {
+ rpm2 = rsq * rsq; /* r4 */
+ rp = rpm2 * rsq; /* r6 */
+ }
+ else
{
/* The soft-core power p will not affect the results
* with not using soft-core, so we use power of 0 which gives
rpm2 = rinv * rinv;
rp = 1;
}
- if (softCoreTreatment == SoftCoreTreatment::RPower6)
- {
- rpm2 = rsq * rsq; /* r4 */
- rp = rpm2 * rsq; /* r6 */
- }
- if (softCoreTreatment == SoftCoreTreatment::RPower48)
- {
- rp = rsq * rsq * rsq; /* r6 */
- rp = rp * rp; /* r12 */
- rp = rp * rp; /* r24 */
- rp = rp * rp; /* r48 */
- rpm2 = rp / rsq; /* r46 */
- }
- real Fscal = 0;
+ RealType Fscal = 0;
qq[STATE_A] = iqA * chargeA[jnr];
qq[STATE_B] = iqB * chargeB[jnr];
tj[STATE_A] = ntiA + 2 * typeA[jnr];
tj[STATE_B] = ntiB + 2 * typeB[jnr];
- if (nlist->excl_fep == nullptr || nlist->excl_fep[k])
+ if (bPairIncluded)
{
c6[STATE_A] = nbfp[tj[STATE_A]];
c6[STATE_B] = nbfp[tj[STATE_B]];
c12[i] = nbfp[tj[i] + 1];
if (useSoftCore)
{
- real sigma6[NSTATES];
if ((c6[i] > 0) && (c12[i] > 0))
{
/* c12 is stored scaled with 12.0 and c6 is scaled with 6.0 - correct for this */
{
sigma6[i] = sigma6_def;
}
- sigma_pow[i] = calculateSigmaPow<softCoreTreatment>(sigma6[i]);
}
}
Vcoul[i] = 0;
Vvdw[i] = 0;
- real rinvC, rinvV;
- SCReal rC, rV, rpinvC, rpinvV; /* Needs double for sc_power==48 */
+ RealType rinvC, rinvV, rC, rV, rpinvC, rpinvV;
/* Only spend time on A or B state if it is non-zero */
if ((qq[i] != 0) || (c6[i] != 0) || (c12[i] != 0))
{
- /* this section has to be inside the loop because of the dependence on sigma_pow */
+ /* this section has to be inside the loop because of the dependence on sigma6 */
if (useSoftCore)
{
- rpinvC = one / (alpha_coul_eff * lfac_coul[i] * sigma_pow[i] + rp);
- pthRoot<softCoreTreatment>(rpinvC, &rinvC, &rC);
+ rpinvC = one / (alpha_coul_eff * lfac_coul[i] * sigma6[i] + rp);
+ pthRoot(rpinvC, &rinvC, &rC);
if (scLambdasOrAlphasDiffer)
{
- rpinvV = one / (alpha_vdw_eff * lfac_vdw[i] * sigma_pow[i] + rp);
- pthRoot<softCoreTreatment>(rpinvV, &rinvV, &rV);
+ rpinvV = one / (alpha_vdw_eff * lfac_vdw[i] * sigma6[i] + rp);
+ pthRoot(rpinvV, &rinvV, &rV);
}
else
{
|| (!vdwInteractionTypeIsEwald && rV < rvdw);
if ((c6[i] != 0 || c12[i] != 0) && computeVdwInteraction)
{
- real rinv6;
- if (softCoreTreatment == SoftCoreTreatment::RPower6)
+ RealType rinv6;
+ if (useSoftCore)
{
- rinv6 = calculateRinv6<softCoreTreatment>(rpinvV);
+ rinv6 = rpinvV;
}
else
{
- rinv6 = calculateRinv6<softCoreTreatment>(rinvV);
+ rinv6 = calculateRinv6(rinvV);
}
- real Vvdw6 = calculateVdw6(c6[i], rinv6);
- real Vvdw12 = calculateVdw12(c12[i], rinv6);
+ RealType Vvdw6 = calculateVdw6(c6[i], rinv6);
+ RealType Vvdw12 = calculateVdw12(c12[i], rinv6);
Vvdw[i] = lennardJonesPotential(Vvdw6, Vvdw12, c6[i], c12[i], repulsionShift,
dispersionShift, onesixth, onetwelfth);
if (vdwModifierIsPotSwitch)
{
- real d = rV - ic->rvdw_switch;
- d = (d > zero) ? d : zero;
- const real d2 = d * d;
- const real sw = one + d2 * d * (vdw_swV3 + d * (vdw_swV4 + d * vdw_swV5));
- const real dsw = d2 * (vdw_swF2 + d * (vdw_swF3 + d * vdw_swF4));
+ RealType d = rV - ic->rvdw_switch;
+ d = (d > zero) ? d : zero;
+ const RealType d2 = d * d;
+ const RealType sw =
+ one + d2 * d * (vdw_swV3 + d * (vdw_swV4 + d * vdw_swV5));
+ const RealType dsw = d2 * (vdw_swF2 + d * (vdw_swF3 + d * vdw_swF4));
FscalV[i] = potSwitchScalarForceMod(FscalV[i], Vvdw[i], sw, rV,
rvdw, dsw, zero);
FscalC[i] *= rpinvC;
FscalV[i] *= rpinvV;
}
- }
+ } // end for (int i = 0; i < NSTATES; i++)
/* Assemble A and B states */
for (int i = 0; i < NSTATES; i++)
if (useSoftCore)
{
- dvdl_coul +=
- Vcoul[i] * DLF[i]
- + LFC[i] * alpha_coul_eff * dlfac_coul[i] * FscalC[i] * sigma_pow[i];
+ dvdl_coul += Vcoul[i] * DLF[i]
+ + LFC[i] * alpha_coul_eff * dlfac_coul[i] * FscalC[i] * sigma6[i];
dvdl_vdw += Vvdw[i] * DLF[i]
- + LFV[i] * alpha_vdw_eff * dlfac_vdw[i] * FscalV[i] * sigma_pow[i];
+ + LFV[i] * alpha_vdw_eff * dlfac_vdw[i] * FscalV[i] * sigma6[i];
}
else
{
dvdl_vdw += Vvdw[i] * DLF[i];
}
}
- }
+ } // end if (bPairIncluded)
else if (icoul == GMX_NBKERNEL_ELEC_REACTIONFIELD)
{
/* For excluded pairs, which are only in this pair list when
* As there is no singularity, there is no need for soft-core.
*/
const real FF = -two * krf;
- real VV = krf * rsq - crf;
+ RealType VV = krf * rsq - crf;
if (ii == jnr)
{
}
}
- if (elecInteractionTypeIsEwald && r < rcoulomb)
+ if (elecInteractionTypeIsEwald && (r < rcoulomb || !bPairIncluded))
{
/* See comment in the preamble. When using Ewald interactions
* (unless we use a switch modifier) we subtract the reciprocal-space
*/
real v_lr, f_lr;
- const real ewrt = r * coulombTableScale;
- int ewitab = static_cast<int>(ewrt);
- const real eweps = ewrt - ewitab;
- ewitab = 4 * ewitab;
- f_lr = ewtab[ewitab] + eweps * ewtab[ewitab + 1];
+ const RealType ewrt = r * coulombTableScale;
+ IntType ewitab = static_cast<IntType>(ewrt);
+ const RealType eweps = ewrt - ewitab;
+ ewitab = 4 * ewitab;
+ f_lr = ewtab[ewitab] + eweps * ewtab[ewitab + 1];
v_lr = (ewtab[ewitab + 2] - coulombTableScaleInvHalf * eweps * (ewtab[ewitab] + f_lr));
f_lr *= rinv;
* r close to 0 for non-interacting pairs.
*/
- const real rs = rsq * rinv * vdwTableScale;
- const int ri = static_cast<int>(rs);
- const real frac = rs - ri;
- const real f_lr = (1 - frac) * tab_ewald_F_lj[ri] + frac * tab_ewald_F_lj[ri + 1];
+ const RealType rs = rsq * rinv * vdwTableScale;
+ const IntType ri = static_cast<IntType>(rs);
+ const RealType frac = rs - ri;
+ const RealType f_lr = (1 - frac) * tab_ewald_F_lj[ri] + frac * tab_ewald_F_lj[ri + 1];
/* TODO: Currently the Ewald LJ table does not contain
* the factor 1/6, we should add this.
*/
- const real FF = f_lr * rinv / six;
- real VV = (tab_ewald_V_lj[ri] - vdwTableScaleInvHalf * frac * (tab_ewald_F_lj[ri] + f_lr))
- / six;
+ const RealType FF = f_lr * rinv / six;
+ RealType VV =
+ (tab_ewald_V_lj[ri] - vdwTableScaleInvHalf * frac * (tab_ewald_F_lj[ri] + f_lr))
+ / six;
if (ii == jnr)
{
#pragma omp atomic
f[j3 + 2] -= tz;
}
- }
+ } // end for (int k = nj0; k < nj1; k++)
/* The atomics below are expensive with many OpenMP threads.
* Here unperturbed i-particles will usually only have a few
Vv[ggid] += vvtot;
}
}
- }
+ } // end for (int n = 0; n < nri; n++)
#pragma omp atomic
dvdl[efptCOUL] += dvdl_coul;
nb_kernel_data_t* gmx_restrict kernel_data,
t_nrnb* gmx_restrict nrnb);
-template<SoftCoreTreatment softCoreTreatment, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald, bool elecInteractionTypeIsEwald>
-static KernelFunction dispatchKernelOnVdwModifier(const bool vdwModifierIsPotSwitch)
+template<bool useSoftCore, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald, bool elecInteractionTypeIsEwald, bool vdwModifierIsPotSwitch>
+static KernelFunction dispatchKernelOnUseSimd(const bool useSimd)
+{
+ if (useSimd)
+ {
+#if GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS && GMX_USE_SIMD_KERNELS
+ /* FIXME: Here SimdDataTypes should be used to enable SIMD. So far, the code in nb_free_energy_kernel is not adapted to SIMD */
+ return (nb_free_energy_kernel<ScalarDataTypes, useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch>);
+#else
+ return (nb_free_energy_kernel<ScalarDataTypes, useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch>);
+#endif
+ }
+ else
+ {
+ return (nb_free_energy_kernel<ScalarDataTypes, useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch>);
+ }
+}
+
+template<bool useSoftCore, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald, bool elecInteractionTypeIsEwald>
+static KernelFunction dispatchKernelOnVdwModifier(const bool vdwModifierIsPotSwitch, const bool useSimd)
{
if (vdwModifierIsPotSwitch)
{
- return (nb_free_energy_kernel<softCoreTreatment, scLambdasOrAlphasDiffer,
- vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, true>);
+ return (dispatchKernelOnUseSimd<useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, true>(useSimd));
}
else
{
- return (nb_free_energy_kernel<softCoreTreatment, scLambdasOrAlphasDiffer,
- vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, false>);
+ return (dispatchKernelOnUseSimd<useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, false>(useSimd));
}
}
-template<SoftCoreTreatment softCoreTreatment, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald>
+template<bool useSoftCore, bool scLambdasOrAlphasDiffer, bool vdwInteractionTypeIsEwald>
static KernelFunction dispatchKernelOnElecInteractionType(const bool elecInteractionTypeIsEwald,
- const bool vdwModifierIsPotSwitch)
+ const bool vdwModifierIsPotSwitch,
+ const bool useSimd)
{
if (elecInteractionTypeIsEwald)
{
- return (dispatchKernelOnVdwModifier<softCoreTreatment, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, true>(
- vdwModifierIsPotSwitch));
+ return (dispatchKernelOnVdwModifier<useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, true>(
+ vdwModifierIsPotSwitch, useSimd));
}
else
{
- return (dispatchKernelOnVdwModifier<softCoreTreatment, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, false>(
- vdwModifierIsPotSwitch));
+ return (dispatchKernelOnVdwModifier<useSoftCore, scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, false>(
+ vdwModifierIsPotSwitch, useSimd));
}
}
-template<SoftCoreTreatment softCoreTreatment, bool scLambdasOrAlphasDiffer>
+template<bool useSoftCore, bool scLambdasOrAlphasDiffer>
static KernelFunction dispatchKernelOnVdwInteractionType(const bool vdwInteractionTypeIsEwald,
const bool elecInteractionTypeIsEwald,
- const bool vdwModifierIsPotSwitch)
+ const bool vdwModifierIsPotSwitch,
+ const bool useSimd)
{
if (vdwInteractionTypeIsEwald)
{
- return (dispatchKernelOnElecInteractionType<softCoreTreatment, scLambdasOrAlphasDiffer, true>(
- elecInteractionTypeIsEwald, vdwModifierIsPotSwitch));
+ return (dispatchKernelOnElecInteractionType<useSoftCore, scLambdasOrAlphasDiffer, true>(
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, useSimd));
}
else
{
- return (dispatchKernelOnElecInteractionType<softCoreTreatment, scLambdasOrAlphasDiffer, false>(
- elecInteractionTypeIsEwald, vdwModifierIsPotSwitch));
+ return (dispatchKernelOnElecInteractionType<useSoftCore, scLambdasOrAlphasDiffer, false>(
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, useSimd));
}
}
-template<SoftCoreTreatment softCoreTreatment>
+template<bool useSoftCore>
static KernelFunction dispatchKernelOnScLambdasOrAlphasDifference(const bool scLambdasOrAlphasDiffer,
const bool vdwInteractionTypeIsEwald,
const bool elecInteractionTypeIsEwald,
- const bool vdwModifierIsPotSwitch)
+ const bool vdwModifierIsPotSwitch,
+ const bool useSimd)
{
if (scLambdasOrAlphasDiffer)
{
- return (dispatchKernelOnVdwInteractionType<softCoreTreatment, true>(
- vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, vdwModifierIsPotSwitch));
+ return (dispatchKernelOnVdwInteractionType<useSoftCore, true>(
+ vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, useSimd));
}
else
{
- return (dispatchKernelOnVdwInteractionType<softCoreTreatment, false>(
- vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, vdwModifierIsPotSwitch));
+ return (dispatchKernelOnVdwInteractionType<useSoftCore, false>(
+ vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, useSimd));
}
}
const bool vdwInteractionTypeIsEwald,
const bool elecInteractionTypeIsEwald,
const bool vdwModifierIsPotSwitch,
+ const bool useSimd,
const t_forcerec* fr)
{
if (fr->sc_alphacoul == 0 && fr->sc_alphavdw == 0)
{
- return (dispatchKernelOnScLambdasOrAlphasDifference<SoftCoreTreatment::None>(
+ return (dispatchKernelOnScLambdasOrAlphasDifference<false>(
scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald,
- vdwModifierIsPotSwitch));
- }
- else if (fr->sc_r_power == 6.0_real)
- {
- return (dispatchKernelOnScLambdasOrAlphasDifference<SoftCoreTreatment::RPower6>(
- scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald,
- vdwModifierIsPotSwitch));
+ vdwModifierIsPotSwitch, useSimd));
}
else
{
- return (dispatchKernelOnScLambdasOrAlphasDifference<SoftCoreTreatment::RPower48>(
+ return (dispatchKernelOnScLambdasOrAlphasDifference<true>(
scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald, elecInteractionTypeIsEwald,
- vdwModifierIsPotSwitch));
+ vdwModifierIsPotSwitch, useSimd));
}
}
const bool elecInteractionTypeIsEwald = (EEL_PME_EWALD(fr->ic->eeltype));
const bool vdwModifierIsPotSwitch = (fr->ic->vdw_modifier == eintmodPOTSWITCH);
bool scLambdasOrAlphasDiffer = true;
+ const bool useSimd = fr->use_simd_kernels;
if (fr->sc_alphacoul == 0 && fr->sc_alphavdw == 0)
{
scLambdasOrAlphasDiffer = false;
}
- else if (fr->sc_r_power == 6.0_real || fr->sc_r_power == 48.0_real)
+ else if (fr->sc_r_power == 6.0_real)
{
if (kernel_data->lambda[efptCOUL] == kernel_data->lambda[efptVDW] && fr->sc_alphacoul == fr->sc_alphavdw)
{
{
GMX_RELEASE_ASSERT(false, "Unsupported soft-core r-power");
}
- KernelFunction kernelFunc = dispatchKernel(scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
- elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, fr);
+
+ KernelFunction kernelFunc;
+ kernelFunc = dispatchKernel(scLambdasOrAlphasDiffer, vdwInteractionTypeIsEwald,
+ elecInteractionTypeIsEwald, vdwModifierIsPotSwitch, useSimd, fr);
kernelFunc(nlist, xx, ff, fr, mdatoms, kernel_data, nrnb);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/gmxlib/nonbonded/nb_kernel.h"
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/nblist.h"
struct t_forcerec;
+struct t_mdatoms;
namespace gmx
{
class ForceWithShiftForces;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/nblist.h"
#include "gromacs/utility/real.h"
struct t_blocka;
+struct t_mdatoms;
/* Structure to collect kernel data not available in forcerec or mdatoms structures.
* This is only used inside the nonbonded module.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016, by the GROMACS development team, led by
+# Copyright (c) 2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(GmxlibTests gmxlib-test
+ CPP_SOURCE_FILES
)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-static void visualize_images(const char* fn, int ePBC, matrix box)
+static void visualize_images(const char* fn, PbcType pbcType, matrix box)
{
t_atoms atoms;
rvec* img;
}
calc_triclinic_images(box, img + 1);
- write_sto_conf(fn, "Images", &atoms, img, nullptr, ePBC, box);
+ write_sto_conf(fn, "Images", &atoms, img, nullptr, pbcType, box);
done_atom(&atoms);
sfree(img);
int isize, ssize, numAlignmentAtoms;
int * index, *sindex, *aindex;
rvec * x, *v, gc, rmin, rmax, size;
- int ePBC;
+ PbcType pbcType;
matrix box, rotmatrix, trans;
rvec princd, tmpvec;
gmx_bool bIndex, bSetSize, bSetAng, bDist, bSetCenter, bAlign;
char* name;
t_atoms atoms;
open_symtab(&symtab);
- readConfAndAtoms(infile, &symtab, &name, &atoms, &ePBC, &x, &v, box);
+ readConfAndAtoms(infile, &symtab, &name, &atoms, &pbcType, &x, &v, box);
natom = atoms.nr;
if (atoms.pdbinfo == nullptr)
{
get_pdb_atomnumber(&atoms, &aps);
}
- if (ePBC != epbcNONE)
+ if (pbcType != PbcType::No)
{
real vol = det(box);
printf("Volume: %g nm^3, corresponds to roughly %d electrons\n", vol,
}
else if (visbox[0] == -1)
{
- visualize_images("images.pdb", ePBC, box);
+ visualize_images("images.pdb", pbcType, box);
}
/* remove pbc */
if ((btype[0] != nullptr) && (bSetSize || bDist || (btype[0][0] == 't' && bSetAng)))
{
- ePBC = epbcXYZ;
+ pbcType = PbcType::Xyz;
if (!(bSetSize || bDist))
{
for (i = 0; i < DIM; i++)
printf("new box volume :%7.2f (nm^3)\n", det(box));
}
- if (check_box(epbcXYZ, box))
+ if (check_box(PbcType::Xyz, box))
{
printf("\nWARNING: %s\n"
"See the GROMACS manual for a description of the requirements that\n"
"must be satisfied by descriptions of simulation cells.\n",
- check_box(epbcXYZ, box));
+ check_box(PbcType::Xyz, box));
}
if (bDist && btype[0][0] == 't')
if (outftp == efPDB)
{
out = gmx_ffopen(outfile, "w");
- write_pdbfile_indexed(out, name, &atoms, x, ePBC, box, ' ', 1, isize, index, conect, FALSE);
+ write_pdbfile_indexed(out, name, &atoms, x, pbcType, box, ' ', 1, isize, index, conect, FALSE);
gmx_ffclose(out);
}
else
{
- write_sto_conf_indexed(outfile, name, &atoms, x, bHaveV ? v : nullptr, ePBC, box, isize, index);
+ write_sto_conf_indexed(outfile, name, &atoms, x, bHaveV ? v : nullptr, pbcType, box,
+ isize, index);
}
sfree(grpname);
sfree(index);
{
index[i] = i;
}
- write_pdbfile_indexed(out, name, &atoms, x, ePBC, box, ' ', -1, atoms.nr, index, conect,
- outftp == efPQR);
+ write_pdbfile_indexed(out, name, &atoms, x, pbcType, box, ' ', -1, atoms.nr, index,
+ conect, outftp == efPQR);
sfree(index);
if (bLegend)
{
}
else
{
- write_sto_conf(outfile, name, &atoms, x, bHaveV ? v : nullptr, ePBC, box);
+ write_sto_conf(outfile, name, &atoms, x, bHaveV ? v : nullptr, pbcType, box);
}
}
done_atom(&atoms);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
int ac;
- if ((ac = (a1.aj() - a2.aj())) != 0)
- {
- return ac < 0;
- }
- else if ((ac = (a1.ai() - a2.ai())) != 0)
+ if (((ac = (a1.aj() - a2.aj())) != 0) || ((ac = (a1.ai() - a2.ai())) != 0))
{
return ac < 0;
}
int dc;
/* First sort by J & K (the two central) atoms */
- if ((dc = (d1.aj() - d2.aj())) != 0)
- {
- return dc < 0;
- }
- else if ((dc = (d1.ak() - d2.ak())) != 0)
- {
+ if (((dc = (d1.aj() - d2.aj())) != 0) || ((dc = (d1.ak() - d2.ak())) != 0))
+ { // NOLINT bugprone-branch-clone
return dc < 0;
}
/* Then make sure to put rtp dihedrals before generated ones */
return false;
}
/* Then sort by I and J (two outer) atoms */
- else if ((dc = (d1.ai() - d2.ai())) != 0)
- {
- return dc < 0;
- }
- else if ((dc = (d1.al() - d2.al())) != 0)
+ else if (((dc = (d1.ai() - d2.ai())) != 0) || ((dc = (d1.al() - d2.al())) != 0))
{
return dc < 0;
}
{
int d;
- if ((d = (a.ai() - b.ai())) != 0)
- {
- return d < 0;
- }
- else if ((d = (a.al() - b.al())) != 0)
- {
- return d < 0;
- }
- else if ((d = (a.aj() - b.aj())) != 0)
+ if (((d = (a.ai() - b.ai())) != 0) || ((d = (a.al() - b.al())) != 0) || ((d = (a.aj() - b.aj())) != 0))
{
return d < 0;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
-static void low_mspeed(real tempi, gmx_mtop_t* mtop, rvec v[], gmx::ThreeFry2x64<>* rng)
+static void low_mspeed(real tempi, gmx_mtop_t* mtop, rvec v[], gmx::ThreeFry2x64<>* rng, const gmx::MDLogger& logger)
{
int nrdf;
real boltz;
}
}
}
- fprintf(stderr, "Velocities were taken from a Maxwell distribution at %g K\n", tempi);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Velocities were taken from a Maxwell distribution at %g K", tempi);
if (debug)
{
fprintf(debug,
}
}
-void maxwell_speed(real tempi, unsigned int seed, gmx_mtop_t* mtop, rvec v[])
+void maxwell_speed(real tempi, unsigned int seed, gmx_mtop_t* mtop, rvec v[], const gmx::MDLogger& logger)
{
if (seed == 0)
{
seed = static_cast<int>(gmx::makeRandomSeed());
- fprintf(stderr, "Using random seed %u for generating velocities\n", seed);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Using random seed %u for generating velocities", seed);
}
gmx::ThreeFry2x64<> rng(seed, gmx::RandomDomain::MaxwellVelocities);
- low_mspeed(tempi, mtop, v, &rng);
+ low_mspeed(tempi, mtop, v, &rng, logger);
}
static real calc_cm(int natoms, const real mass[], rvec x[], rvec v[], rvec xcm, rvec vcm, rvec acm, matrix L)
return tm;
}
-void stop_cm(FILE gmx_unused* log, int natoms, real mass[], rvec x[], rvec v[])
+void stop_cm(const gmx::MDLogger gmx_unused& logger, int natoms, real mass[], rvec x[], rvec v[])
{
rvec xcm, vcm, acm;
tensor L;
int i, m;
#ifdef DEBUG
- fprintf(log, "stopping center of mass motion...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("stopping center of mass motion...");
#endif
(void)calc_cm(natoms, mass, x, v, xcm, vcm, acm, L);
v[i][m] -= vcm[m];
}
}
-
-#ifdef DEBUG
- (void)calc_cm(log, natoms, mass, x, v, xcm, vcm, acm, L);
-#endif
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_mtop_t;
+namespace gmx
+{
+class MDLogger;
+}
+
/*! \brief
* Generate Maxwellian velocities.
*
* \param[in] seed Random number generator seed
* \param[in] mtop Molecular Topology
* \param[out] v Velocities
+ * \param[in] logger Handle to logging interface.
*/
-void maxwell_speed(real tempi, unsigned int seed, gmx_mtop_t* mtop, rvec v[]);
+void maxwell_speed(real tempi, unsigned int seed, gmx_mtop_t* mtop, rvec v[], const gmx::MDLogger& logger);
/*! \brief
* Remove the center of mass motion in a set of coordinates.
*
- * \param[out] log File for printing debug information
+ * \param[in] logger Handle to logging interface.
* \param[in] natoms Number of atoms
* \param[in] mass Atomic masses
* \param[in] x Coordinates
* \param[out] v Velocities
*/
-void stop_cm(FILE* log, int natoms, real mass[], rvec x[], rvec v[]);
+void stop_cm(const gmx::MDLogger& logger, int natoms, real mass[], rvec x[], rvec v[]);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
rvec * x, *xx, *v; /* coordinates? */
real t;
vec4 * xrot, *vrot;
- int ePBC;
+ PbcType pbcType;
matrix box, boxx; /* box length matrix */
rvec shift;
int natoms; /* number of atoms in one molecule */
gmx_mtop_t mtop;
bool haveTop = false;
- readConfAndTopology(opt2fn("-f", NFILE, fnm), &haveTop, &mtop, &ePBC, &x, &v, box);
+ readConfAndTopology(opt2fn("-f", NFILE, fnm), &haveTop, &mtop, &pbcType, &x, &v, box);
t_atoms atoms = gmx_mtop_global_atoms(&mtop);
natoms = atoms.nr;
nres = atoms.nres; /* nr of residues in one element? */
v[ndx + l][m] = v[l][m];
}
}
- if (ePBC == epbcSCREW && i % 2 == 1)
+ if (pbcType == PbcType::Screw && i % 2 == 1)
{
/* Rotate around x axis */
for (m = YY; m <= ZZ; m++)
svmul(nx, box[XX], box[XX]);
svmul(ny, box[YY], box[YY]);
svmul(nz, box[ZZ], box[ZZ]);
- if (ePBC == epbcSCREW && nx % 2 == 0)
+ if (pbcType == PbcType::Screw && nx % 2 == 0)
{
/* With an even number of boxes in x we can forgot about the screw */
- ePBC = epbcXYZ;
+ pbcType = PbcType::Xyz;
}
/*depending on how you look at it, this is either a nasty hack or the way it should work*/
}
}
- write_sto_conf(opt2fn("-o", NFILE, fnm), *mtop.name, &atoms, x, v, ePBC, box);
+ write_sto_conf(opt2fn("-o", NFILE, fnm), *mtop.name, &atoms, x, v, pbcType, box);
sfree(x);
sfree(v);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
matrix box;
t_atoms atoms;
t_pbc pbc;
- int * repl, ePBC;
+ int* repl;
+ PbcType pbcType;
int nw, nsa, nsalt, iqtot;
gmx_output_env_t* oenv = nullptr;
t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD },
}
/* Read atom positions and charges */
- read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, &x, nullptr, box, FALSE);
+ read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &pbcType, &x, nullptr, box, FALSE);
atoms = top.atoms;
/* Compute total charge */
}
snew(repl, nw);
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
if (seed == 0)
sfree(atoms.pdbinfo);
atoms.pdbinfo = nullptr;
- write_sto_conf(ftp2fn(efSTO, NFILE, fnm), *top.name, &atoms, x, nullptr, ePBC, box);
+ write_sto_conf(ftp2fn(efSTO, NFILE, fnm), *top.name, &atoms, x, nullptr, pbcType, box);
sfree(pptr);
sfree(paptr);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
#include <memory>
-
#include <unordered_set>
+
#include <sys/types.h>
#include "gromacs/utility/arrayref.h"
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
#endif
-static void nnb2excl(t_nextnb* nnb, t_blocka* excl)
+static void nnb2excl(t_nextnb* nnb, gmx::ListOfLists<int>* excls)
{
int i, j, j_index;
int nre, nrx, nrs, nr_of_sortables;
sortable* s;
- srenew(excl->index, nnb->nr + 1);
- excl->index[0] = 0;
+ excls->clear();
+
for (i = 0; (i < nnb->nr); i++)
{
/* calculate the total number of exclusions for atom i */
nr_of_sortables = j_index;
prints("after rm-double", j_index, s);
- /* make space for arrays */
- srenew(excl->a, excl->nra + nr_of_sortables);
-
/* put the sorted exclusions in the target list */
+ excls->pushBackListOfSize(nr_of_sortables);
+ gmx::ArrayRef<int> exclusionsForAtom = excls->back();
for (nrs = 0; (nrs < nr_of_sortables); nrs++)
{
- excl->a[excl->nra + nrs] = s[nrs].aj;
+ exclusionsForAtom[nrs] = s[nrs].aj;
}
- excl->nra += nr_of_sortables;
- excl->index[i + 1] = excl->nra;
/* cleanup temporary space */
sfree(s);
}
-void generate_excl(int nrexcl, int nratoms, gmx::ArrayRef<InteractionsOfType> plist, t_blocka* excl)
+void generate_excl(int nrexcl, int nratoms, gmx::ArrayRef<InteractionsOfType> plist, gmx::ListOfLists<int>* excls)
{
t_nextnb nnb;
if (nrexcl < 0)
}
init_nnb(&nnb, nratoms, nrexcl);
gen_nnb(&nnb, plist);
- excl->nr = nratoms;
sort_and_purge_nnb(&nnb);
- nnb2excl(&nnb, excl);
+ nnb2excl(&nnb, excls);
done_nnb(&nnb);
}
#include "gromacs/utility/arrayref.h"
-struct t_blocka;
struct InteractionsOfType;
+namespace gmx
+{
+template<typename>
+class ListOfLists;
+}
+
struct t_nextnb
{
int nr; /* nr atoms (0 <= i < nr) (atoms->nr) */
* initiated using init_nnb.
*/
-void generate_excl(int nrexcl, int nratoms, gmx::ArrayRef<InteractionsOfType> plist, t_blocka* excl);
+void generate_excl(int nrexcl, int nratoms, gmx::ArrayRef<InteractionsOfType> plist, gmx::ListOfLists<int>* excls);
/* Generate an exclusion block from bonds and constraints in
* plist.
*/
#include "gromacs/mdlib/compute_io.h"
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdlib/perf_est.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/vsite.h"
#include "gromacs/mdrun/mdmodules.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/filestream.h"
#include "gromacs/utility/futil.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/keyvaluetreebuilder.h"
+#include "gromacs/utility/listoflists.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/mdmodulenotification.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/snprintf.h"
void MoleculeInformation::initMolInfo()
{
init_block(&mols);
- init_blocka(&excls);
+ excls.clear();
init_t_atoms(&atoms, 0, FALSE);
}
return n;
}
-static int check_atom_names(const char* fn1, const char* fn2, gmx_mtop_t* mtop, const t_atoms* at)
+static int check_atom_names(const char* fn1,
+ const char* fn2,
+ gmx_mtop_t* mtop,
+ const t_atoms* at,
+ const gmx::MDLogger& logger)
{
int m, i, j, nmismatch;
t_atoms* tat;
-#define MAXMISMATCH 20
+
+ constexpr int c_maxNumberOfMismatches = 20;
if (mtop->natoms != at->nr)
{
{
if (strcmp(*(tat->atomname[j]), *(at->atomname[i])) != 0)
{
- if (nmismatch < MAXMISMATCH)
+ if (nmismatch < c_maxNumberOfMismatches)
{
- fprintf(stderr,
- "Warning: atom name %d in %s and %s does not match (%s - %s)\n",
- i + 1, fn1, fn2, *(tat->atomname[j]), *(at->atomname[i]));
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "atom name %d in %s and %s does not match (%s - %s)", i + 1,
+ fn1, fn2, *(tat->atomname[j]), *(at->atomname[i]));
}
- else if (nmismatch == MAXMISMATCH)
+ else if (nmismatch == c_maxNumberOfMismatches)
{
- fprintf(stderr, "(more than %d non-matching atom names)\n", MAXMISMATCH);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("(more than %d non-matching atom names)",
+ c_maxNumberOfMismatches);
}
nmismatch++;
}
int i, a1, a2, w_a1, w_a2, j;
real twopi2, limit2, fc, re, m1, m2, period2, w_period2;
bool bFound, bWater, bWarn;
- char warn_buf[STRLEN];
/* Get the interaction parameters */
gmx::ArrayRef<const t_iparams> ip = mtop->ffparams.iparams;
bWarn = (w_period2 < gmx::square(min_steps_warn * dt));
/* A check that would recognize most water models */
bWater = ((*w_moltype->atoms.atomname[0])[0] == 'O' && w_moltype->atoms.nr <= 5);
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"The bond in molecule-type %s between atoms %d %s and %d %s has an estimated "
"oscillational period of %.1e ps, which is less than %d times the time step of "
"%.1e ps.\n"
: "Maybe you forgot to change the constraints mdp option.");
if (bWarn)
{
- warning(wi, warn_buf);
+ warning(wi, warningMessage.c_str());
}
else
{
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage.c_str());
}
}
}
static void check_shells_inputrec(gmx_mtop_t* mtop, t_inputrec* ir, warninp* wi)
{
- int nshells = 0;
- char warn_buf[STRLEN];
+ int nshells = 0;
for (const AtomProxy atomP : AtomRange(*mtop))
{
if ((nshells > 0) && (ir->nstcalcenergy != 1))
{
set_warning_line(wi, "unknown", -1);
- snprintf(warn_buf, STRLEN, "There are %d shells, changing nstcalcenergy from %d to 1",
- nshells, ir->nstcalcenergy);
+ std::string warningMessage = gmx::formatString(
+ "There are %d shells, changing nstcalcenergy from %d to 1", nshells, ir->nstcalcenergy);
ir->nstcalcenergy = 1;
- warning(wi, warn_buf);
+ warning(wi, warningMessage.c_str());
}
}
double* reppow,
real* fudgeQQ,
gmx_bool bMorse,
- warninp* wi)
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
std::vector<gmx_molblock_t> molblock;
int i, nmismatch;
bool ffParametrizedWithHBondConstraints;
- char buf[STRLEN];
- char warn_buf[STRLEN];
/* TOPOLOGY processing */
sys->name = do_top(bVerbose, topfile, topppfile, opts, bZero, &(sys->symtab), interactions,
comb, reppow, fudgeQQ, atypes, mi, intermolecular_interactions, ir,
- &molblock, &ffParametrizedWithHBondConstraints, wi);
+ &molblock, &ffParametrizedWithHBondConstraints, wi, logger);
sys->molblock.clear();
if (i > 0)
{
set_warning_line(wi, "unknown", -1);
- sprintf(warn_buf, "disre = no, removed %d distance restraints", i);
- warning_note(wi, warn_buf);
+ std::string warningMessage =
+ gmx::formatString("disre = no, removed %d distance restraints", i);
+ warning_note(wi, warningMessage.c_str());
}
}
if (!opts->bOrire)
if (i > 0)
{
set_warning_line(wi, "unknown", -1);
- sprintf(warn_buf, "orire = no, removed %d orientation restraints", i);
- warning_note(wi, warn_buf);
+ std::string warningMessage =
+ gmx::formatString("orire = no, removed %d orientation restraints", i);
+ warning_note(wi, warningMessage.c_str());
}
}
/* COORDINATE file processing */
if (bVerbose)
{
- fprintf(stderr, "processing coordinates...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("processing coordinates...");
}
t_topology* conftop;
/* This call fixes the box shape for runs with pressure scaling */
set_box_rel(ir, state);
- nmismatch = check_atom_names(topfile, confin, sys, &conftop->atoms);
+ nmismatch = check_atom_names(topfile, confin, sys, &conftop->atoms, logger);
done_top(conftop);
sfree(conftop);
if (nmismatch)
{
- sprintf(buf,
+ std::string warningMessage = gmx::formatString(
"%d non-matching atom name%s\n"
"atom names from %s will be used\n"
"atom names from %s will be ignored\n",
nmismatch, (nmismatch == 1) ? "" : "s", topfile, confin);
- warning(wi, buf);
+ warning(wi, warningMessage.c_str());
}
/* Do more checks, mostly related to constraints */
if (bVerbose)
{
- fprintf(stderr, "double-checking input for internal consistency...\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("double-checking input for internal consistency...");
}
{
bool bHasNormalConstraints =
if (opts->seed == -1)
{
opts->seed = static_cast<int>(gmx::makeRandomSeed());
- fprintf(stderr, "Setting gen_seed to %d\n", opts->seed);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Setting gen_seed to %d", opts->seed);
}
state->flags |= (1 << estV);
- maxwell_speed(opts->tempi, opts->seed, sys, state->v.rvec_array());
+ maxwell_speed(opts->tempi, opts->seed, sys, state->v.rvec_array(), logger);
- stop_cm(stdout, state->natoms, mass, state->x.rvec_array(), state->v.rvec_array());
+ stop_cm(logger, state->natoms, mass, state->x.rvec_array(), state->v.rvec_array());
sfree(mass);
}
}
t_inputrec* ir,
t_state* state,
gmx_mtop_t* sys,
- const gmx_output_env_t* oenv)
+ const gmx_output_env_t* oenv,
+ const gmx::MDLogger& logger)
/* If fr_time == -1 read the last frame available which is complete */
{
bool bReadVel;
bReadVel = (bNeedVel && !bGenVel);
- fprintf(stderr, "Reading Coordinates%s and Box size from old trajectory\n",
- bReadVel ? ", Velocities" : "");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Reading Coordinates%s and Box size from old trajectory",
+ bReadVel ? ", Velocities" : "");
if (fr_time == -1)
{
- fprintf(stderr, "Will read whole trajectory\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Will read whole trajectory");
}
else
{
- fprintf(stderr, "Will read till time %g\n", fr_time);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Will read till time %g", fr_time);
}
if (!bReadVel)
{
if (bGenVel)
{
- fprintf(stderr,
- "Velocities generated: "
- "ignoring velocities in input trajectory\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Velocities generated: "
+ "ignoring velocities in input trajectory");
}
read_first_frame(oenv, &fp, slog, &fr, TRX_NEED_X);
}
if (!fr.bV)
{
- fprintf(stderr,
- "\n"
- "WARNING: Did not find a frame with velocities in file %s,\n"
- " all velocities will be set to zero!\n\n",
- slog);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "WARNING: Did not find a frame with velocities in file %s,\n"
+ " all velocities will be set to zero!",
+ slog);
for (auto& vi : makeArrayRef(state->v))
{
vi = { 0, 0, 0 };
*/
set_box_rel(ir, state);
- fprintf(stderr, "Using frame at t = %g ps\n", use_time);
- fprintf(stderr, "Starting time for run is %g ps\n", ir->init_t);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Using frame at t = %g ps", use_time);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Starting time for run is %g ps", ir->init_t);
if ((ir->epc != epcNO || ir->etc == etcNOSEHOOVER) && ener)
{
gmx_bool bTopB,
const char* fn,
int rc_scaling,
- int ePBC,
+ PbcType pbcType,
rvec com,
- warninp* wi)
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
gmx_bool* hadAtom;
rvec * x, *v;
t_topology* top;
matrix box, invbox;
int natoms, npbcdim = 0;
- char warn_buf[STRLEN];
int a, nat_molb;
t_atom* atom;
sfree(top);
if (natoms != mtop->natoms)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"The number of atoms in %s (%d) does not match the number of atoms in the topology "
"(%d). Will assume that the first %d atoms in the topology and %s match.",
fn, natoms, mtop->natoms, std::min(mtop->natoms, natoms), fn);
- warning(wi, warn_buf);
+ warning(wi, warningMessage.c_str());
}
- npbcdim = ePBC2npbcdim(ePBC);
+ npbcdim = numPbcDimensions(pbcType);
GMX_RELEASE_ASSERT(npbcdim <= DIM, "Invalid npbcdim");
clear_rvec(com);
if (rc_scaling != erscNO)
{
com[j] = sum[j] / totmass;
}
- fprintf(stderr,
- "The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n",
- com[XX], com[YY], com[ZZ]);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f",
+ com[XX], com[YY], com[ZZ]);
}
if (rc_scaling != erscNO)
const char* fnA,
const char* fnB,
int rc_scaling,
- int ePBC,
+ PbcType pbcType,
rvec com,
rvec comB,
- warninp* wi)
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
- read_posres(mtop, mi, FALSE, fnA, rc_scaling, ePBC, com, wi);
+ read_posres(mtop, mi, FALSE, fnA, rc_scaling, pbcType, com, wi, logger);
/* It is safer to simply read the b-state posres rather than trying
* to be smart and copy the positions.
*/
- read_posres(mtop, mi, TRUE, fnB, rc_scaling, ePBC, comB, wi);
+ read_posres(mtop, mi, TRUE, fnB, rc_scaling, pbcType, comB, wi, logger);
}
-static void set_wall_atomtype(PreprocessingAtomTypes* at, t_gromppopts* opts, t_inputrec* ir, warninp* wi)
+static void set_wall_atomtype(PreprocessingAtomTypes* at,
+ t_gromppopts* opts,
+ t_inputrec* ir,
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
- int i;
- char warn_buf[STRLEN];
+ int i;
if (ir->nwall > 0)
{
- fprintf(stderr, "Searching the wall atom type(s)\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Searching the wall atom type(s)");
}
for (i = 0; i < ir->nwall; i++)
{
ir->wall_atomtype[i] = at->atomTypeFromName(opts->wall_atomtype[i]);
if (ir->wall_atomtype[i] == NOTSET)
{
- sprintf(warn_buf, "Specified wall atom type %s is not defined", opts->wall_atomtype[i]);
- warning_error(wi, warn_buf);
+ std::string warningMessage = gmx::formatString(
+ "Specified wall atom type %s is not defined", opts->wall_atomtype[i]);
+ warning_error(wi, warningMessage.c_str());
}
}
}
}
switch (nmass)
{
- case 0: nrdf = 0; break;
+ case 0: // Fall through intended
case 1: nrdf = 0; break;
case 2: nrdf = 1; break;
default: nrdf = nmass * 3 - 6; break;
static int count_constraints(const gmx_mtop_t* mtop, gmx::ArrayRef<const MoleculeInformation> mi, warninp* wi)
{
- int count, count_mol;
- char buf[STRLEN];
+ int count, count_mol;
count = 0;
for (const gmx_molblock_t& molb : mtop->molblock)
if (count_mol > nrdf_internal(&mi[molb.type].atoms))
{
- sprintf(buf,
+ std::string warningMessage = gmx::formatString(
"Molecule type '%s' has %d constraints.\n"
"For stability and efficiency there should not be more constraints than "
"internal number of degrees of freedom: %d.\n",
*mi[molb.type].name, count_mol, nrdf_internal(&mi[molb.type].atoms));
- warning(wi, buf);
+ warning(wi, warningMessage.c_str());
}
count += molb.nmol * count_mol;
}
if (bNoCoupl)
{
- char buf[STRLEN];
-
- sprintf(buf,
+ std::string warningMessage = gmx::formatString(
"Some temperature coupling groups do not use temperature coupling. We will assume "
"their temperature is not more than %.3f K. If their temperature is higher, the "
"energy error and the Verlet buffer might be underestimated.",
ref_t);
- warning(wi, buf);
+ warning(wi, warningMessage.c_str());
}
return ref_t;
/* Checks if there are unbound atoms in moleculetype molt.
* Prints a note for each unbound atoms and a warning if any is present.
*/
-static void checkForUnboundAtoms(const gmx_moltype_t* molt, gmx_bool bVerbose, warninp* wi)
+static void checkForUnboundAtoms(const gmx_moltype_t* molt, gmx_bool bVerbose, warninp* wi, const gmx::MDLogger& logger)
{
const t_atoms* atoms = &molt->atoms;
{
if (bVerbose)
{
- fprintf(stderr,
- "\nAtom %d '%s' in moleculetype '%s' is not bound by a potential or "
- "constraint to any other atom in the same moleculetype.\n",
- a + 1, *atoms->atomname[a], *molt->name);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Atom %d '%s' in moleculetype '%s' is not bound by a potential or "
+ "constraint to any other atom in the same moleculetype.",
+ a + 1, *atoms->atomname[a], *molt->name);
}
numDanglingAtoms++;
}
if (numDanglingAtoms > 0)
{
- char buf[STRLEN];
- sprintf(buf,
+ std::string warningMessage = gmx::formatString(
"In moleculetype '%s' %d atoms are not bound by a potential or constraint to any "
"other atom in the same moleculetype. Although technically this might not cause "
"issues in a simulation, this often means that the user forgot to add a "
"bond/potential/constraint or put multiple molecules in the same moleculetype "
"definition by mistake. Run with -v to get information for each atom.",
*molt->name, numDanglingAtoms);
- warning_note(wi, buf);
+ warning_note(wi, warningMessage.c_str());
}
}
/* Checks all moleculetypes for unbound atoms */
-static void checkForUnboundAtoms(const gmx_mtop_t* mtop, gmx_bool bVerbose, warninp* wi)
+static void checkForUnboundAtoms(const gmx_mtop_t* mtop, gmx_bool bVerbose, warninp* wi, const gmx::MDLogger& logger)
{
for (const gmx_moltype_t& molt : mtop->moltype)
{
- checkForUnboundAtoms(&molt, bVerbose, wi);
+ checkForUnboundAtoms(&molt, bVerbose, wi, logger);
}
}
gmx::ArrayRef<const t_iparams> iparams,
real massFactorThreshold)
{
- if (molt.ilist[F_CONSTR].size() == 0 && molt.ilist[F_CONSTRNC].size() == 0)
+ if (molt.ilist[F_CONSTR].empty() && molt.ilist[F_CONSTRNC].empty())
{
return false;
}
const t_atom* atom = molt.atoms.atom;
- t_blocka atomToConstraints =
+ const auto atomToConstraints =
gmx::make_at2con(molt, iparams, gmx::FlexibleConstraintTreatment::Exclude);
bool haveDecoupledMode = false;
int a1 = il.iatoms[1 + i + 1];
int a2 = il.iatoms[1 + i + 2];
if ((atom[a0].m > atom[a2].m * massFactorThreshold || atom[a2].m > atom[a0].m * massFactorThreshold)
- && atomToConstraints.index[a0 + 1] - atomToConstraints.index[a0] == 1
- && atomToConstraints.index[a2 + 1] - atomToConstraints.index[a2] == 1
- && atomToConstraints.index[a1 + 1] - atomToConstraints.index[a1] >= 3)
+ && atomToConstraints[a0].ssize() == 1 && atomToConstraints[a2].ssize() == 1
+ && atomToConstraints[a1].ssize() >= 3)
{
- int constraint0 = atomToConstraints.a[atomToConstraints.index[a0]];
- int constraint2 = atomToConstraints.a[atomToConstraints.index[a2]];
+ int constraint0 = atomToConstraints[a0][0];
+ int constraint2 = atomToConstraints[a2][0];
bool foundAtom0 = false;
bool foundAtom2 = false;
- for (int conIndex = atomToConstraints.index[a1];
- conIndex < atomToConstraints.index[a1 + 1]; conIndex++)
+ for (const int constraint : atomToConstraints[a1])
{
- if (atomToConstraints.a[conIndex] == constraint0)
+ if (constraint == constraint0)
{
foundAtom0 = true;
}
- if (atomToConstraints.a[conIndex] == constraint2)
+ if (constraint == constraint2)
{
foundAtom2 = true;
}
}
}
- done_blocka(&atomToConstraints);
-
return haveDecoupledMode;
}
}
}
-static void set_verlet_buffer(const gmx_mtop_t* mtop, t_inputrec* ir, real buffer_temp, matrix box, warninp* wi)
+static void set_verlet_buffer(const gmx_mtop_t* mtop,
+ t_inputrec* ir,
+ real buffer_temp,
+ matrix box,
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
- char warn_buf[STRLEN];
-
- printf("Determining Verlet buffer for a tolerance of %g kJ/mol/ps at %g K\n", ir->verletbuf_tol,
- buffer_temp);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Determining Verlet buffer for a tolerance of %g kJ/mol/ps at %g K",
+ ir->verletbuf_tol, buffer_temp);
/* Calculate the buffer size for simple atom vs atoms list */
VerletbufListSetup listSetup1x1;
const int n_nonlin_vsite = countNonlinearVsites(*mtop);
if (n_nonlin_vsite > 0)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"There are %d non-linear virtual site constructions. Their contribution to the "
"energy error is approximated. In most cases this does not affect the error "
"significantly.",
n_nonlin_vsite);
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
- printf("Calculated rlist for %dx%d atom pair-list as %.3f nm, buffer size %.3f nm\n", 1, 1,
- rlist_1x1, rlist_1x1 - std::max(ir->rvdw, ir->rcoulomb));
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Calculated rlist for %dx%d atom pair-list as %.3f nm, buffer size %.3f nm", 1,
+ 1, rlist_1x1, rlist_1x1 - std::max(ir->rvdw, ir->rcoulomb));
- printf("Set rlist, assuming %dx%d atom pair-list, to %.3f nm, buffer size %.3f nm\n",
- listSetup4x4.cluster_size_i, listSetup4x4.cluster_size_j, ir->rlist,
- ir->rlist - std::max(ir->rvdw, ir->rcoulomb));
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Set rlist, assuming %dx%d atom pair-list, to %.3f nm, buffer size %.3f nm",
+ listSetup4x4.cluster_size_i, listSetup4x4.cluster_size_j, ir->rlist,
+ ir->rlist - std::max(ir->rvdw, ir->rcoulomb));
- printf("Note that mdrun will redetermine rlist based on the actual pair-list setup\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Note that mdrun will redetermine rlist based on the actual pair-list setup");
- if (gmx::square(ir->rlist) >= max_cutoff2(ir->ePBC, box))
+ if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
{
gmx_fatal(FARGS,
"The pair-list cut-off (%g nm) is longer than half the shortest box vector or "
"longer than the smallest box diagonal element (%g nm). Increase the box size or "
"decrease nstlist or increase verlet-buffer-tolerance.",
- ir->rlist, std::sqrt(max_cutoff2(ir->ePBC, box)));
+ ir->rlist, std::sqrt(max_cutoff2(ir->pbcType, box)));
}
}
double reppow;
const char* mdparin;
bool bNeedVel, bGenVel;
- gmx_bool have_atomnumber;
gmx_output_env_t* oenv;
gmx_bool bVerbose = FALSE;
warninp* wi;
- char warn_buf[STRLEN];
t_filenm fnm[] = { { efMDP, nullptr, nullptr, ffREAD },
{ efMDP, "-po", "mdout", ffWRITE },
{ efEDR, "-e", nullptr, ffOPTRD },
/* This group is needed by the VMD viewer as the start configuration for IMD sessions: */
{ efGRO, "-imd", "imdgroup", ffOPTWR },
- { efTRN, "-ref", "rotref", ffOPTRW } };
+ { efTRN, "-ref", "rotref", ffOPTRW | ffALLOW_MISSING } };
#define NFILE asize(fnm)
/* Command line options */
snew(opts->include, STRLEN);
snew(opts->define, STRLEN);
+ gmx::LoggerBuilder builder;
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Info, &gmx::TextOutputFile::standardOutput());
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Warning, &gmx::TextOutputFile::standardError());
+ gmx::LoggerOwner logOwner(builder.build());
+ const gmx::MDLogger logger(logOwner.logger());
+
+
wi = init_warning(TRUE, maxwarn);
/* PARAMETER file processing */
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+ // Now that the MdModules have their options assigned from get_ir, subscribe
+ // to eventual notifications during pre-processing their data
+ mdModules.subscribeToPreProcessingNotifications();
+
+
if (bVerbose)
{
- fprintf(stderr, "checking input for internal consistency...\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("checking input for internal consistency...");
}
check_ir(mdparin, mdModules.notifier(), ir, opts, wi);
if (ir->ld_seed == -1)
{
ir->ld_seed = static_cast<int>(gmx::makeRandomSeed());
- fprintf(stderr, "Setting the LD random seed to %" PRId64 "\n", ir->ld_seed);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Setting the LD random seed to %" PRId64 "", ir->ld_seed);
}
if (ir->expandedvals->lmc_seed == -1)
{
ir->expandedvals->lmc_seed = static_cast<int>(gmx::makeRandomSeed());
- fprintf(stderr, "Setting the lambda MC random seed to %d\n", ir->expandedvals->lmc_seed);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Setting the lambda MC random seed to %d", ir->expandedvals->lmc_seed);
}
bNeedVel = EI_STATE_VELOCITY(ir->eI);
bGenVel = (bNeedVel && opts->bGenVel);
if (bGenVel && ir->bContinuation)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"Generating velocities is inconsistent with attempting "
"to continue a previous run. Choose only one of "
"gen-vel = yes and continuation = yes.");
- warning_error(wi, warn_buf);
+ warning_error(wi, warningMessage);
}
std::array<InteractionsOfType, F_NRE> interactions;
t_state state;
new_status(fn, opt2fn_null("-pp", NFILE, fnm), opt2fn("-c", NFILE, fnm), opts, ir, bZero,
bGenVel, bVerbose, &state, &atypes, &sys, &mi, &intermolecular_interactions,
- interactions, &comb, &reppow, &fudgeQQ, opts->bMorse, wi);
+ interactions, &comb, &reppow, &fudgeQQ, opts->bMorse, wi, logger);
if (debug)
{
/* set parameters for virtual site construction (not for vsiten) */
for (size_t mt = 0; mt < sys.moltype.size(); mt++)
{
- nvsite += set_vsites(bVerbose, &sys.moltype[mt].atoms, &atypes, mi[mt].interactions);
+ nvsite += set_vsites(bVerbose, &sys.moltype[mt].atoms, &atypes, mi[mt].interactions, logger);
}
/* now throw away all obsolete bonds, angles and dihedrals: */
/* note: constraints are ALWAYS removed */
{
for (size_t mt = 0; mt < sys.moltype.size(); mt++)
{
- clean_vsite_bondeds(mi[mt].interactions, sys.moltype[mt].atoms.nr, bRmVSBds);
+ clean_vsite_bondeds(mi[mt].interactions, sys.moltype[mt].atoms.nr, bRmVSBds, logger);
}
}
{
if (ir->eI == eiCG || ir->eI == eiLBFGS)
{
- sprintf(warn_buf, "Can not do %s with %s, use %s", EI(ir->eI),
- econstr_names[econtSHAKE], econstr_names[econtLINCS]);
- warning_error(wi, warn_buf);
+ std::string warningMessage =
+ gmx::formatString("Can not do %s with %s, use %s", EI(ir->eI),
+ econstr_names[econtSHAKE], econstr_names[econtLINCS]);
+ warning_error(wi, warningMessage);
}
if (ir->bPeriodicMols)
{
- sprintf(warn_buf, "Can not do periodic molecules with %s, use %s",
- econstr_names[econtSHAKE], econstr_names[econtLINCS]);
- warning_error(wi, warn_buf);
+ std::string warningMessage =
+ gmx::formatString("Can not do periodic molecules with %s, use %s",
+ econstr_names[econtSHAKE], econstr_names[econtLINCS]);
+ warning_error(wi, warningMessage);
}
}
warning_note(wi, "Temperature coupling is ignored with SD integrators.");
}
- /* If we are doing QM/MM, check that we got the atom numbers */
- have_atomnumber = TRUE;
- for (gmx::index i = 0; i < gmx::ssize(atypes); i++)
- {
- have_atomnumber = have_atomnumber && (atypes.atomNumberFromAtomType(i) >= 0);
- }
- if (!have_atomnumber && ir->bQMMM)
- {
- warning_error(
- wi,
- "\n"
- "It appears as if you are trying to run a QM/MM calculation, but the force\n"
- "field you are using does not contain atom numbers fields. This is an\n"
- "optional field (introduced in GROMACS 3.3) for general runs, but mandatory\n"
- "for QM/MM. The good news is that it is easy to add - put the atom number as\n"
- "an integer just before the mass column in ffXXXnb.itp.\n"
- "NB: United atoms have the same atom numbers as normal ones.\n\n");
- }
-
/* Check for errors in the input now, since they might cause problems
* during processing further down.
*/
{
if (ir->epc == epcPARRINELLORAHMAN || ir->epc == epcMTTK)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"You are combining position restraints with %s pressure coupling, which can "
"lead to instabilities. If you really want to combine position restraints with "
"pressure coupling, we suggest to use %s pressure coupling instead.",
EPCOUPLTYPE(ir->epc), EPCOUPLTYPE(epcBERENDSEN));
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
const char* fn = opt2fn("-r", NFILE, fnm);
if (bVerbose)
{
- fprintf(stderr, "Reading position restraint coords from %s", fn);
- if (strcmp(fn, fnB) == 0)
- {
- fprintf(stderr, "\n");
- }
- else
+ std::string message = gmx::formatString("Reading position restraint coords from %s", fn);
+ if (strcmp(fn, fnB) != 0)
{
- fprintf(stderr, " and %s\n", fnB);
+ message += gmx::formatString(" and %s", fnB);
}
+ GMX_LOG(logger.info).asParagraph().appendText(message);
}
- gen_posres(&sys, mi, fn, fnB, ir->refcoord_scaling, ir->ePBC, ir->posres_com, ir->posres_comB, wi);
+ gen_posres(&sys, mi, fn, fnB, ir->refcoord_scaling, ir->pbcType, ir->posres_com,
+ ir->posres_comB, wi, logger);
}
/* If we are using CMAP, setup the pre-interpolation grid */
interactions[F_CMAP].cmap, &sys.ffparams.cmap_grid);
}
- set_wall_atomtype(&atypes, opts, ir, wi);
+ set_wall_atomtype(&atypes, opts, ir, wi, logger);
if (bRenum)
{
atypes.renumberTypes(interactions, &sys, ir->wall_atomtype, bVerbose);
if (bVerbose)
{
- fprintf(stderr, "converting bonded parameters...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("converting bonded parameters...");
}
const int ntype = atypes.size();
/* set ptype to VSite for virtual sites */
for (gmx_moltype_t& moltype : sys.moltype)
{
- set_vsites_ptype(FALSE, &moltype);
+ set_vsites_ptype(FALSE, &moltype, logger);
}
if (debug)
{
/* check masses */
check_mol(&sys, wi);
- checkForUnboundAtoms(&sys, bVerbose, wi);
+ checkForUnboundAtoms(&sys, bVerbose, wi, logger);
if (EI_DYNAMICS(ir->eI) && ir->eI != eiBD)
{
if (bVerbose)
{
- fprintf(stderr, "initialising group options...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("initialising group options...");
}
do_index(mdparin, ftp2fn_null(efNDX, NFILE, fnm), &sys, bVerbose, mdModules.notifier(), ir, wi);
}
if (buffer_temp > 0)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"NVE simulation: will use the initial temperature of %.3f K for "
"determining the Verlet buffer size",
buffer_temp);
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
else
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"NVE simulation with an initial temperature of zero: will use a Verlet "
"buffer of %d%%. Check your energy drift!",
gmx::roundToInt(verlet_buffer_ratio_NVE_T0 * 100));
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
}
else
if (ir->verletbuf_tol > 1.1 * driftTolerance * totalEnergyDriftPerAtomPerPicosecond)
{
- sprintf(warn_buf,
+ std::string warningMessage = gmx::formatString(
"You are using a Verlet buffer tolerance of %g kJ/mol/ps for an "
"NVE simulation of length %g ps, which can give a final drift of "
"%d%%. For conserving energy to %d%% when using constraints, you "
gmx::roundToInt(ir->verletbuf_tol / totalEnergyDriftPerAtomPerPicosecond * 100),
gmx::roundToInt(100 * driftTolerance),
driftTolerance * totalEnergyDriftPerAtomPerPicosecond);
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
}
- set_verlet_buffer(&sys, ir, buffer_temp, state.box, wi);
+ set_verlet_buffer(&sys, ir, buffer_temp, state.box, wi, logger);
}
}
}
pr_symtab(debug, 0, "After close", &sys.symtab);
}
- /* make exclusions between QM atoms and remove charges if needed */
- if (ir->bQMMM)
- {
- generate_qmexcl(&sys, ir, wi, GmxQmmmMode::GMX_QMMM_ORIGINAL);
- if (ir->QMMMscheme != eQMMMschemeoniom)
- {
- std::vector<int> qmmmAtoms = qmmmAtomIndices(*ir, sys);
- removeQmmmAtomCharges(&sys, qmmmAtoms);
- }
- }
-
if (ir->eI == eiMimic)
{
- generate_qmexcl(&sys, ir, wi, GmxQmmmMode::GMX_QMMM_MIMIC);
+ generate_qmexcl(&sys, ir, logger);
}
if (ftp2bSet(efTRN, NFILE, fnm))
{
if (bVerbose)
{
- fprintf(stderr, "getting data from old trajectory ...\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("getting data from old trajectory ...");
}
cont_status(ftp2fn(efTRN, NFILE, fnm), ftp2fn_null(efEDR, NFILE, fnm), bNeedVel, bGenVel,
- fr_time, ir, &state, &sys, oenv);
+ fr_time, ir, &state, &sys, oenv, logger);
}
- if (ir->ePBC == epbcXY && ir->nwall != 2)
+ if (ir->pbcType == PbcType::XY && ir->nwall != 2)
{
clear_rvec(state.box[ZZ]);
}
{
copy_mat(ir->compress, compressibility);
}
- setStateDependentAwhParams(ir->awhParams, ir->pull, pull, state.box, ir->ePBC,
+ setStateDependentAwhParams(ir->awhParams, ir->pull, pull, state.box, ir->pbcType,
compressibility, &ir->opts, wi);
}
if (EEL_PME(ir->coulombtype))
{
float ratio = pme_load_estimate(sys, *ir, state.box);
- fprintf(stderr, "Estimate for the relative computational load of the PME mesh part: %.2f\n", ratio);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Estimate for the relative computational load of the PME mesh part: %.2f", ratio);
/* With free energy we might need to do PME both for the A and B state
* charges. This will double the cost, but the optimal performance will
* then probably be at a slightly larger cut-off and grid spacing.
}
{
- char warn_buf[STRLEN];
- double cio = compute_io(ir, sys.natoms, sys.groups, F_NRE, 1);
- sprintf(warn_buf, "This run will generate roughly %.0f Mb of data", cio);
+ double cio = compute_io(ir, sys.natoms, sys.groups, F_NRE, 1);
+ std::string warningMessage =
+ gmx::formatString("This run will generate roughly %.0f Mb of data", cio);
if (cio > 2000)
{
set_warning_line(wi, mdparin, -1);
- warning_note(wi, warn_buf);
+ warning_note(wi, warningMessage);
}
else
{
- printf("%s\n", warn_buf);
+ GMX_LOG(logger.info).asParagraph().appendText(warningMessage);
}
}
{
gmx::KeyValueTreeBuilder internalParameterBuilder;
- mdModules.notifier().notifier_.notify(internalParameterBuilder.rootObject());
+ mdModules.notifier().preProcessingNotifications_.notify(internalParameterBuilder.rootObject());
ir->internalParameters =
std::make_unique<gmx::KeyValueTreeObject>(internalParameterBuilder.build());
}
if (bVerbose)
{
- fprintf(stderr, "writing run input file...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("writing run input file...");
}
done_warning(wi, FARGS);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/real.h"
/*! \libinternal \brief
//! Molecules separated in datastructure.
t_block mols;
//! Exclusions in the molecule.
- t_blocka excls;
+ gmx::ListOfLists<int> excls;
//! Interactions of a defined type.
std::array<InteractionsOfType, F_NRE> interactions;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/topology.h"
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
using gmx::RVec;
/* enum for random rotations of inserted solutes */
-enum RotationType
+enum class RotationType : int
{
- en_rotXYZ,
- en_rotZ,
- en_rotNone
+ XYZ,
+ Z,
+ None,
+ Count
};
-const char* const cRotationEnum[] = { "xyz", "z", "none" };
+static const gmx::EnumerationArray<RotationType, const char*> c_rotationTypeNames = { { "xyz", "z",
+ "none" } };
static void center_molecule(gmx::ArrayRef<RVec> x)
{
real alfa = 0.0, beta = 0.0, gamma = 0.0;
switch (enum_rot)
{
- case en_rotXYZ:
+ case RotationType::XYZ:
alfa = dist(*rng);
beta = dist(*rng);
gamma = dist(*rng);
break;
- case en_rotZ:
+ case RotationType::Z:
alfa = beta = 0.;
gamma = dist(*rng);
break;
- case en_rotNone: alfa = beta = gamma = 0.; break;
+ case RotationType::None: alfa = beta = gamma = 0.; break;
+ default: GMX_THROW(gmx::InternalError("Invalid RotationType"));
}
- if (enum_rot == en_rotXYZ || enum_rot == en_rotZ)
+ if (enum_rot == RotationType::XYZ || enum_rot == RotationType::Z)
{
rotate_conf(xout->size(), as_rvec_array(xout->data()), nullptr, alfa, beta, gamma);
}
const std::set<int>& removableAtoms,
const t_atoms& atoms_insrt,
gmx::ArrayRef<RVec> x_insrt,
- int ePBC,
+ PbcType pbcType,
matrix box,
const std::string& posfn,
const rvec deltaR,
gmx::DefaultRandomEngine rng(seed);
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
/* With -ip, take nmol_insrt from file posfn */
double** rpos = nullptr;
seed_(0),
defaultDistance_(0.105),
scaleFactor_(0.57),
- enumRot_(en_rotXYZ)
+ enumRot_(RotationType::XYZ)
{
clear_rvec(newBox_);
clear_rvec(deltaR_);
gmx_mtop_t top_;
std::vector<RVec> x_;
matrix box_;
- int ePBC_;
+ PbcType pbcType_;
};
void InsertMolecules::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings)
options->addOption(RealOption("dr").vector().store(deltaR_).description(
"Allowed displacement in x/y/z from positions in [TT]-ip[tt] file"));
options->addOption(EnumOption<RotationType>("rot")
- .enumValue(cRotationEnum)
+ .enumValue(c_rotationTypeNames)
.store(&enumRot_)
.description("Rotate inserted molecules randomly"));
}
bool bTprFileWasRead;
rvec* temporaryX = nullptr;
fprintf(stderr, "Reading solute configuration\n");
- readConfAndTopology(inputConfFile_.c_str(), &bTprFileWasRead, &top_, &ePBC_, &temporaryX,
+ readConfAndTopology(inputConfFile_.c_str(), &bTprFileWasRead, &top_, &pbcType_, &temporaryX,
nullptr, box_);
x_.assign(temporaryX, temporaryX + top_.natoms);
sfree(temporaryX);
if (replaceSel_.isValid())
{
t_pbc pbc;
- set_pbc(&pbc, ePBC_, box_);
+ set_pbc(&pbc, pbcType_, box_);
t_trxframe* fr;
snew(fr, 1);
fr->natoms = x_.size();
// individual atoms.
}
- int ePBCForOutput = ePBC_;
+ PbcType pbcTypeForOutput = pbcType_;
if (bBox_)
{
- ePBCForOutput = epbcXYZ;
+ pbcTypeForOutput = PbcType::Xyz;
clear_mat(box_);
box_[XX][XX] = newBox_[XX];
box_[YY][YY] = newBox_[YY];
t_atoms atomsInserted;
std::vector<RVec> xInserted;
{
- bool bTprFileWasRead;
- int ePBC_dummy;
- matrix box_dummy;
- rvec* temporaryX;
- readConfAndTopology(insertConfFile_.c_str(), &bTprFileWasRead, &topInserted, &ePBC_dummy,
+ bool bTprFileWasRead;
+ PbcType pbcType_dummy;
+ matrix box_dummy;
+ rvec* temporaryX;
+ readConfAndTopology(insertConfFile_.c_str(), &bTprFileWasRead, &topInserted, &pbcType_dummy,
&temporaryX, nullptr, box_dummy);
xInserted.assign(temporaryX, temporaryX + topInserted.natoms);
sfree(temporaryX);
/* add nmol_ins molecules of atoms_ins
in random orientation at random place */
insert_mols(nmolIns_, nmolTry_, seed_, defaultDistance_, scaleFactor_, &atoms, &top_.symtab,
- &x_, removableAtoms, atomsInserted, xInserted, ePBCForOutput, box_, positionFile_,
- deltaR_, enumRot_);
+ &x_, removableAtoms, atomsInserted, xInserted, pbcTypeForOutput, box_,
+ positionFile_, deltaR_, enumRot_);
/* write new configuration to file confout */
fprintf(stderr, "Writing generated configuration to %s\n", outputConfFile_.c_str());
write_sto_conf(outputConfFile_.c_str(), *top_.name, &atoms, as_rvec_array(x_.data()), nullptr,
- ePBCForOutput, box_);
+ pbcTypeForOutput, box_);
/* print size of generated configuration */
fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n", atoms.nr, atoms.nres);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
static int match_str(const char* atom, const char* template_string)
{
if (!atom || !template_string)
- {
+ { // NOLINT bugprone-branch-clone
return ematchNone;
}
else if (gmx_strcasecmp(atom, template_string) == 0)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/dir_separator.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/filestream.h"
+#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/path.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strdb.h"
gmx::ArrayRef<const int> r_end,
gmx::ArrayRef<const RtpRename> rr,
t_symtab* symtab,
- bool bVerbose)
+ bool bVerbose,
+ const gmx::MDLogger& logger)
{
bool bFFRTPTERRNM = (getenv("GMX_NO_FFRTP_TER_RENAME") == nullptr);
{
if (bVerbose)
{
- printf("Changing rtp entry of residue %d %s to '%s'\n", pdba->resinfo[r].nr,
- *pdba->resinfo[r].name, newName.c_str());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Changing rtp entry of residue %d %s to '%s'",
+ pdba->resinfo[r].nr, *pdba->resinfo[r].name,
+ newName.c_str());
}
pdba->resinfo[r].rtp = put_symtab(symtab, newName.c_str());
}
}
}
-static void check_occupancy(t_atoms* atoms, const char* filename, bool bVerbose)
+static void check_occupancy(t_atoms* atoms, const char* filename, bool bVerbose, const gmx::MDLogger& logger)
{
int i, ftp;
int nzero = 0;
ftp = fn2ftp(filename);
if (!atoms->pdbinfo || ((ftp != efPDB) && (ftp != efBRK) && (ftp != efENT)))
{
- fprintf(stderr, "No occupancies in %s\n", filename);
+ GMX_LOG(logger.warning).asParagraph().appendTextFormatted("No occupancies in %s", filename);
}
else
{
{
if (bVerbose)
{
- fprintf(stderr, "Occupancy for atom %s%d-%s is %f rather than 1\n",
- *atoms->resinfo[atoms->atom[i].resind].name,
- atoms->resinfo[atoms->atom[i].resind].nr, *atoms->atomname[i],
- atoms->pdbinfo[i].occup);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("Occupancy for atom %s%d-%s is %f rather than 1",
+ *atoms->resinfo[atoms->atom[i].resind].name,
+ atoms->resinfo[atoms->atom[i].resind].nr,
+ *atoms->atomname[i], atoms->pdbinfo[i].occup);
}
if (atoms->pdbinfo[i].occup == 0)
{
}
if (nzero == atoms->nr)
{
- fprintf(stderr, "All occupancy fields zero. This is probably not an X-Ray structure\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "All occupancy fields zero. This is probably not an X-Ray structure");
}
else if ((nzero > 0) || (nnotone > 0))
{
- fprintf(stderr,
- "\n"
- "WARNING: there were %d atoms with zero occupancy and %d atoms with\n"
- " occupancy unequal to one (out of %d atoms). Check your pdb file.\n"
- "\n",
- nzero, nnotone, atoms->nr);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "there were %d atoms with zero occupancy and %d atoms with "
+ " occupancy unequal to one (out of %d atoms). Check your pdb "
+ "file.",
+ nzero, nnotone, atoms->nr);
}
else
{
- fprintf(stderr, "All occupancies are one\n");
+ GMX_LOG(logger.warning).asParagraph().appendTextFormatted("All occupancies are one");
}
}
}
char** title,
t_atoms* atoms,
rvec** x,
- int* ePBC,
+ PbcType* pbcType,
matrix box,
bool bRemoveH,
t_symtab* symtab,
/* READ IT */
printf("Reading %s...\n", inf);
- readConfAndAtoms(inf, symtab, title, atoms, ePBC, x, nullptr, box);
+ readConfAndAtoms(inf, symtab, title, atoms, pbcType, x, nullptr, box);
natom = atoms->nr;
if (atoms->pdbinfo == nullptr)
{
}
if (bOutput)
{
- write_sto_conf(outf, *title, atoms, *x, nullptr, *ePBC, box);
+ write_sto_conf(outf, *title, atoms, *x, nullptr, *pbcType, box);
}
return natom;
[&atomnm](char** it) { return gmx::equalCaseInsensitive(atomnm, *it); });
if (found == localPpResidue->atomname.end())
{
- char buf[STRLEN];
-
- sprintf(buf,
+ std::string buf = gmx::formatString(
"Atom %s in residue %s %d was not found in rtp entry %s with %d atoms\n"
"while sorting atoms.\n%s",
atomnm, *pdba->resinfo[pdba->atom[i].resind].name,
"solve it.\n"
"Option -ignh will ignore all hydrogens in the input."
: ".");
- gmx_fatal(FARGS, "%s", buf);
+ gmx_fatal(FARGS, "%s", buf.c_str());
}
/* make shadow array to be sorted into indexgroup */
pdbi[i].resnr = pdba->atom[i].resind;
sfree(pdbi);
}
-static int remove_duplicate_atoms(t_atoms* pdba, gmx::ArrayRef<gmx::RVec> x, bool bVerbose)
+static int remove_duplicate_atoms(t_atoms* pdba, gmx::ArrayRef<gmx::RVec> x, bool bVerbose, const gmx::MDLogger& logger)
{
int i, j, oldnatoms, ndel;
t_resinfo* ri;
- printf("Checking for duplicate atoms....\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Checking for duplicate atoms....");
oldnatoms = pdba->nr;
ndel = 0;
/* NOTE: pdba->nr is modified inside the loop */
if (bVerbose)
{
ri = &pdba->resinfo[pdba->atom[i].resind];
- printf("deleting duplicate atom %4s %s%4d%c", *pdba->atomname[i], *ri->name,
- ri->nr, ri->ic);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("deleting duplicate atom %4s %s%4d%c",
+ *pdba->atomname[i], *ri->name, ri->nr, ri->ic);
if (ri->chainid && (ri->chainid != ' '))
{
printf(" ch %c", ri->chainid);
}
if (pdba->nr != oldnatoms)
{
- printf("Now there are %d atoms. Deleted %d duplicates.\n", pdba->nr, ndel);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Now there are %d atoms. Deleted %d duplicates.", pdba->nr, ndel);
}
return pdba->nr;
}
}
-static void find_nc_ter(t_atoms* pdba, int r0, int r1, int* r_start, int* r_end, ResidueType* rt)
+static void find_nc_ter(t_atoms* pdba, int r0, int r1, int* r_start, int* r_end, ResidueType* rt, const gmx::MDLogger& logger)
{
- int i;
- gmx::compat::optional<std::string> startrestype;
+ int i;
+ std::optional<std::string> startrestype;
*r_start = -1;
*r_end = -1;
|| gmx::equalCaseInsensitive(*startrestype, "DNA")
|| gmx::equalCaseInsensitive(*startrestype, "RNA"))
{
- printf("Identified residue %s%d as a starting terminus.\n", *pdba->resinfo[i].name,
- pdba->resinfo[i].nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Identified residue %s%d as a starting terminus.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr);
*r_start = i;
}
else if (gmx::equalCaseInsensitive(*startrestype, "Ion"))
{
if (ionNotes < 5)
{
- printf("Residue %s%d has type 'Ion', assuming it is not linked into a chain.\n",
- *pdba->resinfo[i].name, pdba->resinfo[i].nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Residue %s%d has type 'Ion', assuming it is not linked into a "
+ "chain.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr);
}
if (ionNotes == 4)
{
- printf("Disabling further notes about ions.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Disabling further notes about ions.");
}
ionNotes++;
}
{
if (chainID == ' ')
{
- printf("\nWarning: Starting residue %s%d in chain not identified as "
- "Protein/RNA/DNA.\n"
- "This chain lacks identifiers, which makes it impossible to do strict\n"
- "classification of the start/end residues. Here we need to guess this "
- "residue\n"
- "should not be part of the chain and instead introduce a break, but "
- "that will\n"
- "be catastrophic if they should in fact be linked. Please check your "
- "structure,\n"
- "and add %s to residuetypes.dat if this was not correct.\n\n",
- *pdba->resinfo[i].name, pdba->resinfo[i].nr, *pdba->resinfo[i].name);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Starting residue %s%d in chain not identified as "
+ "Protein/RNA/DNA. "
+ "This chain lacks identifiers, which makes it impossible to do "
+ "strict "
+ "classification of the start/end residues. Here we need to "
+ "guess this residue "
+ "should not be part of the chain and instead introduce a "
+ "break, but that will "
+ "be catastrophic if they should in fact be linked. Please "
+ "check your structure, "
+ "and add %s to residuetypes.dat if this was not correct.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr, *pdba->resinfo[i].name);
}
else
{
- printf("\nWarning: No residues in chain starting at %s%d identified as "
- "Protein/RNA/DNA.\n"
- "This makes it impossible to link them into a molecule, which could "
- "either be\n"
- "correct or a catastrophic error. Please check your structure, and add "
- "all\n"
- "necessary residue names to residuetypes.dat if this was not "
- "correct.\n\n",
- *pdba->resinfo[i].name, pdba->resinfo[i].nr);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "No residues in chain starting at %s%d identified as "
+ "Protein/RNA/DNA. "
+ "This makes it impossible to link them into a molecule, which "
+ "could either be "
+ "correct or a catastrophic error. Please check your structure, "
+ "and add all "
+ "necessary residue names to residuetypes.dat if this was not "
+ "correct.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr);
}
}
if (startWarnings == 4)
{
- printf("Disabling further warnings about unidentified residues at start of "
- "chain.\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Disabling further warnings about unidentified residues at start "
+ "of chain.");
}
startWarnings++;
}
/* Go through the rest of the residues, check that they are the same class, and identify the ending terminus. */
for (int i = *r_start; i < r1; i++)
{
- gmx::compat::optional<std::string> restype =
+ std::optional<std::string> restype =
rt->optionalTypeOfNamedDatabaseResidue(*pdba->resinfo[i].name);
if (!restype)
{
{
if (ionNotes < 5)
{
- printf("Residue %s%d has type 'Ion', assuming it is not linked into a chain.\n",
- *pdba->resinfo[i].name, pdba->resinfo[i].nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Residue %s%d has type 'Ion', assuming it is not linked into a "
+ "chain.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr);
}
if (ionNotes == 4)
{
- printf("Disabling further notes about ions.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Disabling further notes about ions.");
}
ionNotes++;
}
// have caught the problem.
if (endWarnings < 5)
{
- printf("\nWarning: Residue %s%d in chain has different type ('%s') from\n"
- "residue %s%d ('%s'). This chain lacks identifiers, which makes\n"
- "it impossible to do strict classification of the start/end residues. "
- "Here we\n"
- "need to guess this residue should not be part of the chain and "
- "instead\n"
- "introduce a break, but that will be catastrophic if they should in "
- "fact be\n"
- "linked. Please check your structure, and add %s to residuetypes.dat\n"
- "if this was not correct.\n\n",
- *pdba->resinfo[i].name, pdba->resinfo[i].nr, restype->c_str(),
- *pdba->resinfo[*r_start].name, pdba->resinfo[*r_start].nr,
- startrestype->c_str(), *pdba->resinfo[i].name);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Residue %s%d in chain has different type ('%s') from "
+ "residue %s%d ('%s'). This chain lacks identifiers, which "
+ "makes "
+ "it impossible to do strict classification of the start/end "
+ "residues. Here we "
+ "need to guess this residue should not be part of the chain "
+ "and instead "
+ "introduce a break, but that will be catastrophic if they "
+ "should in fact be "
+ "linked. Please check your structure, and add %s to "
+ "residuetypes.dat "
+ "if this was not correct.",
+ *pdba->resinfo[i].name, pdba->resinfo[i].nr, restype->c_str(),
+ *pdba->resinfo[*r_start].name, pdba->resinfo[*r_start].nr,
+ startrestype->c_str(), *pdba->resinfo[i].name);
}
if (endWarnings == 4)
{
- printf("Disabling further warnings about unidentified residues at end of "
- "chain.\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Disabling further warnings about unidentified residues at end "
+ "of chain.");
}
endWarnings++;
}
if (*r_end >= 0)
{
- printf("Identified residue %s%d as a ending terminus.\n", *pdba->resinfo[*r_end].name,
- pdba->resinfo[*r_end].nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Identified residue %s%d as a ending terminus.",
+ *pdba->resinfo[*r_end].name, pdba->resinfo[*r_end].nr);
}
}
-/* enum for chain separation */
-enum ChainSepType
+enum class ChainSeparationType : int
{
- enChainSep_id_or_ter,
- enChainSep_id_and_ter,
- enChainSep_ter,
- enChainSep_id,
- enChainSep_interactive
+ IdOrTer,
+ IdAndTer,
+ Ter,
+ Id,
+ Interactive,
+ Count
+};
+static const gmx::EnumerationArray<ChainSeparationType, const char*> c_chainSeparationTypeNames = {
+ { "id_or_ter", "id_and_ter", "ter", "id", "interactive" }
};
-static const char* ChainSepEnum[] = { "id_or_ter", "id_and_ter", "ter", "id", "interactive" };
-static const char* ChainSepInfoString[] = {
- "Splitting chemical chains based on TER records or chain id changing.\n",
- "Splitting chemical chains based on TER records and chain id changing.\n",
- "Splitting chemical chains based on TER records only (ignoring chain id).\n",
- "Splitting chemical chains based on changing chain id only (ignoring TER records).\n",
- "Splitting chemical chains interactively.\n"
+static const gmx::EnumerationArray<ChainSeparationType, const char*> c_chainSeparationTypeNotificationMessages = {
+ { "Splitting chemical chains based on TER records or chain id changing.\n",
+ "Splitting chemical chains based on TER records and chain id changing.\n",
+ "Splitting chemical chains based on TER records only (ignoring chain id).\n",
+ "Splitting chemical chains based on changing chain id only (ignoring TER records).\n",
+ "Splitting chemical chains interactively.\n" }
};
-static void modify_chain_numbers(t_atoms* pdba, ChainSepType enumChainSep)
+static void modify_chain_numbers(t_atoms* pdba, ChainSeparationType chainSeparation, const gmx::MDLogger& logger)
{
int i;
char old_prev_chainid;
char this_chainid;
/* The default chain enumeration is based on TER records only */
- printf("%s", ChainSepInfoString[enumChainSep]);
+ printf("%s", c_chainSeparationTypeNotificationMessages[chainSeparation]);
old_prev_chainid = '?';
old_prev_chainnum = -1;
this_resnum = ri->nr;
this_chainid = ri->chainid;
- switch (enumChainSep)
+ switch (chainSeparation)
{
- case enChainSep_id_or_ter:
+ case ChainSeparationType::IdOrTer:
if (old_this_chainid != old_prev_chainid || old_this_chainnum != old_prev_chainnum)
{
new_chainnum++;
}
break;
- case enChainSep_id_and_ter:
+ case ChainSeparationType::IdAndTer:
if (old_this_chainid != old_prev_chainid && old_this_chainnum != old_prev_chainnum)
{
new_chainnum++;
}
break;
- case enChainSep_id:
+ case ChainSeparationType::Id:
if (old_this_chainid != old_prev_chainid)
{
new_chainnum++;
}
break;
- case enChainSep_ter:
+ case ChainSeparationType::Ter:
if (old_this_chainnum != old_prev_chainnum)
{
new_chainnum++;
}
break;
- case enChainSep_interactive:
+ case ChainSeparationType::Interactive:
if (old_this_chainid != old_prev_chainid || old_this_chainnum != old_prev_chainnum)
{
if (i > 0)
{
- printf("Split the chain (and introduce termini) between residue %s%d (chain id '%c', atom %d %s)\
-\n"
- "and residue %s%d (chain id '%c', atom %d %s) ? [n/y]\n",
- prev_resname, prev_resnum, prev_chainid, prev_atomnum, prev_atomname,
- this_resname, this_resnum, this_chainid, this_atomnum, this_atomname);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Split the chain (and introduce termini) between residue %s%d (chain id '%c', atom %d %s)\
+"
+ "and residue %s%d (chain id '%c', atom %d %s) ? [n/y]",
+ prev_resname, prev_resnum, prev_chainid, prev_atomnum,
+ prev_atomname, this_resname, this_resnum, this_chainid,
+ this_atomnum, this_atomname);
if (nullptr == fgets(select, STRLEN - 1, stdin))
{
}
}
break;
- default: gmx_fatal(FARGS, "Internal inconsistency - this shouldn't happen...");
+ case ChainSeparationType::Count:
+ gmx_fatal(FARGS, "Internal inconsistency - this shouldn't happen...");
}
old_prev_chainid = old_this_chainid;
old_prev_chainnum = old_this_chainnum;
std::vector<gmx::RVec> x;
};
-// TODO make all enums into scoped enums
-/* enum for vsites */
-enum VSitesType
+enum class VSitesType : int
{
- enVSites_none,
- enVSites_hydrogens,
- enVSites_aromatics
+ None,
+ Hydrogens,
+ Aromatics,
+ Count
+};
+static const gmx::EnumerationArray<VSitesType, const char*> c_vsitesTypeNames = {
+ { "none", "hydrogens", "aromatics" }
};
-static const char* VSitesEnum[] = { "none", "hydrogens", "aromatics" };
-/* enum for water model */
-enum WaterType
+enum class WaterType : int
{
- enWater_select,
- enWater_none,
- enWater_spc,
- enWater_spce,
- enWater_tip3p,
- enWater_tip4p,
- enWater_tip5p,
- enWater_tips3p
+ Select,
+ None,
+ Spc,
+ SpcE,
+ Tip3p,
+ Tip4p,
+ Tip5p,
+ Tips3p,
+ Count
+};
+static const gmx::EnumerationArray<WaterType, const char*> c_waterTypeNames = {
+ { "select", "none", "spc", "spce", "tip3p", "tip4p", "tip5p", "tips3p" }
};
-static const char* WaterEnum[] = { "select", "none", "spc", "spce",
- "tip3p", "tip4p", "tip5p", "tips3p" };
-/* enum for merge */
-enum MergeType
+enum class MergeType : int
{
- enMerge_no,
- enMerge_all,
- enMerge_interactive
+ No,
+ All,
+ Interactive,
+ Count
};
-static const char* MergeEnum[] = { "no", "all", "interactive" };
+static const gmx::EnumerationArray<MergeType, const char*> c_mergeTypeNames = { { "no", "all",
+ "interactive" } };
namespace gmx
{
bVsites_(FALSE),
bPrevWat_(FALSE),
bVsiteAromatics_(FALSE),
- enumChainSep_(enChainSep_id_or_ter),
- enumVSites_(enVSites_none),
- enumWater_(enWater_select),
- enumMerge_(enMerge_no),
+ chainSeparation_(ChainSeparationType::IdOrTer),
+ vsitesType_(VSitesType::None),
+ waterType_(WaterType::Select),
+ mergeType_(MergeType::No),
itp_file_(nullptr),
mHmult_(0)
{
std::string outFile_;
std::string ff_;
- ChainSepType enumChainSep_;
- VSitesType enumVSites_;
- WaterType enumWater_;
- MergeType enumMerge_;
-
- FILE* itp_file_;
- char forcefield_[STRLEN];
- char ffdir_[STRLEN];
- char* ffname_;
- char* watermodel_;
- std::vector<std::string> incls_;
- std::vector<t_mols> mols_;
- real mHmult_;
+ ChainSeparationType chainSeparation_;
+ VSitesType vsitesType_;
+ WaterType waterType_;
+ MergeType mergeType_;
+
+ FILE* itp_file_;
+ char forcefield_[STRLEN];
+ char ffdir_[STRLEN];
+ char* ffname_;
+ char* watermodel_;
+ std::vector<std::string> incls_;
+ std::vector<t_mols> mols_;
+ real mHmult_;
+ std::unique_ptr<gmx::MDLogger> loggerPointer_;
};
void pdb2gmx::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings)
RealOption("lb").store(&long_bond_dist_).defaultValue(0.25).hidden().description("Long bond warning distance"));
options->addOption(
RealOption("sb").store(&short_bond_dist_).defaultValue(0.05).hidden().description("Short bond warning distance"));
- options->addOption(
- EnumOption<ChainSepType>("chainsep").enumValue(ChainSepEnum).store(&enumChainSep_).description("Condition in PDB files when a new chain should be started (adding termini)"));
+ options->addOption(EnumOption<ChainSeparationType>("chainsep")
+ .enumValue(c_chainSeparationTypeNames)
+ .store(&chainSeparation_)
+ .description("Condition in PDB files when a new chain should be "
+ "started (adding termini)"));
options->addOption(EnumOption<MergeType>("merge")
- .enumValue(MergeEnum)
- .store(&enumMerge_)
+ .enumValue(c_mergeTypeNames)
+ .store(&mergeType_)
.description("Merge multiple chains into a single [moleculetype]"));
options->addOption(StringOption("ff").store(&ff_).defaultValue("select").description(
"Force field, interactive by default. Use [TT]-h[tt] for information."));
options->addOption(
- EnumOption<WaterType>("water").store(&enumWater_).enumValue(WaterEnum).description("Water model to use"));
+ EnumOption<WaterType>("water").store(&waterType_).enumValue(c_waterTypeNames).description("Water model to use"));
options->addOption(BooleanOption("inter").store(&bInter_).defaultValue(false).description(
"Set the next 8 options to interactive"));
options->addOption(BooleanOption("ss").store(&bCysMan_).defaultValue(false).description(
BooleanOption("v").store(&bVerbose_).defaultValue(false).description("Be slightly more verbose in messages"));
options->addOption(
RealOption("posrefc").store(&posre_fc_).defaultValue(1000).description("Force constant for position restraints"));
- options->addOption(
- EnumOption<VSitesType>("vsite").store(&enumVSites_).enumValue(VSitesEnum).description("Convert atoms to virtual sites"));
+ options->addOption(EnumOption<VSitesType>("vsite")
+ .store(&vsitesType_)
+ .enumValue(c_vsitesTypeNames)
+ .description("Convert atoms to virtual sites"));
options->addOption(BooleanOption("heavyh").store(&bHeavyH_).defaultValue(false).description(
"Make hydrogen atoms heavy"));
options->addOption(
/* Force field selection, interactive or direct */
choose_ff(strcmp(ff_.c_str(), "select") == 0 ? nullptr : ff_.c_str(), forcefield_,
- sizeof(forcefield_), ffdir_, sizeof(ffdir_));
+ sizeof(forcefield_), ffdir_, sizeof(ffdir_), *loggerPointer_);
if (strlen(forcefield_) > 0)
{
int this_chainstart;
int prev_chainstart;
- printf("\nUsing the %s force field in directory %s\n\n", ffname_, ffdir_);
+ gmx::LoggerBuilder builder;
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Info, &gmx::TextOutputFile::standardOutput());
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Warning, &gmx::TextOutputFile::standardError());
+ gmx::LoggerOwner logOwner(builder.build());
+ loggerPointer_ = std::make_unique<gmx::MDLogger>(logOwner.logger());
+ const gmx::MDLogger& logger = *loggerPointer_;
- choose_watermodel(WaterEnum[enumWater_], ffdir_, &watermodel_);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Using the %s force field in directory %s", ffname_, ffdir_);
- switch (enumVSites_)
+ choose_watermodel(c_waterTypeNames[waterType_], ffdir_, &watermodel_, logger);
+
+ switch (vsitesType_)
{
- case enVSites_none:
+ case VSitesType::None:
bVsites_ = false;
bVsiteAromatics_ = false;
break;
- case enVSites_hydrogens:
+ case VSitesType::Hydrogens:
bVsites_ = true;
bVsiteAromatics_ = false;
break;
- case enVSites_aromatics:
+ case VSitesType::Aromatics:
bVsites_ = true;
bVsiteAromatics_ = true;
break;
- default:
- gmx_fatal(FARGS, "Internal inconsistency: VSitesEnum='%s'", VSitesEnum[enumVSites_]);
+ case VSitesType::Count:
+ gmx_fatal(FARGS, "Internal inconsistency: VSitesType='%s'", c_vsitesTypeNames[vsitesType_]);
} /* end switch */
/* Open the symbol table */
std::vector<RtpRename> rtprename;
for (const auto& filename : rrn)
{
- printf("going to rename %s\n", filename.c_str());
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("going to rename %s", filename.c_str());
FILE* fp = fflib_open(filename);
read_rtprename(filename.c_str(), fp, &rtprename);
gmx_ffclose(fp);
AtomProperties aps;
char* title = nullptr;
- int ePBC;
+ PbcType pbcType;
t_atoms pdba_all;
rvec* pdbx;
int natom = read_pdball(inputConfFile_.c_str(), bOutputSet_, outFile_.c_str(), &title, &pdba_all,
- &pdbx, &ePBC, box, bRemoveH_, &symtab, &rt, watres, &aps, bVerbose_);
+ &pdbx, &pbcType, box, bRemoveH_, &symtab, &rt, watres, &aps, bVerbose_);
if (natom == 0)
{
GMX_THROW(InconsistentInputError(message));
}
- printf("Analyzing pdb file\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Analyzing pdb file");
int nwaterchain = 0;
- modify_chain_numbers(&pdba_all, enumChainSep_);
+ modify_chain_numbers(&pdba_all, chainSeparation_, logger);
int nchainmerges = 0;
bMerged = false;
if (i > 0 && !bWat_)
{
- if (!strncmp(MergeEnum[enumMerge_], "int", 3))
+ if (!strncmp(c_mergeTypeNames[mergeType_], "int", 3))
{
- printf("Merge chain ending with residue %s%d (chain id '%c', atom %d %s) and "
- "chain starting with\n"
- "residue %s%d (chain id '%c', atom %d %s) into a single moleculetype "
- "(keeping termini)? [n/y]\n",
- prev_resname, prev_resnum, prev_chainid, prev_atomnum, prev_atomname,
- this_resname, this_resnum, this_chainid, this_atomnum, this_atomname);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Merge chain ending with residue %s%d (chain id '%c', atom %d "
+ "%s) and chain starting with "
+ "residue %s%d (chain id '%c', atom %d %s) into a single "
+ "moleculetype (keeping termini)? [n/y]",
+ prev_resname, prev_resnum, prev_chainid, prev_atomnum,
+ prev_atomname, this_resname, this_resnum, this_chainid,
+ this_atomnum, this_atomname);
if (nullptr == fgets(select, STRLEN - 1, stdin))
{
}
bMerged = (select[0] == 'y');
}
- else if (!strncmp(MergeEnum[enumMerge_], "all", 3))
+ else if (!strncmp(c_mergeTypeNames[mergeType_], "all", 3))
{
bMerged = true;
}
{
if (pdb_ch[j].chainid != ' ' && pdb_ch[j].chainid == ri->chainid)
{
- printf("WARNING: Chain identifier '%c' is used in two non-sequential "
- "blocks.\n"
- "They will be treated as separate chains unless you reorder your "
- "file.\n",
- ri->chainid);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Chain identifier '%c' is used in two non-sequential "
+ "blocks. "
+ "They will be treated as separate chains unless you "
+ "reorder your file.",
+ ri->chainid);
}
}
t_pdbchain newChain;
}
if (nwaterchain > 1)
{
- printf("Moved all the water blocks to the end\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Moved all the water blocks to the end");
}
t_atoms* pdba;
if (nchainmerges > 0)
{
- printf("\nMerged chains into joint molecule definitions at %d places.\n\n", nchainmerges);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Merged chains into joint molecule definitions at %d places.",
+ nchainmerges);
}
- printf("There are %d chains and %d blocks of water and "
- "%d residues with %d atoms\n",
- numChains - nwaterchain, nwaterchain, pdba_all.nres, natom);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "There are %d chains and %d blocks of water and "
+ "%d residues with %d atoms",
+ numChains - nwaterchain, nwaterchain, pdba_all.nres, natom);
- printf("\n %5s %4s %6s\n", "chain", "#res", "#atoms");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(" %5s %4s %6s", "chain", "#res", "#atoms");
for (int i = 0; (i < numChains); i++)
{
- printf(" %d '%c' %5d %6d %s\n", i + 1, chains[i].chainid ? chains[i].chainid : '-',
- chains[i].pdba->nres, chains[i].pdba->nr, chains[i].bAllWat ? "(only water)" : "");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(" %d '%c' %5d %6d %s\n", i + 1,
+ chains[i].chainid ? chains[i].chainid : '-', chains[i].pdba->nres,
+ chains[i].pdba->nr, chains[i].bAllWat ? "(only water)" : "");
}
- printf("\n");
- check_occupancy(&pdba_all, inputConfFile_.c_str(), bVerbose_);
+ check_occupancy(&pdba_all, inputConfFile_.c_str(), bVerbose_, logger);
/* Read atomtypes... */
PreprocessingAtomTypes atype = read_atype(ffdir_, &symtab);
/* read residue database */
- printf("Reading residue database... (%s)\n", forcefield_);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Reading residue database... (%s)", forcefield_);
std::vector<std::string> rtpf = fflib_search_file_end(ffdir_, ".rtp", true);
std::vector<PreprocessResidue> rtpFFDB;
for (const auto& filename : rtpf)
{
- readResidueDatabase(filename, &rtpFFDB, &atype, &symtab, false);
+ readResidueDatabase(filename, &rtpFFDB, &atype, &symtab, logger, false);
}
if (bNewRTP_)
{
if (cc->chainid && (cc->chainid != ' '))
{
- printf("Processing chain %d '%c' (%d atoms, %d residues)\n", chain + 1, cc->chainid,
- natom, nres);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Processing chain %d '%c' (%d atoms, %d residues)",
+ chain + 1, cc->chainid, natom, nres);
}
else
{
- printf("Processing chain %d (%d atoms, %d residues)\n", chain + 1, natom, nres);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Processing chain %d (%d atoms, %d residues)", chain + 1,
+ natom, nres);
}
process_chain(pdba, x, bUnA_, bUnA_, bUnA_, bLysMan_, bAspMan_, bGluMan_, bHisMan_,
for (int i = 0; i < cc->nterpairs; i++)
{
find_nc_ter(pdba, cc->chainstart[i], cc->chainstart[i + 1], &(cc->r_start[j]),
- &(cc->r_end[j]), &rt);
+ &(cc->r_end[j]), &rt, logger);
if (cc->r_start[j] >= 0 && cc->r_end[j] >= 0)
{
cc->nterpairs = j;
if (cc->nterpairs == 0)
{
- printf("Problem with chain definition, or missing terminal residues.\n"
- "This chain does not appear to contain a recognized chain molecule.\n"
- "If this is incorrect, you can edit residuetypes.dat to modify the behavior.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Problem with chain definition, or missing terminal residues. "
+ "This chain does not appear to contain a recognized chain molecule. "
+ "If this is incorrect, you can edit residuetypes.dat to modify the "
+ "behavior.");
}
/* Check for disulfides and other special bonds */
if (!rtprename.empty())
{
- rename_resrtp(pdba, cc->nterpairs, cc->r_start, cc->r_end, rtprename, &symtab, bVerbose_);
+ rename_resrtp(pdba, cc->nterpairs, cc->r_start, cc->r_end, rtprename, &symtab, bVerbose_, logger);
}
for (int i = 0; i < cc->nterpairs; i++)
tdblist = filter_ter(ntdb, *pdba->resinfo[cc->r_start[i]].name);
if (tdblist.empty())
{
- printf("No suitable end (N or 5') terminus found in database - assuming this "
- "residue\n"
- "is already in a terminus-specific form and skipping terminus "
- "selection.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "No suitable end (N or 5') terminus found in database - "
+ "assuming this residue "
+ "is already in a terminus-specific form and skipping terminus "
+ "selection.");
cc->ntdb.push_back(nullptr);
}
else
tdblist = filter_ter(ctdb, *pdba->resinfo[cc->r_end[i]].name);
if (tdblist.empty())
{
- printf("No suitable end (C or 3') terminus found in database - assuming this "
- "residue\n"
- "is already in a terminus-specific form and skipping terminus "
- "selection.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "No suitable end (C or 3') terminus found in database - "
+ "assuming this residue"
+ "is already in a terminus-specific form and skipping terminus "
+ "selection.");
cc->ctdb.push_back(nullptr);
}
else
/* lookup hackblocks and rtp for all residues */
std::vector<PreprocessResidue> restp_chain;
get_hackblocks_rtp(&hb_chain, &restp_chain, rtpFFDB, pdba->nres, pdba->resinfo, cc->nterpairs,
- &symtab, cc->ntdb, cc->ctdb, cc->r_start, cc->r_end, bAllowMissing_);
+ &symtab, cc->ntdb, cc->ctdb, cc->r_start, cc->r_end, bAllowMissing_, logger);
/* ideally, now we would not need the rtp itself anymore, but do
everything using the hb and restp arrays. Unfortunately, that
requires some re-thinking of code in gen_vsite.c, which I won't
rename_atoms(nullptr, ffdir_, pdba, &symtab, restp_chain, false, &rt, false, bVerbose_);
- match_atomnames_with_rtp(restp_chain, hb_chain, pdba, &symtab, x, bVerbose_);
+ match_atomnames_with_rtp(restp_chain, hb_chain, pdba, &symtab, x, bVerbose_, logger);
if (bSort_)
{
t_blocka* block = new_blocka();
snew(gnames, 1);
sort_pdbatoms(restp_chain, natom, &pdba, &sortAtoms[chain], &x, block, &gnames);
- remove_duplicate_atoms(pdba, x, bVerbose_);
+ remove_duplicate_atoms(pdba, x, bVerbose_, logger);
if (bIndexSet_)
{
if (bRemoveH_)
{
- fprintf(stderr,
- "WARNING: with the -remh option the generated "
- "index file (%s) might be useless\n"
- "(the index file is generated before hydrogens are added)",
- indexOutputFile_.c_str());
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "With the -remh option the generated "
+ "index file (%s) might be useless "
+ "(the index file is generated before hydrogens are added)",
+ indexOutputFile_.c_str());
}
write_index(indexOutputFile_.c_str(), block, gnames, false, 0);
}
}
else
{
- fprintf(stderr,
- "WARNING: "
- "without sorting no check for duplicate atoms can be done\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Without sorting no check for duplicate atoms can be done");
}
/* Generate Hydrogen atoms (and termini) in the sequence */
- printf("Generating any missing hydrogen atoms and/or adding termini.\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Generating any missing hydrogen atoms and/or adding termini.");
add_h(&pdba, &localAtoms[chain], &x, ah, &symtab, cc->nterpairs, cc->ntdb, cc->ctdb,
cc->r_start, cc->r_end, bAllowMissing_);
- printf("Now there are %d residues with %d atoms\n", pdba->nres, pdba->nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Now there are %d residues with %d atoms", pdba->nres, pdba->nr);
/* make up molecule name(s) */
pdb2top(top_file2, posre_fn.c_str(), molname.c_str(), pdba, &x, &atype, &symtab, rtpFFDB,
restp_chain, hb_chain, bAllowMissing_, bVsites_, bVsiteAromatics_, ffdir_, mHmult_,
ssbonds, long_bond_dist_, short_bond_dist_, bDeuterate_, bChargeGroups_, bCmap_,
- bRenumRes_, bRTPresname_);
+ bRenumRes_, bRTPresname_, logger);
if (!cc->bAllWat)
{
{
if (numChains > 1)
{
- printf("Including chain %d in system: %d atoms %d residues\n", i + 1,
- chains[i].pdba->nr, chains[i].pdba->nres);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Including chain %d in system: %d atoms %d residues",
+ i + 1, chains[i].pdba->nr, chains[i].pdba->nres);
}
for (int j = 0; (j < chains[i].pdba->nr); j++)
{
if (numChains > 1)
{
- fprintf(stderr, "Now there are %d atoms and %d residues\n", k, l);
- print_sums(atoms, true);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Now there are %d atoms and %d residues", k, l);
+ print_sums(atoms, true, logger);
}
rvec box_space;
- fprintf(stderr, "\nWriting coordinate file...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Writing coordinate file...");
clear_rvec(box_space);
if (box[0][0] == 0)
{
make_new_box(atoms->nr, gmx::as_rvec_array(x.data()), box, box_space, false);
}
- write_sto_conf(outputConfFile_.c_str(), title, atoms, gmx::as_rvec_array(x.data()), nullptr, ePBC, box);
+ write_sto_conf(outputConfFile_.c_str(), title, atoms, gmx::as_rvec_array(x.data()), nullptr,
+ pbcType, box);
done_symtab(&symtab);
done_atom(&pdba_all);
sfree(atoms);
sfree(title);
sfree(pdbx);
- printf("\t\t--------- PLEASE NOTE ------------\n");
- printf("You have successfully generated a topology from: %s.\n", inputConfFile_.c_str());
+
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("\t\t--------- PLEASE NOTE ------------");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("You have successfully generated a topology from: %s.",
+ inputConfFile_.c_str());
if (watermodel_ != nullptr)
{
- printf("The %s force field and the %s water model are used.\n", ffname_, watermodel_);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("The %s force field and the %s water model are used.", ffname_,
+ watermodel_);
sfree(watermodel_);
}
else
{
- printf("The %s force field is used.\n", ffname_);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("The %s force field is used.", ffname_);
}
- printf("\t\t--------- ETON ESAELP ------------\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("\t\t--------- ETON ESAELP ------------");
return 0;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/niceheader.h"
#include "gromacs/utility/path.h"
#include "gromacs/utility/programcontext.h"
/* this must correspond to enum in pdb2top.h */
const char* hh[ehisNR] = { "HISD", "HISE", "HISH", "HIS1" };
-static int missing_atoms(const PreprocessResidue* rp, int resind, t_atoms* at, int i0, int i)
+static int missing_atoms(const PreprocessResidue* rp, int resind, t_atoms* at, int i0, int i, const gmx::MDLogger& logger)
{
int nmiss = 0;
for (int j = 0; j < rp->natom(); j++)
if (!bFound)
{
nmiss++;
- fprintf(stderr,
- "\nWARNING: "
- "atom %s is missing in residue %s %d in the pdb file\n",
- name, *(at->resinfo[resind].name), at->resinfo[resind].nr);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("atom %s is missing in residue %s %d in the pdb file",
+ name, *(at->resinfo[resind].name), at->resinfo[resind].nr);
if (name[0] == 'H' || name[0] == 'h')
{
- fprintf(stderr,
- " You might need to add atom %s to the hydrogen database of "
- "building block %s\n"
- " in the file %s.hdb (see the manual)\n",
- name, *(at->resinfo[resind].rtp), rp->filebase.c_str());
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "You might need to add atom %s to the hydrogen database of "
+ "building block %s "
+ "in the file %s.hdb (see the manual)",
+ name, *(at->resinfo[resind].rtp), rp->filebase.c_str());
}
- fprintf(stderr, "\n");
}
}
return (fabs(x - ix) < tol);
}
-static void choose_ff_impl(const char* ffsel, char* forcefield, int ff_maxlen, char* ffdir, int ffdir_maxlen)
+static void choose_ff_impl(const char* ffsel,
+ char* forcefield,
+ int ff_maxlen,
+ char* ffdir,
+ int ffdir_maxlen,
+ const gmx::MDLogger& logger)
{
std::vector<gmx::DataFileInfo> ffdirs = fflib_enumerate_forcefields();
const int nff = ssize(ffdirs);
{
if (cwdsel != -1)
{
- fprintf(stderr,
- "Force field '%s' occurs in %d places. pdb2gmx is using the one in the\n"
- "current directory. Use interactive selection (not the -ff option) if\n"
- "you would prefer a different one.\n",
- ffsel, nfound);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Force field '%s' occurs in %d places. pdb2gmx is using the one in "
+ "the current directory. Use interactive selection "
+ "(not the -ff option) if you would prefer a different one.",
+ ffsel, nfound);
}
else
{
}
}
- printf("\nSelect the Force Field:\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Select the Force Field:");
for (int i = 0; i < nff; ++i)
{
if (i == 0 || ffdirs[i - 1].dir != ffdirs[i].dir)
{
if (ffdirs[i].dir == ".")
{
- printf("From current directory:\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("From current directory:");
}
else
{
- printf("From '%s':\n", ffdirs[i].dir.c_str());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("From '%s':", ffdirs[i].dir.c_str());
}
}
- printf("%2d: %s\n", i + 1, desc[i].c_str());
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("%2d: %s", i + 1, desc[i].c_str());
}
sel = -1;
strcpy(ffdir, ffpath.c_str());
}
-void choose_ff(const char* ffsel, char* forcefield, int ff_maxlen, char* ffdir, int ffdir_maxlen)
+void choose_ff(const char* ffsel, char* forcefield, int ff_maxlen, char* ffdir, int ffdir_maxlen, const gmx::MDLogger& logger)
{
try
{
- choose_ff_impl(ffsel, forcefield, ff_maxlen, ffdir, ffdir_maxlen);
+ choose_ff_impl(ffsel, forcefield, ff_maxlen, ffdir, ffdir_maxlen, logger);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
-void choose_watermodel(const char* wmsel, const char* ffdir, char** watermodel)
+void choose_watermodel(const char* wmsel, const char* ffdir, char** watermodel, const gmx::MDLogger& logger)
{
const char* fn_watermodels = "watermodels.dat";
FILE* fp;
std::string filename = gmx::Path::join(ffdir, fn_watermodels);
if (!fflib_fexist(filename))
{
- fprintf(stderr, "No file '%s' found, will not include a water model\n", fn_watermodels);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("No file '%s' found, will not include a water model", fn_watermodels);
*watermodel = nullptr;
return;
}
fp = fflib_open(filename);
- printf("\nSelect the Water Model:\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Select the Water Model:");
nwm = 0;
model = nullptr;
while (get_a_line(fp, buf, STRLEN))
if (i > 0)
{
ltrim(buf + i);
- fprintf(stderr, "%2d: %s\n", nwm + 1, buf + i);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("%2d: %s", nwm + 1, buf + i);
nwm++;
}
else
}
}
gmx_ffclose(fp);
- fprintf(stderr, "%2d: %s\n", nwm + 1, "None");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("%2d: %s", nwm + 1, "None");
sel = -1;
do
sfree(model);
}
-static int name2type(t_atoms* at, int** cgnr, gmx::ArrayRef<const PreprocessResidue> usedPpResidues, ResidueType* rt)
+static int name2type(t_atoms* at,
+ int** cgnr,
+ gmx::ArrayRef<const PreprocessResidue> usedPpResidues,
+ ResidueType* rt,
+ const gmx::MDLogger& logger)
{
int i, j, prevresind, i0, prevcg, cg, curcg;
char* name;
bNterm = bProt && (resind == 0);
if (resind > 0)
{
- nmissat += missing_atoms(&usedPpResidues[prevresind], prevresind, at, i0, i);
+ nmissat += missing_atoms(&usedPpResidues[prevresind], prevresind, at, i0, i, logger);
}
i0 = i;
}
at->atom[i].qB = at->atom[i].q;
at->atom[i].mB = at->atom[i].m;
}
- nmissat += missing_atoms(&usedPpResidues[resind], resind, at, i0, i);
+ nmissat += missing_atoms(&usedPpResidues[resind], resind, at, i0, i, logger);
return nmissat;
}
t_atoms* atoms,
gmx::ArrayRef<const gmx::RVec> x,
real long_bond_dist,
- real short_bond_dist)
+ real short_bond_dist,
+ const gmx::MDLogger& logger)
{
real long_bond_dist2, short_bond_dist2;
const char* ptr;
ptr = "check";
}
- fprintf(stderr, "Making bonds...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Making bonds...");
int i = 0;
for (int resind = 0; (resind < atoms->nres) && (i < atoms->nr); resind++)
{
if (dist2 > long_bond_dist2)
{
- fprintf(stderr, "Warning: Long Bond (%d-%d = %g nm)\n", ai + 1, aj + 1,
- std::sqrt(dist2));
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("Long Bond (%d-%d = %g nm)", ai + 1, aj + 1,
+ std::sqrt(dist2));
}
else if (dist2 < short_bond_dist2)
{
- fprintf(stderr, "Warning: Short Bond (%d-%d = %g nm)\n", ai + 1, aj + 1,
- std::sqrt(dist2));
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("Short Bond (%d-%d = %g nm)", ai + 1, aj + 1,
+ std::sqrt(dist2));
}
add_param(psb, ai, aj, {}, patch.s.c_str());
}
{
int d;
- if ((d = a.ai() - b.ai()) != 0)
- {
- return d < 0;
- }
- else if ((d = a.aj() - b.aj()) != 0)
+ if (((d = a.ai() - b.ai()) != 0) || ((d = a.aj() - b.aj()) != 0))
{
return d < 0;
}
}
}
-static void clean_bonds(InteractionsOfType* ps)
+static void clean_bonds(InteractionsOfType* ps, const gmx::MDLogger& logger)
{
if (ps->size() > 0)
{
++parm;
}
}
- fprintf(stderr, "Number of bonds was %d, now %zu\n", oldNumber, ps->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Number of bonds was %d, now %zu", oldNumber, ps->size());
}
else
{
- fprintf(stderr, "No bonds\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("No bonds");
}
}
-void print_sums(const t_atoms* atoms, bool bSystem)
+void print_sums(const t_atoms* atoms, bool bSystem, const gmx::MDLogger& logger)
{
double m, qtot;
int i;
qtot += atoms->atom[i].q;
}
- fprintf(stderr, "Total mass%s %.3f a.m.u.\n", where, m);
- fprintf(stderr, "Total charge%s %.3f e\n", where, qtot);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Total mass%s %.3f a.m.u.", where, m);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Total charge%s %.3f e", where, qtot);
}
static void check_restp_type(const char* name, int t1, int t2)
gmx::ArrayRef<MoleculePatchDatabase*> ctdb,
gmx::ArrayRef<const int> rn,
gmx::ArrayRef<const int> rc,
- bool bAllowMissing)
+ bool bAllowMissing,
+ const gmx::MDLogger& logger)
{
char* key;
bool bRM;
*/
key = *resinfo[i].rtp;
- resinfo[i].rtp = put_symtab(symtab, searchResidueDatabase(key, rtpFFDB).c_str());
+ resinfo[i].rtp = put_symtab(symtab, searchResidueDatabase(key, rtpFFDB, logger).c_str());
auto res = getDatabaseEntry(*resinfo[i].rtp, rtpFFDB);
usedPpResidues->push_back(PreprocessResidue());
PreprocessResidue* newentry = &usedPpResidues->back();
"terminal database entries (.tdb).";
if (bAllowMissing)
{
- fprintf(stderr, "%s\n", errString);
+ GMX_LOG(logger.warning).asParagraph().appendTextFormatted("%s", errString);
}
else
{
"proper existing terminal entry.";
if (bAllowMissing)
{
- fprintf(stderr, "%s\n", errString);
+ GMX_LOG(logger.warning).asParagraph().appendTextFormatted("%s", errString);
}
else
{
int atind,
PreprocessResidue* localPpResidue,
const MoleculePatchDatabase& singlePatch,
- bool bVerbose)
+ bool bVerbose,
+ const gmx::MDLogger& logger)
{
int resnr;
char* oldnm;
if (bVerbose)
{
- printf("Renaming atom '%s' in residue '%s' %d to '%s'\n", oldnm,
- localPpResidue->resname.c_str(), resnr, newnm.c_str());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Renaming atom '%s' in residue '%s' %d to '%s'", oldnm,
+ localPpResidue->resname.c_str(), resnr, newnm.c_str());
}
/* Rename the atom in pdba */
pdba->atomname[atind] = put_symtab(symtab, newnm.c_str());
*/
if (bVerbose)
{
- printf("Deleting atom '%s' in residue '%s' %d\n", oldnm,
- localPpResidue->resname.c_str(), resnr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Deleting atom '%s' in residue '%s' %d", oldnm,
+ localPpResidue->resname.c_str(), resnr);
}
/* We should free the atom name,
* but it might be used multiple times in the symtab.
t_atoms* pdba,
t_symtab* symtab,
gmx::ArrayRef<gmx::RVec> x,
- bool bVerbose)
+ bool bVerbose,
+ const gmx::MDLogger& logger)
{
for (int i = 0; i < pdba->nr; i++)
{
{
/* Not found yet, check if we have to rename this atom */
if (match_atomnames_with_rtp_atom(pdba, x, symtab, i, localPpResidue,
- globalPatches[pdba->atom[i].resind], bVerbose))
+ globalPatches[pdba->atom[i].resind], bVerbose, logger))
{
/* We deleted this atom, decrease the atom counter by 1. */
i--;
}
#define NUM_CMAP_ATOMS 5
-static void gen_cmap(InteractionsOfType* psb, gmx::ArrayRef<const PreprocessResidue> usedPpResidues, t_atoms* atoms)
+static void gen_cmap(InteractionsOfType* psb,
+ gmx::ArrayRef<const PreprocessResidue> usedPpResidues,
+ t_atoms* atoms,
+ const gmx::MDLogger& logger)
{
int residx;
const char* ptr;
ptr = "check";
}
- fprintf(stderr, "Making cmap torsions...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Making cmap torsions...");
int i = 0;
/* Most cmap entries use the N atom from the next residue, so the last
* residue should not have its CMAP entry in that case, but for things like
bool bChargeGroups,
bool bCmap,
bool bRenumRes,
- bool bRTPresname)
+ bool bRTPresname,
+ const gmx::MDLogger& logger)
{
std::array<InteractionsOfType, F_NRE> plist;
t_excls* excls;
ResidueType rt;
/* Make bonds */
- at2bonds(&(plist[F_BONDS]), globalPatches, atoms, *x, long_bond_dist, short_bond_dist);
+ at2bonds(&(plist[F_BONDS]), globalPatches, atoms, *x, long_bond_dist, short_bond_dist, logger);
/* specbonds: disulphide bonds & heme-his */
do_ssbonds(&(plist[F_BONDS]), atoms, ssbonds, bAllowMissing);
- nmissat = name2type(atoms, &cgnr, usedPpResidues, &rt);
+ nmissat = name2type(atoms, &cgnr, usedPpResidues, &rt, logger);
if (nmissat)
{
if (bAllowMissing)
{
- fprintf(stderr, "There were %d missing atoms in molecule %s\n", nmissat, molname);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("There were %d missing atoms in molecule %s", nmissat, molname);
}
else
{
}
/* Cleanup bonds (sort and rm doubles) */
- clean_bonds(&(plist[F_BONDS]));
+ clean_bonds(&(plist[F_BONDS]), logger);
snew(vsite_type, atoms->nr);
for (i = 0; i < atoms->nr; i++)
{
if (bVsiteAromatics)
{
- fprintf(stdout,
- "The conversion of aromatic rings into virtual sites is deprecated "
- "and may be removed in a future version of GROMACS");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "The conversion of aromatic rings into virtual sites is deprecated "
+ "and may be removed in a future version of GROMACS");
}
/* determine which atoms will be vsites and add dummy masses
also renumber atom numbers in plist[0..F_NRE]! */
}
/* Make Angles and Dihedrals */
- fprintf(stderr, "Generating angles, dihedrals and pairs...\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Generating angles, dihedrals and pairs...");
snew(excls, atoms->nr);
gen_pad(atoms, usedPpResidues, plist, excls, globalPatches, bAllowMissing);
/* Make CMAP */
if (bCmap)
{
- gen_cmap(&(plist[F_CMAP]), usedPpResidues, atoms);
+ gen_cmap(&(plist[F_CMAP]), usedPpResidues, atoms, logger);
if (plist[F_CMAP].size() > 0)
{
- fprintf(stderr, "There are %4zu cmap torsion pairs\n", plist[F_CMAP].size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("There are %4zu cmap torsion pairs", plist[F_CMAP].size());
}
}
/* Cleanup bonds (sort and rm doubles) */
/* clean_bonds(&(plist[F_BONDS]));*/
- fprintf(stderr,
- "There are %4zu dihedrals, %4zu impropers, %4zu angles\n"
- " %4zu pairs, %4zu bonds and %4zu virtual sites\n",
- plist[F_PDIHS].size(), plist[F_IDIHS].size(), plist[F_ANGLES].size(),
- plist[F_LJ14].size(), plist[F_BONDS].size(),
- plist[F_VSITE2].size() + plist[F_VSITE3].size() + plist[F_VSITE3FD].size()
- + plist[F_VSITE3FAD].size() + plist[F_VSITE3OUT].size()
- + plist[F_VSITE4FD].size() + plist[F_VSITE4FDN].size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "There are %4zu dihedrals, %4zu impropers, %4zu angles\n"
+ " %4zu pairs, %4zu bonds and %4zu virtual sites",
+ plist[F_PDIHS].size(), plist[F_IDIHS].size(), plist[F_ANGLES].size(),
+ plist[F_LJ14].size(), plist[F_BONDS].size(),
+ plist[F_VSITE2].size() + plist[F_VSITE3].size() + plist[F_VSITE3FD].size()
+ + plist[F_VSITE3FAD].size() + plist[F_VSITE3OUT].size()
+ + plist[F_VSITE4FD].size() + plist[F_VSITE4FDN].size());
- print_sums(atoms, FALSE);
+ print_sums(atoms, FALSE, logger);
if (!bChargeGroups)
{
if (top_file)
{
- fprintf(stderr, "Writing topology\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Writing topology");
/* We can copy the bonded types from the first restp,
* since the types have to be identical for all residues in one molecule.
*/
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
class PreprocessingAtomTypes;
+
+namespace gmx
+{
+class MDLogger;
+}
+
struct t_atoms;
struct t_excls;
struct MoleculePatchDatabase;
};
extern const char* hh[ehisNR];
-void choose_ff(const char* ffsel, char* forcefield, int ff_maxlen, char* ffdir, int ffdir_maxlen);
+void choose_ff(const char* ffsel,
+ char* forcefield,
+ int ff_maxlen,
+ char* ffdir,
+ int ffdir_maxlen,
+ const gmx::MDLogger& logger);
/* Find force fields in the current and libdirs and choose an ff.
* If ffsel!=NULL: search for ffsel.
* If ffsel==NULL: interactive selection.
*/
-void choose_watermodel(const char* wmsel, const char* ffdir, char** watermodel);
+void choose_watermodel(const char* wmsel, const char* ffdir, char** watermodel, const gmx::MDLogger& logger);
/* Choose, possibly interactively, which water model to include,
* based on the wmsel command line option choice and watermodels.dat
* in ffdir.
gmx::ArrayRef<MoleculePatchDatabase*> ctdb,
gmx::ArrayRef<const int> rn,
gmx::ArrayRef<const int> rc,
- bool bAllowMissing);
+ bool bAllowMissing,
+ const gmx::MDLogger& logger);
/* Get the database entries for the nres residues in resinfo
* and store them in restp and hb.
*/
t_atoms* pdba,
t_symtab* symtab,
gmx::ArrayRef<gmx::RVec> x,
- bool bVerbose);
+ bool bVerbose,
+ const gmx::MDLogger& logger);
/* Check if atom in pdba need to be deleted of renamed due to tdb or hdb.
* If renaming involves atoms added wrt to the rtp database,
* add these atoms to restp.
bool bChargeGroups,
bool bCmap,
bool bRenumRes,
- bool bRTPresname);
+ bool bRTPresname,
+ const gmx::MDLogger& logger);
/* Create a topology ! */
-void print_sums(const t_atoms* atoms, bool bSystem);
+void print_sums(const t_atoms* atoms, bool bSystem, const gmx::MDLogger& logger);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017, The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Inquire all MdModules, if their parameters match with the energy
// calculation frequency
gmx::EnergyCalculationFrequencyErrors energyCalculationFrequencyErrors(ir->nstcalcenergy);
- mdModulesNotifier.notifier_.notify(&energyCalculationFrequencyErrors);
+ mdModulesNotifier.preProcessingNotifications_.notify(&energyCalculationFrequencyErrors);
// Emit all errors from the energy calculation frequency checks
for (const std::string& energyFrequencyErrorMessage :
/* TPI STUFF */
if (EI_TPI(ir->eI))
{
- sprintf(err_buf, "TPI only works with pbc = %s", epbc_names[epbcXYZ]);
- CHECK(ir->ePBC != epbcXYZ);
+ sprintf(err_buf, "TPI only works with pbc = %s", c_pbcTypeNames[PbcType::Xyz].c_str());
+ CHECK(ir->pbcType != PbcType::Xyz);
sprintf(err_buf, "with TPI nstlist should be larger than zero");
CHECK(ir->nstlist <= 0);
sprintf(err_buf, "TPI does not work with full electrostatics other than PME");
sprintf(err_buf, "The soft-core power is %d and can only be 1 or 2", fep->sc_power);
CHECK(fep->sc_alpha != 0 && fep->sc_power != 1 && fep->sc_power != 2);
- sprintf(err_buf, "The soft-core sc-r-power is %d and can only be 6 or 48",
+ sprintf(err_buf,
+ "The soft-core sc-r-power is %d and can only be 6. (sc-r-power 48 is no longer "
+ "supported.)",
static_cast<int>(fep->sc_r_power));
- CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0 && fep->sc_r_power != 48.0);
+ CHECK(fep->sc_alpha != 0 && fep->sc_r_power != 6.0);
sprintf(err_buf,
"Can't use positive delta-lambda (%g) if initial state/lambda does not start at "
}
/* PBC/WALLS */
- sprintf(err_buf, "walls only work with pbc=%s", epbc_names[epbcXY]);
- CHECK(ir->nwall && ir->ePBC != epbcXY);
+ sprintf(err_buf, "walls only work with pbc=%s", c_pbcTypeNames[PbcType::XY].c_str());
+ CHECK(ir->nwall && ir->pbcType != PbcType::XY);
/* VACUUM STUFF */
- if (ir->ePBC != epbcXYZ && ir->nwall != 2)
+ if (ir->pbcType != PbcType::Xyz && ir->nwall != 2)
{
- if (ir->ePBC == epbcNONE)
+ if (ir->pbcType == PbcType::No)
{
if (ir->epc != epcNO)
{
}
else
{
- sprintf(err_buf, "Can not have pressure coupling with pbc=%s", epbc_names[ir->ePBC]);
+ sprintf(err_buf, "Can not have pressure coupling with pbc=%s",
+ c_pbcTypeNames[ir->pbcType].c_str());
CHECK(ir->epc != epcNO);
}
- sprintf(err_buf, "Can not have Ewald with pbc=%s", epbc_names[ir->ePBC]);
+ sprintf(err_buf, "Can not have Ewald with pbc=%s", c_pbcTypeNames[ir->pbcType].c_str());
CHECK(EEL_FULL(ir->coulombtype));
- sprintf(err_buf, "Can not have dispersion correction with pbc=%s", epbc_names[ir->ePBC]);
+ sprintf(err_buf, "Can not have dispersion correction with pbc=%s",
+ c_pbcTypeNames[ir->pbcType].c_str());
CHECK(ir->eDispCorr != edispcNO);
}
"with coulombtype = %s or coulombtype = %s\n"
"without periodic boundary conditions (pbc = %s) and\n"
"rcoulomb and rvdw set to zero",
- eel_names[eelCUT], eel_names[eelUSER], epbc_names[epbcNONE]);
+ eel_names[eelCUT], eel_names[eelUSER], c_pbcTypeNames[PbcType::No].c_str());
CHECK(((ir->coulombtype != eelCUT) && (ir->coulombtype != eelUSER))
- || (ir->ePBC != epbcNONE) || (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
+ || (ir->pbcType != PbcType::No) || (ir->rcoulomb != 0.0) || (ir->rvdw != 0.0));
if (ir->nstlist > 0)
{
"Can not remove the rotation around the center of mass with periodic "
"molecules");
CHECK(ir->bPeriodicMols);
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
warning(wi,
"Removing the rotation around the center of mass in a periodic system, "
}
}
- if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->ePBC == epbcNONE && ir->comm_mode != ecmANGULAR)
+ if (EI_STATE_VELOCITY(ir->eI) && !EI_SD(ir->eI) && ir->pbcType == PbcType::No && ir->comm_mode != ecmANGULAR)
{
sprintf(warn_buf,
"Tumbling and flying ice-cubes: We are not removing rotation around center of mass "
{
if (ir->ewald_geometry == eewg3D)
{
- sprintf(warn_buf, "With pbc=%s you should use ewald-geometry=%s", epbc_names[ir->ePBC],
- eewg_names[eewg3DC]);
+ sprintf(warn_buf, "With pbc=%s you should use ewald-geometry=%s",
+ c_pbcTypeNames[ir->pbcType].c_str(), eewg_names[eewg3DC]);
warning(wi, warn_buf);
}
/* This check avoids extra pbc coding for exclusion corrections */
sprintf(err_buf, "wall-ewald-zfac should be >= 2");
CHECK(ir->wall_ewald_zfac < 2);
}
- if ((ir->ewald_geometry == eewg3DC) && (ir->ePBC != epbcXY) && EEL_FULL(ir->coulombtype))
+ if ((ir->ewald_geometry == eewg3DC) && (ir->pbcType != PbcType::XY) && EEL_FULL(ir->coulombtype))
{
sprintf(warn_buf, "With %s and ewald_geometry = %s you should use pbc = %s",
- eel_names[ir->coulombtype], eewg_names[eewg3DC], epbc_names[epbcXY]);
+ eel_names[ir->coulombtype], eewg_names[eewg3DC], c_pbcTypeNames[PbcType::XY].c_str());
warning(wi, warn_buf);
}
if ((ir->epsilon_surface != 0) && EEL_FULL(ir->coulombtype))
if (ir->bQMMM)
{
- warning_error(wi, "QMMM is currently not supported");
- if (!EI_DYNAMICS(ir->eI))
- {
- char buf[STRLEN];
- sprintf(buf, "QMMM is only supported with dynamics, not with integrator %s", ei_names[ir->eI]);
- warning_error(wi, buf);
- }
+ warning_error(wi, "The QMMM integration you are trying to use is no longer supported");
}
if (ir->bAdress)
}
- /* make it easier if sc_r_power = 48 by increasing it to the 4th power, to be in the right scale. */
- if (fep->sc_r_power == 48)
- {
- if (fep->sc_alpha > 0.1)
- {
- gmx_fatal(FARGS,
- "sc_alpha (%f) for sc_r_power = 48 should usually be between 0.001 and 0.004",
- fep->sc_alpha);
- }
- }
-
/* now read in the weights */
parse_n_real(weights, &nweights, &(expand->init_lambda_weights), wi);
if (nweights == 0)
GetSimTemps(ir->fepvals->n_lambda, ir->simtempvals, ir->fepvals->all_lambda[efptTEMPERATURE]);
}
-static void convertYesNos(warninp_t /*wi*/,
- gmx::ArrayRef<const std::string> inputs,
- const char* /*name*/,
- gmx_bool* outputs)
-{
- int i = 0;
- for (const auto& input : inputs)
- {
- outputs[i] = gmx::equalCaseInsensitive(input, "Y", 1);
- ++i;
- }
-}
-
template<typename T>
void convertInts(warninp_t wi, gmx::ArrayRef<const std::string> inputs, const char* name, T* outputs)
{
printStringNoNewline(&inp, "nblist update frequency");
ir->nstlist = get_eint(&inp, "nstlist", 10, wi);
printStringNoNewline(&inp, "Periodic boundary conditions: xyz, no, xy");
- ir->ePBC = get_eeenum(&inp, "pbc", epbc_names, wi);
+ // TODO This conversion should be removed when proper std:string handling will be added to get_eeenum(...), etc.
+ std::vector<const char*> pbcTypesNamesChar;
+ for (const auto& pbcTypeName : c_pbcTypeNames)
+ {
+ pbcTypesNamesChar.push_back(pbcTypeName.c_str());
+ }
+ ir->pbcType = static_cast<PbcType>(get_eeenum(&inp, "pbc", pbcTypesNamesChar.data(), wi));
ir->bPeriodicMols = get_eeenum(&inp, "periodic-molecules", yesno_names, wi) != 0;
printStringNoNewline(&inp,
"Allowed energy error due to the Verlet buffer in kJ/mol/ps per atom,");
printStringNoNewline(&inp, "QM method");
setStringEntry(&inp, "QMmethod", is->QMmethod, nullptr);
printStringNoNewline(&inp, "QMMM scheme");
- ir->QMMMscheme = get_eeenum(&inp, "QMMMscheme", eQMMMscheme_names, wi);
+ const char* noQMMMSchemeName = "normal";
+ get_eeenum(&inp, "QMMMscheme", &noQMMMSchemeName, wi);
printStringNoNewline(&inp, "QM basisset");
setStringEntry(&inp, "QMbasis", is->QMbasis, nullptr);
printStringNoNewline(&inp, "QM charge");
setStringEntry(&inp, "SAoff", is->SAoff, nullptr);
setStringEntry(&inp, "SAsteps", is->SAsteps, nullptr);
printStringNoNewline(&inp, "Scale factor for MM charges");
- ir->scalefactor = get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
+ get_ereal(&inp, "MMChargeScaleFactor", 1.0, wi);
/* Simulated annealing */
printStringNewline(&inp, "SIMULATED ANNEALING");
ir->bDoAwh = (get_eeenum(&inp, "awh", yesno_names, wi) != 0);
if (ir->bDoAwh)
{
- if (ir->bPull)
- {
- ir->awhParams = gmx::readAndCheckAwhParams(&inp, ir, wi);
- }
- else
- {
- gmx_fatal(FARGS, "AWH biasing is only compatible with COM pulling turned on");
- }
+ ir->awhParams = gmx::readAwhParams(&inp, wi);
}
/* Enforced rotation */
}
}
- sfree(dumstr[0]);
- sfree(dumstr[1]);
-}
-
-static int search_QMstring(const char* s, int ng, const char* gn[])
-{
- /* same as normal search_string, but this one searches QM strings */
- int i;
-
- for (i = 0; (i < ng); i++)
+ if (ir->bDoAwh)
{
- if (gmx_strcasecmp(s, gn[i]) == 0)
- {
- return i;
- }
+ gmx::checkAwhParams(ir->awhParams, ir, wi);
}
- gmx_fatal(FARGS, "this QM method or basisset (%s) is not implemented\n!", s);
-} /* search_QMstring */
+ sfree(dumstr[0]);
+ sfree(dumstr[1]);
+}
/* We would like gn to be const as well, but C doesn't allow this */
/* TODO this is utility functionality (search for the index of a
gmx::IndexGroupsAndNames defaultIndexGroupsAndNames(
*defaultIndexGroups, gmx::arrayRefFromArray(gnames, defaultIndexGroups->nr));
- notifier.notifier_.notify(defaultIndexGroupsAndNames);
+ notifier.preProcessingNotifications_.notify(defaultIndexGroupsAndNames);
auto accelerations = gmx::splitString(is->acc);
auto accelerationGroupNames = gmx::splitString(is->accgrps);
SimulationAtomGroupType::OrientationRestraintsFit, restnm, egrptpALL_GENREST,
bVerbose, wi);
- /* QMMM input processing */
+ /* MiMiC QMMM input processing */
auto qmGroupNames = gmx::splitString(is->QMMM);
- auto qmMethods = gmx::splitString(is->QMmethod);
- auto qmBasisSets = gmx::splitString(is->QMbasis);
- if (ir->eI != eiMimic)
- {
- if (qmMethods.size() != qmGroupNames.size() || qmBasisSets.size() != qmGroupNames.size())
- {
- gmx_fatal(FARGS,
- "Invalid QMMM input: %zu groups %zu basissets"
- " and %zu methods\n",
- qmGroupNames.size(), qmBasisSets.size(), qmMethods.size());
- }
- /* group rest, if any, is always MM! */
- do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
- nr = qmGroupNames.size(); /*atoms->grps[egcQMMM].nr;*/
- ir->opts.ngQM = qmGroupNames.size();
- snew(ir->opts.QMmethod, nr);
- snew(ir->opts.QMbasis, nr);
- for (i = 0; i < nr; i++)
- {
- /* input consists of strings: RHF CASSCF PM3 .. These need to be
- * converted to the corresponding enum in names.c
- */
- ir->opts.QMmethod[i] = search_QMstring(qmMethods[i].c_str(), eQMmethodNR, eQMmethod_names);
- ir->opts.QMbasis[i] = search_QMstring(qmBasisSets[i].c_str(), eQMbasisNR, eQMbasis_names);
- }
- auto qmMultiplicities = gmx::splitString(is->QMmult);
- auto qmCharges = gmx::splitString(is->QMcharge);
- auto qmbSH = gmx::splitString(is->bSH);
- snew(ir->opts.QMmult, nr);
- snew(ir->opts.QMcharge, nr);
- snew(ir->opts.bSH, nr);
- convertInts(wi, qmMultiplicities, "QMmult", ir->opts.QMmult);
- convertInts(wi, qmCharges, "QMcharge", ir->opts.QMcharge);
- convertYesNos(wi, qmbSH, "bSH", ir->opts.bSH);
-
- auto CASelectrons = gmx::splitString(is->CASelectrons);
- auto CASorbitals = gmx::splitString(is->CASorbitals);
- snew(ir->opts.CASelectrons, nr);
- snew(ir->opts.CASorbitals, nr);
- convertInts(wi, CASelectrons, "CASelectrons", ir->opts.CASelectrons);
- convertInts(wi, CASorbitals, "CASOrbitals", ir->opts.CASorbitals);
-
- auto SAon = gmx::splitString(is->SAon);
- auto SAoff = gmx::splitString(is->SAoff);
- auto SAsteps = gmx::splitString(is->SAsteps);
- snew(ir->opts.SAon, nr);
- snew(ir->opts.SAoff, nr);
- snew(ir->opts.SAsteps, nr);
- convertInts(wi, SAon, "SAon", ir->opts.SAon);
- convertInts(wi, SAoff, "SAoff", ir->opts.SAoff);
- convertInts(wi, SAsteps, "SAsteps", ir->opts.SAsteps);
- }
- else
+ if (qmGroupNames.size() > 1)
{
- /* MiMiC */
- if (qmGroupNames.size() > 1)
- {
- gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
- }
- /* group rest, if any, is always MM! */
- do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
- SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
-
- ir->opts.ngQM = qmGroupNames.size();
+ gmx_fatal(FARGS, "Currently, having more than one QM group in MiMiC is not supported");
}
+ /* group rest, if any, is always MM! */
+ do_numbering(natoms, groups, qmGroupNames, defaultIndexGroups, gnames,
+ SimulationAtomGroupType::QuantumMechanics, restnm, egrptpALL_GENREST, bVerbose, wi);
+ ir->opts.ngQM = qmGroupNames.size();
- /* end of QMMM input */
+ /* end of MiMiC QMMM input */
if (bVerbose)
{
char warn_buf[STRLEN];
const char* ptr;
- ptr = check_box(ir->ePBC, box);
+ ptr = check_box(ir->pbcType, box);
if (ptr)
{
warning_error(wi, ptr);
ir->LincsWarnAngle = 90.0;
}
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
if (ir->nstlist == 0)
{
"With nstlist=0 atoms are only put into the box at step 0, therefore drifting "
"atoms might cause the simulation to crash.");
}
- if (gmx::square(ir->rlist) >= max_cutoff2(ir->ePBC, box))
+ if (gmx::square(ir->rlist) >= max_cutoff2(ir->pbcType, box))
{
sprintf(warn_buf,
"ERROR: The cut-off length is longer than half the shortest box vector or "
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/mdatoms.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/pull_params.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
update_mdatoms(md, lambda);
}
- set_pbc(&pbc, ir->ePBC, box);
+ set_pbc(&pbc, ir->pbcType, box);
t_start = ir->init_t + ir->init_step * ir->delta_t;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strdb.h"
{
a->m = m;
at.addType(tab, *a, name, InteractionOfType({}, {}), 0, 0);
- fflush(stderr);
}
else
{
}
}
-static void check_rtp(gmx::ArrayRef<const PreprocessResidue> rtpDBEntry, const std::string& libfn)
+static void check_rtp(gmx::ArrayRef<const PreprocessResidue> rtpDBEntry,
+ const std::string& libfn,
+ const gmx::MDLogger& logger)
{
/* check for double entries, assuming list is already sorted */
for (auto it = rtpDBEntry.begin() + 1; it != rtpDBEntry.end(); it++)
auto prev = it - 1;
if (gmx::equalCaseInsensitive(prev->resname, it->resname))
{
- fprintf(stderr, "WARNING double entry %s in file %s\n", it->resname.c_str(), libfn.c_str());
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("Double entry %s in file %s", it->resname.c_str(), libfn.c_str());
}
}
}
static_cast<int>(rtpDBEntry[0].bRemoveDihedralIfWithImproper));
}
+
+static void print_resall_log(const gmx::MDLogger& logger, gmx::ArrayRef<const PreprocessResidue> rtpDBEntry)
+{
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("[ bondedtypes ]");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "; bonds angles dihedrals impropers all_dihedrals nr_exclusions HH14 "
+ "remove_dih");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ " %5d %6d %9d %9d %14d %14d %14d %14d", rtpDBEntry[0].rb[0].type,
+ rtpDBEntry[0].rb[1].type, rtpDBEntry[0].rb[2].type, rtpDBEntry[0].rb[3].type,
+ static_cast<int>(rtpDBEntry[0].bKeepAllGeneratedDihedrals),
+ rtpDBEntry[0].nrexcl, static_cast<int>(rtpDBEntry[0].bGenerateHH14Interactions),
+ static_cast<int>(rtpDBEntry[0].bRemoveDihedralIfWithImproper));
+}
+
+
void print_resall(FILE* out, gmx::ArrayRef<const PreprocessResidue> rtpDBEntry, const PreprocessingAtomTypes& atype)
{
if (rtpDBEntry.empty())
std::vector<PreprocessResidue>* rtpDBEntry,
PreprocessingAtomTypes* atype,
t_symtab* tab,
+ const gmx::MDLogger& logger,
bool bAllowOverrideRTP)
{
FILE* in;
get_a_line(in, line, STRLEN);
if (nparam < 5)
{
- fprintf(stderr, "Using default: not generating all possible dihedrals\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Using default: not generating all possible dihedrals");
header_settings.bKeepAllGeneratedDihedrals = FALSE;
}
if (nparam < 6)
{
- fprintf(stderr, "Using default: excluding 3 bonded neighbors\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Using default: excluding 3 bonded neighbors");
header_settings.nrexcl = 3;
}
if (nparam < 7)
{
- fprintf(stderr, "Using default: generating 1,4 H--H interactions\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Using default: generating 1,4 H--H interactions");
header_settings.bGenerateHH14Interactions = TRUE;
}
if (nparam < 8)
{
- fprintf(stderr,
- "Using default: removing proper dihedrals found on the same bond as a proper "
- "dihedral\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Using default: removing proper dihedrals found on the same bond as a "
+ "proper dihedral");
header_settings.bRemoveDihedralIfWithImproper = TRUE;
}
}
else
{
- fprintf(stderr,
- "Reading .rtp file without '[ bondedtypes ]' directive,\n"
- "Will proceed as if the entry was:\n");
- print_resall_header(stderr, gmx::arrayRefFromArray(&header_settings, 1));
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Reading .rtp file without '[ bondedtypes ]' directive, "
+ "Will proceed as if the entry was:");
+ print_resall_log(logger, gmx::arrayRefFromArray(&header_settings, 1));
}
/* We don't know the current size of rrtp, but simply realloc immediately */
auto oldArrayEnd = rtpDBEntry->end();
}
if (bAllowOverrideRTP)
{
- fprintf(stderr,
- "Found another rtp entry for '%s' in '%s', ignoring this entry and keeping "
- "the one from '%s.rtp'\n",
- res->resname.c_str(), rrdb.c_str(), found->filebase.c_str());
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Found another rtp entry for '%s' in '%s',"
+ " ignoring this entry and keeping the one from '%s.rtp'",
+ res->resname.c_str(), rrdb.c_str(), found->filebase.c_str());
/* We should free all the data for this entry.
* The current code gives a lot of dangling pointers.
*/
[](const char& c1, const char& c2) { return std::toupper(c1) < std::toupper(c2); });
});
- check_rtp(*rtpDBEntry, rrdb);
+ check_rtp(*rtpDBEntry, rrdb, logger);
}
/************************************************************
}
}
-std::string searchResidueDatabase(const std::string& key, gmx::ArrayRef<const PreprocessResidue> rtpDBEntry)
+std::string searchResidueDatabase(const std::string& key,
+ gmx::ArrayRef<const PreprocessResidue> rtpDBEntry,
+ const gmx::MDLogger& logger)
{
int nbest, best, besti;
std::string bestbuf;
}
if (!gmx::equalCaseInsensitive(rtpDBEntry[besti].resname, key))
{
- fprintf(stderr,
- "\nWARNING: '%s' not found in residue topology database, "
- "trying to use '%s'\n\n",
- key.c_str(), rtpDBEntry[besti].resname.c_str());
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "'%s' not found in residue topology database, "
+ "trying to use '%s'",
+ key.c_str(), rtpDBEntry[besti].resname.c_str());
}
return rtpDBEntry[besti].resname;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
class PreprocessingAtomTypes;
+
+namespace gmx
+{
+class MDLogger;
+}
struct PreprocessResidue;
struct t_symtab;
*
* \param[in] key The atomname to search for.
* \param[in] rtpDBEntry Database with residue information.
+ * \param[in] logger Logging object.
* \returns The rtp residue name.
*/
-std::string searchResidueDatabase(const std::string& key, gmx::ArrayRef<const PreprocessResidue> rtpDBEntry);
+std::string searchResidueDatabase(const std::string& key,
+ gmx::ArrayRef<const PreprocessResidue> rtpDBEntry,
+ const gmx::MDLogger& logger);
/*! \brief
* Returns matching entry in database.
* \param[inout] rtpDBEntry Database to populate.
* \param[inout] atype Atomtype information.
* \param[inout] tab Symbol table for names.
+ * \param[in] logger MDLogger interface.
* \param[in] bAllowOverrideRTP If entries can be overwritten in the database.
*/
void readResidueDatabase(const std::string& resdb,
std::vector<PreprocessResidue>* rtpDBEntry,
PreprocessingAtomTypes* atype,
t_symtab* tab,
+ const gmx::MDLogger& logger,
bool bAllowOverrideRTP);
/*! \brief
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_symtab* symtab,
std::vector<RVec>* x,
std::vector<RVec>* v,
- int ePBC,
+ PbcType pbcType,
matrix box,
AtomProperties* aps,
real defaultDistance,
gmx_mtop_t topSolvent;
std::vector<RVec> xSolvent, vSolvent;
matrix boxSolvent = { { 0 } };
- int ePBCSolvent;
+ PbcType pbcTypeSolvent;
fprintf(stderr, "Reading solvent configuration\n");
bool bTprFileWasRead;
rvec *temporaryX = nullptr, *temporaryV = nullptr;
readConfAndTopology(gmx::findLibraryFile(filename).c_str(), &bTprFileWasRead, &topSolvent,
- &ePBCSolvent, &temporaryX, &temporaryV, boxSolvent);
+ &pbcTypeSolvent, &temporaryX, &temporaryV, boxSolvent);
t_atoms* atomsSolvent;
snew(atomsSolvent, 1);
*atomsSolvent = gmx_mtop_global_atoms(&topSolvent);
/* generate a new solvent configuration */
fprintf(stderr, "Generating solvent configuration\n");
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
if (!gmx::boxesAreEqual(boxSolvent, box))
{
if (TRICLINIC(boxSolvent))
/* apply pbc for solvent configuration for whole molecules */
rm_res_pbc(atomsSolvent, &xSolvent, boxSolvent);
replicateSolventBox(atomsSolvent, &xSolvent, &vSolvent, &exclusionDistances_solvt, boxSolvent, box);
- if (ePBC != epbcNONE)
+ if (pbcType != PbcType::No)
{
removeSolventBoxOverlap(atomsSolvent, &xSolvent, &vSolvent, &exclusionDistances_solvt, pbc);
}
/* solute configuration data */
gmx_mtop_t top;
std::vector<RVec> x, v;
- matrix box = { { 0 } };
- int ePBC = -1;
+ matrix box = { { 0 } };
+ PbcType pbcType = PbcType::Unset;
t_atoms* atoms;
snew(atoms, 1);
if (bProt)
fprintf(stderr, "Reading solute configuration%s\n", bReadV ? " and velocities" : "");
bool bTprFileWasRead;
rvec *temporaryX = nullptr, *temporaryV = nullptr;
- readConfAndTopology(conf_prot, &bTprFileWasRead, &top, &ePBC, &temporaryX,
+ readConfAndTopology(conf_prot, &bTprFileWasRead, &top, &pbcType, &temporaryX,
bReadV ? &temporaryV : nullptr, box);
*atoms = gmx_mtop_global_atoms(&top);
x.assign(temporaryX, temporaryX + top.natoms);
firstSolventResidueIndex = atoms->nres;
}
}
- int ePBCForOutput = ePBC;
+ PbcType pbcTypeForOutput = pbcType;
if (bBox)
{
- ePBCForOutput = epbcXYZ;
+ pbcTypeForOutput = PbcType::Xyz;
clear_mat(box);
box[XX][XX] = new_box[XX];
box[YY][YY] = new_box[YY];
"or give explicit -box command line option");
}
- add_solv(solventFileName, atoms, &top.symtab, &x, &v, ePBCForOutput, box, &aps, defaultDistance,
- scaleFactor, r_shell, max_sol);
+ add_solv(solventFileName, atoms, &top.symtab, &x, &v, pbcTypeForOutput, box, &aps,
+ defaultDistance, scaleFactor, r_shell, max_sol);
/* write new configuration 1 to file confout */
confout = ftp2fn(efSTO, NFILE, fnm);
fprintf(stderr, "Writing generated configuration to %s\n", confout);
const char* outputTitle = (bProt ? *top.name : "Generated by gmx solvate");
write_sto_conf(confout, outputTitle, atoms, as_rvec_array(x.data()),
- !v.empty() ? as_rvec_array(v.data()) : nullptr, ePBCForOutput, box);
+ !v.empty() ? as_rvec_array(v.data()) : nullptr, pbcTypeForOutput, box);
/* print size of generated configuration */
fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n", atoms->nr, atoms->nres);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-gmx_add_unit_test(GmxPreprocessTests gmxpreprocess-test
- editconf.cpp
- genconf.cpp
- genion.cpp
- gpp_atomtype.cpp
- gpp_bond_atomtype.cpp
- insert_molecules.cpp
- readir.cpp
- solvate.cpp
- topdirs.cpp
- )
+gmx_add_gtest_executable(gmxpreprocess-test
+ CPP_SOURCE_FILES
+ editconf.cpp
+ genconf.cpp
+ genion.cpp
+ gpp_atomtype.cpp
+ gpp_bond_atomtype.cpp
+ insert_molecules.cpp
+ readir.cpp
+ solvate.cpp
+ topdirs.cpp
+ )
+gmx_register_gtest_test(GmxPreprocessTests gmxpreprocess-test SLOW_TEST)
# Currently these can be slow to run in Jenkins, so they are in
# several test binaries.
set(exename pdb2gmx1-test)
gmx_add_gtest_executable(${exename}
- pdb2gmx.cpp
-)
+ CPP_SOURCE_FILES
+ pdb2gmx.cpp
+ )
target_compile_definitions(${exename} PRIVATE OPLSAA=1 GROMOS=0 AMBER=0 CHARMM=0)
-gmx_register_gtest_test(Pdb2gmx1Test ${exename})
+gmx_register_gtest_test(Pdb2gmx1Test ${exename} SLOW_TEST)
set(exename pdb2gmx2-test)
gmx_add_gtest_executable(${exename}
- pdb2gmx.cpp
- )
+ CPP_SOURCE_FILES
+ pdb2gmx.cpp
+ )
target_compile_definitions(${exename} PRIVATE OPLSAA=0 GROMOS=1 AMBER=0 CHARMM=0)
-gmx_register_gtest_test(Pdb2gmx2Test ${exename})
+gmx_register_gtest_test(Pdb2gmx2Test ${exename} SLOW_TEST)
set(exename pdb2gmx3-test)
gmx_add_gtest_executable(${exename}
- pdb2gmx.cpp
- )
+ CPP_SOURCE_FILES
+ pdb2gmx.cpp
+ )
target_compile_definitions(${exename} PRIVATE OPLSAA=0 GROMOS=0 AMBER=1 CHARMM=1)
-gmx_register_gtest_test(Pdb2gmx3Test ${exename})
+gmx_register_gtest_test(Pdb2gmx3Test ${exename} SLOW_TEST)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
#include <memory>
-
#include <unordered_set>
+
#include <sys/types.h>
#include "gromacs/fileio/gmxfio.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/pleasecite.h"
#include "gromacs/utility/smalloc.h"
bool bFEP,
bool bZero,
bool usingFullRangeElectrostatics,
- warninp* wi)
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
FILE* out;
int sl, nb_funct;
bGenPairs ? &pair : nullptr, wi);
break;
- case Directive::d_bondtypes:
- push_bt(d, interactions, 2, nullptr, &bondAtomType, pline, wi);
- break;
+ case Directive::d_bondtypes: // Intended to fall through
case Directive::d_constrainttypes:
push_bt(d, interactions, 2, nullptr, &bondAtomType, pline, wi);
break;
push_nbt(d, nbparam, atypes, pline, nb_funct, wi);
break;
- case Directive::d_implicit_genborn_params:
+ case Directive::d_implicit_genborn_params: // NOLINT bugprone-branch-clone
// Skip this line, so old topologies with
// GB parameters can be read.
break;
generate_nbparams(*combination_rule, nb_funct,
&(interactions[nb_funct]), atypes, wi);
ncopy = copy_nbparams(nbparam, nb_funct, &(interactions[nb_funct]), ntype);
- fprintf(stderr,
- "Generated %d of the %d non-bonded parameter "
- "combinations\n",
- ncombs - ncopy, ncombs);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Generated %d of the %d non-bonded parameter "
+ "combinations",
+ ncombs - ncopy, ncombs);
free_nbparam(nbparam, ntype);
if (bGenPairs)
{
gen_pairs((interactions[nb_funct]), &(interactions[F_LJ14]),
fudgeLJ, *combination_rule);
ncopy = copy_nbparams(pair, nb_funct, &(interactions[F_LJ14]), ntype);
- fprintf(stderr,
- "Generated %d of the %d 1-4 parameter combinations\n",
- ncombs - ncopy, ncombs);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Generated %d of the %d 1-4 parameter "
+ "combinations",
+ ncombs - ncopy, ncombs);
free_nbparam(pair, ntype);
}
/* Copy GBSA parameters to atomtype array? */
{
gmx_fatal(FARGS, "Molecule type '%s' contains no atoms", *mi0->name);
}
- fprintf(stderr, "Excluding %d bonded neighbours molecule type '%s'\n",
- mi0->nrexcl, *mi0->name);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Excluding %d bonded neighbours molecule type '%s'",
+ mi0->nrexcl, *mi0->name);
sum_q(&mi0->atoms, nrcopies, &qt, &qBt);
if (!mi0->bProcessed)
{
generate_excl(mi0->nrexcl, mi0->atoms.nr, mi0->interactions, &(mi0->excls));
gmx::mergeExclusions(&(mi0->excls), exclusionBlocks[whichmol]);
- make_shake(mi0->interactions, &mi0->atoms, opts->nshake);
+ make_shake(mi0->interactions, &mi0->atoms, opts->nshake, logger);
if (bCouple)
{
break;
}
default:
- fprintf(stderr, "case: %d\n", static_cast<int>(d));
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted("case: %d", static_cast<int>(d));
gmx_incons("unknown directive");
}
}
"algorithms "
"can be found at https://doi.org/10.26434/chemrxiv.11474583.v1 .");
}
+ // TODO: Update URL for Issue #2884 in conjunction with updating grompp.warn in regressiontests.
cpp_done(handle);
{
gmx_fatal(FARGS, "Did not find any molecules of type '%s' for coupling", opts->couple_moltype);
}
- fprintf(stderr, "Coupling %d copies of molecule type '%s'\n", nmol_couple, opts->couple_moltype);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Coupling %d copies of molecule type '%s'", nmol_couple,
+ opts->couple_moltype);
}
/* this is not very clean, but fixes core dump on empty system name */
const t_inputrec* ir,
std::vector<gmx_molblock_t>* molblock,
bool* ffParametrizedWithHBondConstraints,
- warninp* wi)
+ warninp* wi,
+ const gmx::MDLogger& logger)
{
/* Tmpfile might contain a long path */
const char* tmpfile;
if (bVerbose)
{
- printf("processing topology...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("processing topology...");
}
title = read_topol(topfile, tmpfile, opts->define, opts->include, symtab, atypes, molinfo,
intermolecular_interactions, interactions, combination_rule, repulsion_power,
opts, fudgeQQ, molblock, ffParametrizedWithHBondConstraints,
- ir->efep != efepNO, bZero, EEL_FULL(ir->coulombtype), wi);
+ ir->efep != efepNO, bZero, EEL_FULL(ir->coulombtype), wi, logger);
if ((*combination_rule != eCOMB_GEOMETRIC) && (ir->vdwtype == evdwUSER))
{
}
/*! \brief
- * Generate exclusion lists for QM/MM.
+ * Exclude molecular interactions for QM atoms handled by MiMic.
*
- * This routine updates the exclusion lists for QM atoms in order to include all other QM
- * atoms of this molecule. Moreover, this routine replaces bonds between QM atoms with
- * CONNBOND and, when MiMiC is not used, removes bonded interactions between QM and link atoms.
- * Finally, in case if MiMiC QM/MM is used - charges of QM atoms are set to 0
+ * Update the exclusion lists to include all QM atoms of this molecule,
+ * replace bonds between QM atoms with CONNBOND and
+ * set charges of QM atoms to 0.
*
- * @param molt molecule type with QM atoms
- * @param grpnr group informatio
- * @param ir input record
- * @param qmmmMode QM/MM mode switch: original/MiMiC
+ * \param[in,out] molt molecule type with QM atoms
+ * \param[in] grpnr group informatio
+ * \param[in,out] ir input record
+ * \param[in] logger Handle to logging interface.
*/
-static void generate_qmexcl_moltype(gmx_moltype_t* molt, const unsigned char* grpnr, t_inputrec* ir, GmxQmmmMode qmmmMode)
+static void generate_qmexcl_moltype(gmx_moltype_t* molt,
+ const unsigned char* grpnr,
+ t_inputrec* ir,
+ const gmx::MDLogger& logger)
{
/* This routine expects molt->ilist to be of size F_NRE and ordered. */
* these interactions should be handled by the QM subroutines and
* not by the gromacs routines
*/
- int qm_max = 0, qm_nr = 0, link_nr = 0, link_max = 0;
+ int qm_max = 0, qm_nr = 0, link_nr = 0;
int * qm_arr = nullptr, *link_arr = nullptr;
- bool *bQMMM, *blink;
+ bool* bQMMM;
/* First we search and select the QM atoms in an qm_arr array that
* we use to create the exclusions.
*/
int ftype_connbond = 0;
int ind_connbond = 0;
- if (molt->ilist[F_CONNBONDS].size() != 0)
+ if (!molt->ilist[F_CONNBONDS].empty())
{
- fprintf(stderr, "nr. of CONNBONDS present already: %d\n", molt->ilist[F_CONNBONDS].size() / 3);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("nr. of CONNBONDS present already: %d",
+ molt->ilist[F_CONNBONDS].size() / 3);
ftype_connbond = molt->ilist[F_CONNBONDS].iatoms[0];
ind_connbond = molt->ilist[F_CONNBONDS].size();
}
/* MiMiC treats link atoms as quantum atoms - therefore
* we do not need do additional exclusions here */
- if (qmmmMode == GmxQmmmMode::GMX_QMMM_MIMIC)
- {
- bexcl = numQmAtoms == nratoms;
- }
- else
- {
- bexcl = (numQmAtoms >= nratoms - 1);
- }
+ bexcl = numQmAtoms == nratoms;
if (bexcl && ftype == F_SETTLE)
{
* linkatoms interaction with the QMatoms and would be counted
* twice. */
- if (qmmmMode != GmxQmmmMode::GMX_QMMM_MIMIC)
- {
- for (int i = 0; i < F_NRE; i++)
- {
- if (IS_CHEMBOND(i))
- {
- int j = 0;
- while (j < molt->ilist[i].size())
- {
- int a1 = molt->ilist[i].iatoms[j + 1];
- int a2 = molt->ilist[i].iatoms[j + 2];
- if ((bQMMM[a1] && !bQMMM[a2]) || (!bQMMM[a1] && bQMMM[a2]))
- {
- if (link_nr >= link_max)
- {
- link_max += 10;
- srenew(link_arr, link_max);
- }
- if (bQMMM[a1])
- {
- link_arr[link_nr++] = a2;
- }
- else
- {
- link_arr[link_nr++] = a1;
- }
- }
- j += 3;
- }
- }
- }
- }
- snew(blink, molt->atoms.nr);
- for (int i = 0; i < molt->atoms.nr; i++)
- {
- blink[i] = FALSE;
- }
-
- if (qmmmMode != GmxQmmmMode::GMX_QMMM_MIMIC)
- {
- for (int i = 0; i < link_nr; i++)
- {
- blink[link_arr[i]] = TRUE;
- }
- }
/* creating the exclusion block for the QM atoms. Each QM atom has
* as excluded elements all the other QMatoms (and itself).
*/
}
j += (qm_nr + link_nr);
}
- if (blink[i])
- {
- for (int k = 0; k < qm_nr; k++)
- {
- qmexcl.a[k + j] = qm_arr[k];
- }
- j += qm_nr;
- }
}
qmexcl.index[qmexcl.nr] = j;
int j = 0;
while (j < molt->ilist[i].size())
{
- int a1 = molt->ilist[i].iatoms[j + 1];
- int a2 = molt->ilist[i].iatoms[j + 2];
- bool bexcl =
- ((bQMMM[a1] && bQMMM[a2]) || (blink[a1] && bQMMM[a2]) || (bQMMM[a1] && blink[a2]));
+ int a1 = molt->ilist[i].iatoms[j + 1];
+ int a2 = molt->ilist[i].iatoms[j + 2];
+ bool bexcl = (bQMMM[a1] && bQMMM[a2]);
if (bexcl)
{
/* since the interaction involves QM atoms, these should be
free(qm_arr);
free(bQMMM);
free(link_arr);
- free(blink);
} /* generate_qmexcl */
-void generate_qmexcl(gmx_mtop_t* sys, t_inputrec* ir, warninp* wi, GmxQmmmMode qmmmMode)
+void generate_qmexcl(gmx_mtop_t* sys, t_inputrec* ir, const gmx::MDLogger& logger)
{
/* This routine expects molt->molt[m].ilist to be of size F_NRE and ordered.
*/
/* Copy the exclusions to a new array, since this is the only
* thing that needs to be modified for QMMM.
*/
- copy_blocka(&sys->moltype[molb->type].excls, &sys->moltype.back().excls);
+ sys->moltype.back().excls = sys->moltype[molb->type].excls;
/* Set the molecule type for the QMMM molblock */
molb->type = sys->moltype.size() - 1;
}
- generate_qmexcl_moltype(&sys->moltype[molb->type], grpnr, ir, qmmmMode);
+ generate_qmexcl_moltype(&sys->moltype[molb->type], grpnr, ir, logger);
}
if (grpnr)
{
index_offset += nat_mol;
}
}
- if (qmmmMode == GmxQmmmMode::GMX_QMMM_ORIGINAL && nr_mol_with_qm_atoms > 1)
- {
- /* generate a warning is there are QM atoms in different
- * topologies. In this case it is not possible at this stage to
- * mutualy exclude the non-bonded interactions via the
- * exclusions (AFAIK). Instead, the user is advised to use the
- * energy group exclusions in the mdp file
- */
- warning_note(wi,
- "\nThe QM subsystem is divided over multiple topologies. "
- "The mutual non-bonded interactions cannot be excluded. "
- "There are two ways to achieve this:\n\n"
- "1) merge the topologies, such that the atoms of the QM "
- "subsystem are all present in one single topology file. "
- "In this case this warning will dissappear\n\n"
- "2) exclude the non-bonded interactions explicitly via the "
- "energygrp-excl option in the mdp file. if this is the case "
- "this warning may be ignored"
- "\n\n");
- }
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct InteractionsOfType;
struct t_symtab;
struct warninp;
-enum struct GmxQmmmMode;
typedef warninp* warninp_t;
+namespace gmx
+{
+class MDLogger;
+}
+
double check_mol(const gmx_mtop_t* mtop, warninp_t wi);
/* Check mass and charge */
const t_inputrec* ir,
std::vector<gmx_molblock_t>* molblock,
bool* ffParametrizedWithHBondConstraints,
- warninp_t wi);
+ warninp_t wi,
+ const gmx::MDLogger& logger);
/* This routine expects sys->molt[m].ilist to be of size F_NRE and ordered. */
-void generate_qmexcl(gmx_mtop_t* sys, t_inputrec* ir, warninp_t wi, GmxQmmmMode qmmmMode);
+void generate_qmexcl(gmx_mtop_t* sys, t_inputrec* ir, const gmx::MDLogger& logger);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, InteractionsOfType* nbp, warninp* wi)
{
- int n, ntype;
- t_atom* atom;
- t_blocka* excl;
- bool bExcl;
+ int n, ntype;
+ t_atom* atom;
n = mol->atoms.nr;
atom = mol->atoms.atom;
"Number of pairs of generated non-bonded parameters should be a perfect square");
/* Add a pair interaction for all non-excluded atom pairs */
- excl = &mol->excls;
+ const auto& excls = mol->excls;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
- bExcl = FALSE;
- for (int k = excl->index[i]; k < excl->index[i + 1]; k++)
+ bool pairIsExcluded = false;
+ for (const int atomK : excls[i])
{
- if (excl->a[k] == j)
+ if (atomK == j)
{
- bExcl = TRUE;
+ pairIsExcluded = true;
}
}
- if (!bExcl)
+ if (!pairIsExcluded)
{
if (nb_funct != F_LJ)
{
}
}
-static void set_excl_all(t_blocka* excl)
+static void set_excl_all(gmx::ListOfLists<int>* excl)
{
- int nat, i, j, k;
-
/* Get rid of the current exclusions and exclude all atom pairs */
- nat = excl->nr;
- excl->nra = nat * nat;
- srenew(excl->a, excl->nra);
- k = 0;
- for (i = 0; i < nat; i++)
+ const int numAtoms = excl->ssize();
+ std::vector<int> exclusionsForAtom(numAtoms);
+ for (int i = 0; i < numAtoms; i++)
{
- excl->index[i] = k;
- for (j = 0; j < nat; j++)
- {
- excl->a[k++] = j;
- }
+ exclusionsForAtom[i] = i;
+ }
+ excl->clear();
+ for (int i = 0; i < numAtoms; i++)
+ {
+ excl->pushBack(exclusionsForAtom);
}
- excl->index[nat] = k;
}
static void decouple_atoms(t_atoms* atoms,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/units.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
static int count_hydrogens(char*** atomname, int nra, gmx::ArrayRef<const int> a)
return nh;
}
-void make_shake(gmx::ArrayRef<InteractionsOfType> plist, t_atoms* atoms, int nshake)
+void make_shake(gmx::ArrayRef<InteractionsOfType> plist, t_atoms* atoms, int nshake, const gmx::MDLogger& logger)
{
char*** info = atoms->atomname;
real b_ij, b_jk;
{
switch (nshake)
{
- case eshHBONDS: printf("turning H bonds into constraints...\n"); break;
- case eshALLBONDS: printf("turning all bonds into constraints...\n"); break;
- case eshHANGLES: printf("turning all bonds and H angles into constraints...\n"); break;
- case eshALLANGLES: printf("turning all bonds and angles into constraints...\n"); break;
+ case eshHBONDS:
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("turning H bonds into constraints...");
+ break;
+ case eshALLBONDS:
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("turning all bonds into constraints...");
+ break;
+ case eshHANGLES:
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("turning all bonds and H angles into constraints...");
+ break;
+ case eshALLANGLES:
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("turning all bonds and angles into constraints...");
+ break;
default: gmx_fatal(FARGS, "Invalid option for make_shake (%d)", nshake);
}
{
const InteractionOfType* ang = &(*parm);
#ifdef DEBUG
- printf("Angle: %d-%d-%d\n", ang->ai(), ang->aj(), ang->ak());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Angle: %d-%d-%d", ang->ai(),
+ ang->aj(), ang->ak());
#endif
int numhydrogens = count_hydrogens(info, 3, ang->atoms());
if ((nshake == eshALLANGLES) || (numhydrogens > 1)
}
/* apply law of cosines */
#ifdef DEBUG
- printf("p: %d, q: %d, dist: %12.5e\n", atomNumbers[0],
- atomNumbers[1], forceParm[0]);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("p: %d, q: %d, dist: %12.5e",
+ atomNumbers[0], atomNumbers[1],
+ forceParm[0]);
#endif
add_param_to_list(&(plist[F_CONSTR]),
InteractionOfType(atomNumbers, forceParm));
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_atoms;
struct InteractionsOfType;
-void make_shake(gmx::ArrayRef<InteractionsOfType> plist, t_atoms* atoms, int nshake);
+namespace gmx
+{
+class MDLogger;
+}
+
+void make_shake(gmx::ArrayRef<InteractionsOfType> plist, t_atoms* atoms, int nshake, const gmx::MDLogger& logger);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int f = 0;
switch (ftype)
{
- case F_G96ANGLES: f = 1; break;
+ case F_G96ANGLES: // Intended to fall through
case F_G96BONDS: f = 1; break;
case F_MORSE: f = 2; break;
case F_CUBICBONDS: f = 3; break;
case F_CROSS_BOND_ANGLES: f = 2; break;
case F_CROSS_BOND_BONDS: f = 3; break;
case F_UREY_BRADLEY: f = 4; break;
- case F_PDIHS:
- case F_RBDIHS:
+ case F_PDIHS: // Intended to fall through
+ case F_RBDIHS: // Intended to fall through
case F_FOURDIHS: bDih = TRUE; break;
case F_IDIHS:
f = 1;
bDih = TRUE;
break;
- case F_CONSTRNC: f = 1; break;
+ case F_CONSTRNC: // Intended to fall through
case F_VSITE3FD: f = 1; break;
case F_VSITE3FAD: f = 2; break;
case F_VSITE3OUT: f = 3; break;
- case F_VSITE4FDN: f = 1; break;
+ case F_VSITE4FDN: // Intended to fall through
case F_CMAP: f = 1; break;
default: bDih = FALSE;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strconvert.h"
static bool calc_vsite4fd_param(InteractionOfType* vsite,
gmx::ArrayRef<const VsiteBondedInteraction> bonds,
- gmx::ArrayRef<const VsiteBondedInteraction> angles)
+ gmx::ArrayRef<const VsiteBondedInteraction> angles,
+ const gmx::MDLogger& logger)
{
/* i = virtual site | ,k
* j = 1st bonded heavy atom | i-j-m
cosakm = (std::cos(akjm) - std::cos(aijk) * std::cos(aijm)) / (std::sin(aijk) * std::sin(aijm));
if (cosakl < -1 || cosakl > 1 || cosakm < -1 || cosakm > 1)
{
- fprintf(stderr, "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f\n",
- vsite->ai() + 1, RAD2DEG * aijk, RAD2DEG * aijl, RAD2DEG * aijm);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f",
+ vsite->ai() + 1, RAD2DEG * aijk, RAD2DEG * aijl, RAD2DEG * aijm);
gmx_fatal(FARGS,
"invalid construction in calc_vsite4fd for atom %d: "
"cosakl=%f, cosakm=%f\n",
static bool calc_vsite4fdn_param(InteractionOfType* vsite,
gmx::ArrayRef<const VsiteBondedInteraction> bonds,
- gmx::ArrayRef<const VsiteBondedInteraction> angles)
+ gmx::ArrayRef<const VsiteBondedInteraction> angles,
+ const gmx::MDLogger& logger)
{
/* i = virtual site | ,k
* j = 1st bonded heavy atom | i-j-m
if (fabs(pl) < 1000 * GMX_REAL_MIN || fabs(pm) < 1000 * GMX_REAL_MIN)
{
- fprintf(stderr, "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f\n",
- vsite->ai() + 1, RAD2DEG * aijk, RAD2DEG * aijl, RAD2DEG * aijm);
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "virtual site %d: angle ijk = %f, angle ijl = %f, angle ijm = %f",
+ vsite->ai() + 1, RAD2DEG * aijk, RAD2DEG * aijl, RAD2DEG * aijm);
gmx_fatal(FARGS,
"invalid construction in calc_vsite4fdn for atom %d: "
"pl=%f, pm=%f\n",
}
-int set_vsites(bool bVerbose, t_atoms* atoms, PreprocessingAtomTypes* atypes, gmx::ArrayRef<InteractionsOfType> plist)
+int set_vsites(bool bVerbose,
+ t_atoms* atoms,
+ PreprocessingAtomTypes* atypes,
+ gmx::ArrayRef<InteractionsOfType> plist,
+ const gmx::MDLogger& logger)
{
int ftype;
int nvsite, nrset;
{
if (bVerbose && bFirst)
{
- fprintf(stderr, "Calculating parameters for virtual sites\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Calculating parameters for virtual sites");
bFirst = FALSE;
}
break;
case F_VSITE4FD:
bERROR = calc_vsite4fd_param(¶m, allVsiteBondeds.bonds,
- allVsiteBondeds.angles);
+ allVsiteBondeds.angles, logger);
break;
case F_VSITE4FDN:
bERROR = calc_vsite4fdn_param(¶m, allVsiteBondeds.bonds,
- allVsiteBondeds.angles);
+ allVsiteBondeds.angles, logger);
break;
default:
gmx_fatal(FARGS,
return nvsite;
}
-void set_vsites_ptype(bool bVerbose, gmx_moltype_t* molt)
+void set_vsites_ptype(bool bVerbose, gmx_moltype_t* molt, const gmx::MDLogger& logger)
{
int ftype, i;
if (bVerbose)
{
- fprintf(stderr, "Setting particle type to V for virtual sites\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Setting particle type to V for virtual sites");
}
for (ftype = 0; ftype < F_NRE; ftype++)
{
if (debug && nrd)
{
- fprintf(stderr, "doing %d %s virtual sites\n", (nrd / (nra + 1)),
- interaction_function[ftype].longname);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("doing %d %s virtual sites", (nrd / (nra + 1)),
+ interaction_function[ftype].longname);
}
for (i = 0; (i < nrd);)
int interactionIndex_;
};
-static void check_vsite_constraints(gmx::ArrayRef<InteractionsOfType> plist, int cftype, const int vsite_type[])
+static void check_vsite_constraints(gmx::ArrayRef<InteractionsOfType> plist,
+ int cftype,
+ const int vsite_type[],
+ const gmx::MDLogger& logger)
{
int n = 0;
for (const auto& param : plist[cftype].interactionTypes)
int atom = atoms[k];
if (vsite_type[atom] != NOTSET)
{
- fprintf(stderr, "ERROR: Cannot have constraint (%d-%d) with virtual site (%d)\n",
- param.ai() + 1, param.aj() + 1, atom + 1);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "ERROR: Cannot have constraint (%d-%d) with virtual site (%d)",
+ param.ai() + 1, param.aj() + 1, atom + 1);
n++;
}
}
static void clean_vsite_bonds(gmx::ArrayRef<InteractionsOfType> plist,
gmx::ArrayRef<const VsiteAtomMapping> pindex,
int cftype,
- const int vsite_type[])
+ const int vsite_type[],
+ const gmx::MDLogger& logger)
{
int ftype, nOut;
int nconverted, nremoved;
if (nremoved)
{
- fprintf(stderr, "Removed %4d %15ss with virtual sites, %zu left\n", nremoved,
- interaction_function[cftype].longname, ps->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Removed %4d %15ss with virtual sites, %zu left", nremoved,
+ interaction_function[cftype].longname, ps->size());
}
if (nconverted)
{
- fprintf(stderr, "Converted %4d %15ss with virtual sites to connections, %zu left\n",
- nconverted, interaction_function[cftype].longname, ps->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Converted %4d %15ss with virtual sites to connections, %zu left",
+ nconverted, interaction_function[cftype].longname, ps->size());
}
if (nOut)
{
- fprintf(stderr,
- "Warning: removed %d %ss with vsite with %s construction\n"
- " This vsite construction does not guarantee constant "
- "bond-length\n"
- " If the constructions were generated by pdb2gmx ignore "
- "this warning\n",
- nOut, interaction_function[cftype].longname, interaction_function[F_VSITE3OUT].longname);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "Warning: removed %d %ss with vsite with %s construction\n"
+ " This vsite construction does not guarantee constant "
+ "bond-length\n"
+ " If the constructions were generated by pdb2gmx ignore "
+ "this warning",
+ nOut, interaction_function[cftype].longname,
+ interaction_function[F_VSITE3OUT].longname);
}
}
gmx::ArrayRef<VsiteAtomMapping> pindex,
int cftype,
const int vsite_type[],
- gmx::ArrayRef<const Atom2VsiteConnection> at2vc)
+ gmx::ArrayRef<const Atom2VsiteConnection> at2vc,
+ const gmx::MDLogger& logger)
{
int atom, at1, at2;
InteractionsOfType* ps;
if (oldSize != gmx::ssize(*ps))
{
- fprintf(stderr, "Removed %4zu %15ss with virtual sites, %zu left\n", oldSize - ps->size(),
- interaction_function[cftype].longname, ps->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Removed %4zu %15ss with virtual sites, %zu left",
+ oldSize - ps->size(), interaction_function[cftype].longname,
+ ps->size());
}
}
static void clean_vsite_dihs(gmx::ArrayRef<InteractionsOfType> plist,
gmx::ArrayRef<const VsiteAtomMapping> pindex,
int cftype,
- const int vsite_type[])
+ const int vsite_type[],
+ const gmx::MDLogger& logger)
{
InteractionsOfType* ps;
if (oldSize != gmx::ssize(*ps))
{
- fprintf(stderr, "Removed %4zu %15ss with virtual sites, %zu left\n", oldSize - ps->size(),
- interaction_function[cftype].longname, ps->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Removed %4zu %15ss with virtual sites, %zu left",
+ oldSize - ps->size(), interaction_function[cftype].longname,
+ ps->size());
}
}
// TODO use gmx::compat::optional for pindex.
-void clean_vsite_bondeds(gmx::ArrayRef<InteractionsOfType> plist, int natoms, bool bRmVSiteBds)
+void clean_vsite_bondeds(gmx::ArrayRef<InteractionsOfType> plist,
+ int natoms,
+ bool bRmVSiteBds,
+ const gmx::MDLogger& logger)
{
int nvsite, vsite;
int* vsite_type;
/* the rest only if we have virtual sites: */
if (nvsite)
{
- fprintf(stderr, "Cleaning up constraints %swith virtual sites\n",
- bRmVSiteBds ? "and constant bonded interactions " : "");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Cleaning up constraints %swith virtual sites",
+ bRmVSiteBds ? "and constant bonded interactions " : "");
/* Make a reverse list to avoid ninteractions^2 operations */
at2vc = make_at2vsitecon(natoms, plist);
{
if (interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT))
{
- clean_vsite_bonds(plist, pindex, ftype, vsite_type);
+ clean_vsite_bonds(plist, pindex, ftype, vsite_type, logger);
}
else if (interaction_function[ftype].flags & IF_ATYPE)
{
- clean_vsite_angles(plist, pindex, ftype, vsite_type, at2vc);
+ clean_vsite_angles(plist, pindex, ftype, vsite_type, at2vc, logger);
}
else if ((ftype == F_PDIHS) || (ftype == F_IDIHS))
{
- clean_vsite_dihs(plist, pindex, ftype, vsite_type);
+ clean_vsite_dihs(plist, pindex, ftype, vsite_type, logger);
}
}
}
{
if (interaction_function[ftype].flags & IF_CONSTRAINT)
{
- check_vsite_constraints(plist, ftype, vsite_type);
+ check_vsite_constraints(plist, ftype, vsite_type, logger);
}
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_atoms;
struct InteractionsOfType;
+namespace gmx
+{
+class MDLogger;
+}
+
int set_vsites(bool bVerbose,
t_atoms* atoms,
PreprocessingAtomTypes* atype,
- gmx::ArrayRef<InteractionsOfType> plist);
+ gmx::ArrayRef<InteractionsOfType> plist,
+ const gmx::MDLogger& logger);
/* set parameters for virtual sites, return number of virtual sites */
-void set_vsites_ptype(bool bVerbose, gmx_moltype_t* molt);
+void set_vsites_ptype(bool bVerbose, gmx_moltype_t* molt, const gmx::MDLogger& logger);
/* set ptype to VSite for virtual sites */
/*! \brief Clean up the bonded interactions
*
* Throw away all obsolete bonds, angles and dihedrals.
* Throw away all constraints. */
-void clean_vsite_bondeds(gmx::ArrayRef<InteractionsOfType> ps, int natoms, bool bRmVSiteBds);
+void clean_vsite_bondeds(gmx::ArrayRef<InteractionsOfType> ps,
+ int natoms,
+ bool bRmVSiteBds,
+ const gmx::MDLogger& logger);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arraysize.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/filestream.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/logger.h"
+#include "gromacs/utility/loggerbuilder.h"
#include "gromacs/utility/smalloc.h"
#include "hackblock.h"
std::array<real, MAXFORCEPARAM> forceParam = { 0.0 };
if (bPBC)
{
- set_pbc(&pbc, -1, box);
+ set_pbc(&pbc, PbcType::Unset, box);
}
for (i = 0; (i < atoms->nr); i++)
{
- if ((i % 10) == 0)
- {
- fprintf(stderr, "\ratom %d", i);
- fflush(stderr);
- }
for (j = i + 1; (j < atoms->nr); j++)
{
if (bPBC)
}
}
}
- fprintf(stderr, "\ratom %d\n", i);
- fflush(stderr);
}
static int* set_cgnr(t_atoms* atoms, bool bUsePDBcharge, real* qtot, real* mtot)
InteractionsOfType* bonds,
int* nbonds,
int nnm,
- t_nm2type nm2t[])
+ t_nm2type nm2t[],
+ const gmx::MDLogger& logger)
{
int nresolved;
gmx_fatal(FARGS, "Could only find a forcefield type for %d out of %d atoms", nresolved, atoms->nr);
}
- fprintf(stderr, "There are %zu different atom types in your sample\n", atypes->size());
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("There are %zu different atom types in your sample", atypes->size());
}
static void lo_set_force_const(InteractionsOfType* plist, real c[], int nrfp, bool bRound, bool bDih, bool bParam)
if (bPBC)
{
- set_pbc(&pbc, epbcXYZ, box);
+ set_pbc(&pbc, PbcType::Xyz, box);
}
for (auto& angle : ang->interactionTypes)
{
int bts[] = { 1, 1, 1, 2 };
matrix box; /* box length matrix */
int natoms; /* number of atoms in one molecule */
- int epbc;
+ PbcType pbcType;
bool bRTP, bTOP, bOPLS;
t_symtab symtab;
real qtot, mtot;
gmx_fatal(FARGS, "Specify at least one output file");
}
+ gmx::LoggerBuilder builder;
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Info, &gmx::TextOutputFile::standardOutput());
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Warning, &gmx::TextOutputFile::standardError());
+ gmx::LoggerOwner logOwner(builder.build());
+ gmx::MDLogger logger(logOwner.logger());
+
+
/* Force field selection, interactive or direct */
choose_ff(strcmp(ff, "select") == 0 ? nullptr : ff, forcefield, sizeof(forcefield), ffdir,
- sizeof(ffdir));
+ sizeof(ffdir), logger);
bOPLS = (strcmp(forcefield, "oplsaa") == 0);
/* Read coordinates */
t_topology* top;
snew(top, 1);
- read_tps_conf(opt2fn("-f", NFILE, fnm), top, &epbc, &x, nullptr, box, FALSE);
+ read_tps_conf(opt2fn("-f", NFILE, fnm), top, &pbcType, &x, nullptr, box, FALSE);
t_atoms* atoms = &top->atoms;
natoms = atoms->nr;
if (atoms->pdbinfo == nullptr)
}
else
{
- printf("There are %d name to type translations in file %s\n", nnm, n2t);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("There are %d name to type translations in file %s", nnm, n2t);
}
if (debug)
{
dump_nm2type(debug, nnm, nm2t);
}
- printf("Generating bonds from distances...\n");
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Generating bonds from distances...");
snew(nbonds, atoms->nr);
mk_bonds(nnm, nm2t, atoms, x, &(plist[F_BONDS]), nbonds, bPBC, box);
open_symtab(&symtab);
PreprocessingAtomTypes atypes;
- set_atom_type(&atypes, &symtab, atoms, &(plist[F_BONDS]), nbonds, nnm, nm2t);
+ set_atom_type(&atypes, &symtab, atoms, &(plist[F_BONDS]), nbonds, nnm, nm2t, logger);
/* Make Angles and Dihedrals */
snew(excls, atoms->nr);
- printf("Generating angles and dihedrals from bonds...\n");
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted("Generating angles and dihedrals from bonds...");
gen_pad(atoms, gmx::arrayRefFromArray(&rtp_header_settings, 1), plist, excls, {}, TRUE);
if (!bPairs)
{
plist[F_LJ14].interactionTypes.clear();
}
- fprintf(stderr,
- "There are %4zu %s dihedrals, %4zu impropers, %4zu angles\n"
- " %4zu pairs, %4zu bonds and %4d atoms\n",
- plist[F_PDIHS].size(), bOPLS ? "Ryckaert-Bellemans" : "proper", plist[F_IDIHS].size(),
- plist[F_ANGLES].size(), plist[F_LJ14].size(), plist[F_BONDS].size(), atoms->nr);
+ GMX_LOG(logger.info)
+ .asParagraph()
+ .appendTextFormatted(
+ "There are %4zu %s dihedrals, %4zu impropers, %4zu angles\n"
+ " %4zu pairs, %4zu bonds and %4d atoms\n",
+ plist[F_PDIHS].size(), bOPLS ? "Ryckaert-Bellemans" : "proper", plist[F_IDIHS].size(),
+ plist[F_ANGLES].size(), plist[F_LJ14].size(), plist[F_BONDS].size(), atoms->nr);
calc_angles_dihs(&plist[F_ANGLES], &plist[F_PDIHS], x, bPBC, box);
set_force_const(plist, kb, kt, kp, bRound, bParam);
cgnr = set_cgnr(atoms, bUsePDBcharge, &qtot, &mtot);
- printf("Total charge is %g, total mass is %g\n", qtot, mtot);
+ GMX_LOG(logger.info).asParagraph().appendTextFormatted("Total charge is %g, total mass is %g", qtot, mtot);
if (bOPLS)
{
bts[2] = 3;
}
close_symtab(&symtab);
- printf("\nWARNING: topologies generated by %s can not be trusted at face value.\n",
- output_env_get_program_display_name(oenv));
- printf(" Please verify atomtypes and charges by comparison to other\n");
- printf(" topologies.\n");
+ GMX_LOG(logger.warning)
+ .asParagraph()
+ .appendTextFormatted(
+ "Topologies generated by %s can not be trusted at face value. "
+ "Please verify atomtypes and charges by comparison to other topologies.",
+ output_env_get_program_display_name(oenv));
return 0;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
gmx_add_libgromacs_sources(
clfftinitializer.cpp
+ device_stream_manager.cpp
hostallocator.cpp
gpu_utils.cpp
gpu_testutils.cpp
)
if(GMX_USE_OPENCL)
gmx_add_libgromacs_sources(
+ device_context_ocl.cpp
+ device_stream_ocl.cpp
gpu_utils_ocl.cpp
ocl_compiler.cpp
ocl_caching.cpp
)
elseif(GMX_USE_CUDA)
gmx_add_libgromacs_sources(
- cudautils.cu
+ device_stream.cu
gpu_utils.cu
pinning.cu
pmalloc_cuda.cu
)
+ gmx_compile_cpp_as_cuda(
+ device_stream_manager.cpp
+ )
+else()
+ gmx_add_libgromacs_sources(
+ device_stream.cpp
+ )
endif()
if (BUILD_TESTING)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \todo Consider making a composite object that also handles
* on-demand compilation, managing lifetime of PME FFT kernel programs
* to avoid exhausting resources and/or recompiling kernels previously
- * used. See Redmine #2535.
+ * used. See Issue #2535.
*
* \todo Consider implementing an appropriate flavor of the nifty
* counter idiom so that both static initialization and
* deinitialization can work in a fast, leak-free, and thread-safe way
* without imposing constraints on the calling code.
- * See Redmine #2535. */
+ * See Issue #2535. */
class ClfftInitializer
{
public:
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
return cu_copy_H2D(d_dest, h_src, bytes, GpuApiCallBehavior::Async, s);
}
-
-/*! \brief Set up texture object for an array of type T.
- *
- * Set up texture object for an array of type T and bind it to the device memory
- * \p d_ptr points to.
- *
- * \tparam[in] T Raw data type
- * \param[out] texObj texture object to initialize
- * \param[in] d_ptr pointer to device global memory to bind \p texObj to
- * \param[in] sizeInBytes size of memory area to bind \p texObj to
- */
-template<typename T>
-static void setup1DTexture(cudaTextureObject_t& texObj, void* d_ptr, size_t sizeInBytes)
-{
- assert(!c_disableCudaTextures);
-
- cudaError_t stat;
- cudaResourceDesc rd;
- cudaTextureDesc td;
-
- memset(&rd, 0, sizeof(rd));
- rd.resType = cudaResourceTypeLinear;
- rd.res.linear.devPtr = d_ptr;
- rd.res.linear.desc = cudaCreateChannelDesc<T>();
- rd.res.linear.sizeInBytes = sizeInBytes;
-
- memset(&td, 0, sizeof(td));
- td.readMode = cudaReadModeElementType;
- stat = cudaCreateTextureObject(&texObj, &rd, &td, nullptr);
- CU_RET_ERR(stat, "cudaCreateTextureObject failed");
-}
-
-template<typename T>
-void initParamLookupTable(T*& d_ptr, cudaTextureObject_t& texObj, const T* h_ptr, int numElem)
-{
- const size_t sizeInBytes = numElem * sizeof(*d_ptr);
- cudaError_t stat = cudaMalloc((void**)&d_ptr, sizeInBytes);
- CU_RET_ERR(stat, "cudaMalloc failed in initParamLookupTable");
- cu_copy_H2D_sync(d_ptr, (void*)h_ptr, sizeInBytes);
-
- if (!c_disableCudaTextures)
- {
- setup1DTexture<T>(texObj, d_ptr, sizeInBytes);
- }
-}
-
-template<typename T>
-void destroyParamLookupTable(T* d_ptr, cudaTextureObject_t texObj)
-{
- if (!c_disableCudaTextures && texObj)
- {
- CU_RET_ERR(cudaDestroyTextureObject(texObj), "cudaDestroyTextureObject on texObj failed");
- }
- CU_RET_ERR(cudaFree(d_ptr), "cudaFree failed");
-}
-
-/*! \brief Add explicit instantiations of init/destroyParamLookupTable() here as needed.
- * One should also verify that the result of cudaCreateChannelDesc<T>() during texture setup
- * looks reasonable, when instantiating the templates for new types - just in case.
- */
-template void initParamLookupTable<float>(float*&, cudaTextureObject_t&, const float*, int);
-template void destroyParamLookupTable<float>(float*, cudaTextureObject_t);
-template void initParamLookupTable<int>(int*&, cudaTextureObject_t&, const int*, int);
-template void destroyParamLookupTable<int>(int*, cudaTextureObject_t);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif /* CHECK_CUDA_ERRORS */
-/*! \brief CUDA device information.
- *
- * The CUDA device information is queried and set at detection and contains
- * both information about the device/hardware returned by the runtime as well
- * as additional data like support status.
- */
-struct gmx_device_info_t
-{
- int id; /* id of the CUDA device */
- cudaDeviceProp prop; /* CUDA device properties */
- int stat; /* result of the device check */
-};
-
-/*! Launches synchronous or asynchronous device to host memory copy.
- *
- * The copy is launched in stream s or if not specified, in stream 0.
- */
-int cu_copy_D2H(void* h_dest, void* d_src, size_t bytes, GpuApiCallBehavior transferKind, cudaStream_t /*s = nullptr*/);
-
-/*! Launches synchronous host to device memory copy in stream 0. */
-int cu_copy_D2H_sync(void* /*h_dest*/, void* /*d_src*/, size_t /*bytes*/);
-
-/*! Launches asynchronous host to device memory copy in stream s. */
-int cu_copy_D2H_async(void* /*h_dest*/, void* /*d_src*/, size_t /*bytes*/, cudaStream_t /*s = nullptr*/);
-
-/*! Launches synchronous or asynchronous host to device memory copy.
- *
- * The copy is launched in stream s or if not specified, in stream 0.
- */
-int cu_copy_H2D(void* d_dest, const void* h_src, size_t bytes, GpuApiCallBehavior transferKind, cudaStream_t /*s = nullptr*/);
-
-/*! Launches synchronous host to device memory copy. */
-int cu_copy_H2D_sync(void* /*d_dest*/, const void* /*h_src*/, size_t /*bytes*/);
-
-/*! Launches asynchronous host to device memory copy in stream s. */
-int cu_copy_H2D_async(void* /*d_dest*/, const void* /*h_src*/, size_t /*bytes*/, cudaStream_t /*s = nullptr*/);
-
// TODO: the 2 functions below are pretty much a constructor/destructor of a simple
// GPU table object. There is also almost self-contained fetchFromParamLookupTable()
// in cuda_kernel_utils.cuh. They could all live in a separate class/struct file.
-/*! \brief Initialize parameter lookup table.
- *
- * Initializes device memory, copies data from host and binds
- * a texture to allocated device memory to be used for parameter lookup.
- *
- * \tparam[in] T Raw data type
- * \param[out] d_ptr device pointer to the memory to be allocated
- * \param[out] texObj texture object to be initialized
- * \param[in] h_ptr pointer to the host memory to be uploaded to the device
- * \param[in] numElem number of elements in the h_ptr
- */
-template<typename T>
-void initParamLookupTable(T*& d_ptr, cudaTextureObject_t& texObj, const T* h_ptr, int numElem);
-
-// Add extern declarations so each translation unit understands that
-// there will be a definition provided.
-extern template void initParamLookupTable<int>(int*&, cudaTextureObject_t&, const int*, int);
-extern template void initParamLookupTable<float>(float*&, cudaTextureObject_t&, const float*, int);
-
-/*! \brief Destroy parameter lookup table.
- *
- * Unbinds texture object, deallocates device memory.
- *
- * \tparam[in] T Raw data type
- * \param[in] d_ptr Device pointer to the memory to be deallocated
- * \param[in] texObj Texture object to be deinitialized
- */
-template<typename T>
-void destroyParamLookupTable(T* d_ptr, cudaTextureObject_t texObj);
-
-// Add extern declarations so each translation unit understands that
-// there will be a definition provided.
-extern template void destroyParamLookupTable<int>(int*, cudaTextureObject_t);
-extern template void destroyParamLookupTable<float>(float*, cudaTextureObject_t);
-
/*! \brief Add a triplets stored in a float3 to an rvec variable.
*
* \param[out] a Rvec to increment
rvec_inc(a, tmp);
}
-/*! \brief Wait for all taks in stream \p s to complete.
- *
- * \param[in] s stream to synchronize with
- */
-static inline void gpuStreamSynchronize(cudaStream_t s)
-{
- cudaError_t stat = cudaStreamSynchronize(s);
- CU_RET_ERR(stat, "cudaStreamSynchronize failed");
-}
-
/*! \brief Returns true if all tasks in \p s have completed.
*
- * \param[in] s stream to check
+ * \param[in] deviceStream CUDA stream to check.
*
- * \returns True if all tasks enqueued in the stream \p s (at the time of this call) have completed.
+ * \returns True if all tasks enqueued in the stream \p deviceStream (at the time of this call) have completed.
*/
-static inline bool haveStreamTasksCompleted(cudaStream_t s)
+static inline bool haveStreamTasksCompleted(const DeviceStream& deviceStream)
{
- cudaError_t stat = cudaStreamQuery(s);
+ cudaError_t stat = cudaStreamQuery(deviceStream.stream());
if (stat == cudaErrorNotReady)
{
* \tparam Args Types of all the kernel arguments
* \param[in] kernel Kernel function handle
* \param[in] config Kernel configuration for launching
+ * \param[in] deviceStream GPU stream to launch kernel in
* \param[in] kernelName Human readable kernel description, for error handling only
* \param[in] kernelArgs Array of the pointers to the kernel arguments, prepared by
* prepareGpuKernelArguments() \throws gmx::InternalError on kernel launch failure
template<typename... Args>
void launchGpuKernel(void (*kernel)(Args...),
const KernelLaunchConfig& config,
+ const DeviceStream& deviceStream,
CommandEvent* /*timingEvent */,
const char* kernelName,
const std::array<void*, sizeof...(Args)>& kernelArgs)
dim3 blockSize(config.blockSize[0], config.blockSize[1], config.blockSize[2]);
dim3 gridSize(config.gridSize[0], config.gridSize[1], config.gridSize[2]);
cudaLaunchKernel((void*)kernel, gridSize, blockSize, const_cast<void**>(kernelArgs.data()),
- config.sharedMemorySize, config.stream);
+ config.sharedMemorySize, deviceStream.stream());
cudaError_t status = cudaGetLastError();
if (cudaSuccess != status)
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_GPU_UTILS_DEVICE_CONTEXT_H
+#define GMX_GPU_UTILS_DEVICE_CONTEXT_H
+
+/*! \libinternal \file
+ *
+ * \brief Declarations for DeviceContext class.
+ *
+ * Only needed for OpenCL builds. Other platforms will be given a stub class.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ * \inlibraryapi
+ */
+
+#include "config.h"
+
+#if GMX_GPU == GMX_GPU_OPENCL
+# include "gromacs/gpu_utils/device_context_ocl.h"
+#else
+# include "gromacs/utility/classhelpers.h"
+
+struct DeviceInformation;
+
+// Stub for device context
+class DeviceContext
+{
+public:
+ //! Constructor.
+ DeviceContext(const DeviceInformation& deviceInfo) : deviceInfo_(deviceInfo) {}
+ //! Destructor
+ ~DeviceContext() = default;
+
+ //! Get the associated device information
+ const DeviceInformation& deviceInfo() const { return deviceInfo_; }
+
+private:
+ //! A reference to the device information used upon context creation
+ const DeviceInformation& deviceInfo_;
+
+ GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(DeviceContext);
+};
+#endif // GMX_GPU != GMX_GPU_OPENCL
+
+#endif // GMX_GPU_UTILS_DEVICE_CONTEXT_H
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ *
+ * \brief Implements the DeviceContext for OpenCL
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ */
+#include "gmxpre.h"
+
+#include "device_context_ocl.h"
+
+#include "gromacs/gpu_utils/gputraits.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+
+/*! \brief Copies of values from cl_driver_diagnostics_intel.h,
+ * which isn't guaranteed to be available. */
+/**@{*/
+#define CL_CONTEXT_SHOW_DIAGNOSTICS_INTEL 0x4106
+#define CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL 0x1
+#define CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL 0x2
+#define CL_CONTEXT_DIAGNOSTICS_LEVEL_NEUTRAL_INTEL 0x4
+/**@}*/
+
+DeviceContext::DeviceContext(const DeviceInformation& deviceInfo) : deviceInfo_(deviceInfo)
+{
+ cl_platform_id platformId = deviceInfo.oclPlatformId;
+ cl_device_id deviceId = deviceInfo.oclDeviceId;
+ std::vector<cl_context_properties> contextProperties;
+
+ contextProperties.emplace_back(CL_CONTEXT_PLATFORM);
+ contextProperties.emplace_back(reinterpret_cast<cl_context_properties>(platformId));
+
+ if (getenv("GMX_OCL_SHOW_DIAGNOSTICS"))
+ {
+ contextProperties.emplace_back(CL_CONTEXT_SHOW_DIAGNOSTICS_INTEL);
+ contextProperties.emplace_back(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL
+ | CL_CONTEXT_DIAGNOSTICS_LEVEL_NEUTRAL_INTEL);
+ }
+ contextProperties.emplace_back(0);
+
+ cl_int clError;
+ context_ = clCreateContext(contextProperties.data(), 1, &deviceId, nullptr, nullptr, &clError);
+ if (clError != CL_SUCCESS)
+ {
+ GMX_THROW(gmx::InternalError(gmx::formatString(
+ "Failed to create OpenCL context on device %s (OpenCL error ID %d).",
+ deviceInfo.device_name, clError)));
+ }
+}
+
+DeviceContext::~DeviceContext()
+{
+ cl_int clError;
+
+ if (context_)
+ {
+ clError = clReleaseContext(context_);
+ GMX_RELEASE_ASSERT(
+ clError == CL_SUCCESS,
+ gmx::formatString("Failed to release OpenCL context (OpenCL error ID %d).", clError).c_str());
+ context_ = nullptr;
+ }
+}
+
+cl_context DeviceContext::context() const
+{
+ return context_;
+}
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_GPU_UTILS_DEVICE_CONTEXT_OCL_H
+#define GMX_GPU_UTILS_DEVICE_CONTEXT_OCL_H
+
+/*! \libinternal \file
+ *
+ * \brief Declarations for DeviceContext class.
+ *
+ * Only needed for OpenCL builds. Other platforms will be given a stub class.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ * \inlibraryapi
+ */
+
+#include "gromacs/gpu_utils/gmxopencl.h"
+#include "gromacs/utility/classhelpers.h"
+
+struct DeviceInformation;
+
+// OpenCL device context class
+class DeviceContext
+{
+public:
+ /*! \brief Constructor that creates the \c cl_context
+ *
+ * \param[in] deviceInfo Platform-specific device information.
+ *
+ * \throws InternalError if context creation failed.
+ */
+ DeviceContext(const DeviceInformation& deviceInfo);
+ //! Destructor
+ ~DeviceContext();
+
+ //! Get the associated device information
+ const DeviceInformation& deviceInfo() const { return deviceInfo_; }
+ //! Getter
+ cl_context context() const;
+
+private:
+ //! A reference to the device information used upon context creation
+ const DeviceInformation& deviceInfo_;
+ //! OpenCL context object
+ cl_context context_ = nullptr;
+
+ GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(DeviceContext);
+};
+
+#endif // GMX_GPU_UTILS_DEVICE_CONTEXT_OCL_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#ifndef GMX_MDLIB_QMGAMESS_H
-#define GMX_MDLIB_QMGAMESS_H
-
-#include "gromacs/mdlib/qmmm.h"
-
-/*! \brief
- * Initialize gamess datastructures.
+/*! \internal \file
*
- * \param[in] cr Commrec datastructure.
- * \param[in] qm QM forcerec.
- * \param[in] mm MM part of forcerec.
- */
-void init_gamess(const t_commrec* cr, t_QMrec* qm, t_MMrec* mm);
-
-/*! \brief
- * Run calculation with Gamess.
+ * \brief Implements the DeviceStream for CPU builds.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
*
- * \param[in] qm QM part of forcerec.
- * \param[in] mm MM part of forcerec.
- * \param[in] f Force vector.
- * \param[in] fshift Force shift vector.
+ * \ingroup module_gpu_utils
*/
-real call_gamess(const t_QMrec* qm, const t_MMrec* mm, rvec f[], rvec fshift[]);
+#include "gmxpre.h"
+
+#include "device_stream.h"
+
+DeviceStream::DeviceStream() = default;
+
+void DeviceStream::init(const DeviceContext& /* deviceContext */,
+ DeviceStreamPriority /* priority */,
+ const bool /* useTiming */)
+{
+}
+
+DeviceStream::~DeviceStream() = default;
+// NOLINTNEXTLINE readability-convert-member-functions-to-static
+bool DeviceStream::isValid() const
+{
+ return false;
+}
-#endif
+void DeviceStream::synchronize() const {};
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ *
+ * \brief Implements the DeviceStream for CUDA.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ */
+#include "gmxpre.h"
+
+#include "device_stream.h"
+
+#include "gromacs/gpu_utils/gputraits.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+
+DeviceStream::DeviceStream()
+{
+ stream_ = nullptr;
+}
+
+void DeviceStream::init(const DeviceContext& /* deviceContext */,
+ DeviceStreamPriority priority,
+ const bool /* useTiming */)
+{
+ cudaError_t stat;
+
+ if (priority == DeviceStreamPriority::Normal)
+ {
+ stat = cudaStreamCreate(&stream_);
+ if (stat != cudaSuccess)
+ {
+ GMX_THROW(gmx::InternalError(gmx::formatString(
+ "Could not create CUDA stream (CUDA error %d: %s).", stat, cudaGetErrorString(stat))));
+ }
+ }
+ else if (priority == DeviceStreamPriority::High)
+ {
+ // Note that the device we're running on does not have to
+ // support priorities, because we are querying the priority
+ // range, which in that case will be a single value.
+ int highestPriority;
+ stat = cudaDeviceGetStreamPriorityRange(nullptr, &highestPriority);
+ if (stat != cudaSuccess)
+ {
+ GMX_THROW(gmx::InternalError(gmx::formatString(
+ "Could not query CUDA stream priority range (CUDA error %d: %s).", stat,
+ cudaGetErrorString(stat))));
+ }
+
+ stat = cudaStreamCreateWithPriority(&stream_, cudaStreamDefault, highestPriority);
+ if (stat != cudaSuccess)
+ {
+ GMX_THROW(gmx::InternalError(gmx::formatString(
+ "Could not create CUDA stream with high priority (CUDA error %d: %s).", stat,
+ cudaGetErrorString(stat))));
+ }
+ }
+}
+
+DeviceStream::~DeviceStream()
+{
+ if (isValid())
+ {
+ cudaError_t stat = cudaStreamDestroy(stream_);
+ GMX_RELEASE_ASSERT(stat == cudaSuccess,
+ gmx::formatString("Failed to release CUDA stream (CUDA error %d: %s).",
+ stat, cudaGetErrorString(stat))
+ .c_str());
+ stream_ = nullptr;
+ }
+}
+
+cudaStream_t DeviceStream::stream() const
+{
+ return stream_;
+}
+
+bool DeviceStream::isValid() const
+{
+ return (stream_ != nullptr);
+}
+
+void DeviceStream::synchronize() const
+{
+ cudaError_t stat = cudaStreamSynchronize(stream_);
+ GMX_RELEASE_ASSERT(stat == cudaSuccess,
+ gmx::formatString("cudaStreamSynchronize failed (CUDA error %d: %s).", stat,
+ cudaGetErrorString(stat))
+ .c_str());
+}
\ No newline at end of file
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_GPU_UTILS_DEVICE_STREAM_H
+#define GMX_GPU_UTILS_DEVICE_STREAM_H
+
+/*! \libinternal \file
+ *
+ * \brief Declarations for DeviceStream class.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ * \inlibraryapi
+ */
+
+#include "config.h"
+
+#if GMX_GPU == GMX_GPU_OPENCL
+# include "gromacs/gpu_utils/gmxopencl.h"
+#endif
+#include "gromacs/utility/classhelpers.h"
+
+struct DeviceInformation;
+class DeviceContext;
+
+//! Enumeration describing the priority with which a stream operates.
+enum class DeviceStreamPriority : int
+{
+ //! High-priority stream
+ High,
+ //! Normal-priority stream
+ Normal,
+ //! Conventional termination of the enumeration
+ Count
+};
+
+/*! \libinternal \brief Declaration of platform-agnostic device stream/queue.
+ *
+ * The command stream (or command queue) is a sequence of operations that are executed
+ * in they order they were issued. Several streams may co-exist to represent concurency.
+ * This class declares the interfaces, that are exposed to platform-agnostic code and
+ * it should be implemented for each compute architecture (e.g. CUDA and OpenCL).
+ *
+ * Destruction of the \p DeviceStream calls the destructor of the underlying low-level
+ * stream/queue, hence should only be called when the stream is no longer needed. To
+ * prevent accidental stream destruction, while copying or moving a \p DeviceStream
+ * object, copy and move constructors and copy and move assignments are not allowed
+ * and the \p DeviceStream object should be passed as a pointer or constant reference.
+ *
+ */
+class DeviceStream
+{
+public:
+ //! Default constructor
+ DeviceStream();
+ //! Destructor
+ ~DeviceStream();
+
+ /*! \brief Initialize
+ *
+ * \param[in] deviceContext Device context (not used in CUDA).
+ * \param[in] priority Stream priority: high or normal.
+ * \param[in] useTiming If the timing should be enabled (not used in CUDA).
+ */
+ void init(const DeviceContext& deviceContext, DeviceStreamPriority priority, bool useTiming);
+
+ /*! \brief Construct and init.
+ *
+ * \param[in] deviceContext Device context (only used in OpenCL).
+ * \param[in] priority Stream priority: high or normal (only used in CUDA).
+ * \param[in] useTiming If the timing should be enabled (only used in OpenCL).
+ */
+ DeviceStream(const DeviceContext& deviceContext, DeviceStreamPriority priority, const bool useTiming)
+ {
+ init(deviceContext, priority, useTiming);
+ }
+
+ /*! \brief Check if the underlying stream is valid.
+ *
+ * \returns Whether the stream is valid (false in CPU-only builds).
+ */
+ bool isValid() const;
+
+ //! Synchronize the steam
+ void synchronize() const;
+
+#if GMX_GPU == GMX_GPU_CUDA
+
+ //! Getter
+ cudaStream_t stream() const;
+ //! Setter (temporary, will be removed in the follow-up)
+ void setStream(cudaStream_t stream) { stream_ = stream; }
+
+private:
+ cudaStream_t stream_ = nullptr;
+
+#elif GMX_GPU == GMX_GPU_OPENCL
+
+ //! Getter
+ cl_command_queue stream() const;
+ //! Setter (temporary, will be removed in the follow-up)
+ void setStream(cl_command_queue stream) { stream_ = stream; }
+
+private:
+ cl_command_queue stream_ = nullptr;
+
+#endif
+
+ GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(DeviceStream);
+};
+
+#endif // GMX_GPU_UTILS_DEVICE_STREAM_H
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ *
+ * \brief Implements GPU stream manager.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ */
+#include "gmxpre.h"
+
+#include "device_stream_manager.h"
+
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
+#include "gromacs/gpu_utils/gputraits.h"
+#include "gromacs/utility/enumerationhelpers.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+
+namespace gmx
+{
+
+/*! \libinternal
+ * \brief Impl class to manages the lifetime of the GPU streams.
+ *
+ * If supported by the GPU API, the available runtime and the
+ * indicated device, some streams will be configured at high
+ * priority. Otherwise, all streams will share the default priority
+ * appropriate to the situation.
+ */
+class DeviceStreamManager::Impl
+{
+public:
+ /*! \brief Constructor.
+ *
+ * \throws InternalError If any of the required resources could not be initialized.
+ */
+ Impl(const DeviceInformation& deviceInfo,
+ bool useGpuForPme,
+ bool havePpDomainDecomposition,
+ bool doGpuPmePpTransfer,
+ bool useGpuForUpdate,
+ bool useTiming);
+ ~Impl();
+
+ //! Device context.
+ DeviceContext context_;
+ //! GPU command streams.
+ EnumerationArray<DeviceStreamType, DeviceStream> streams_;
+};
+
+// DeviceStreamManager::Impl
+DeviceStreamManager::Impl::Impl(const DeviceInformation& deviceInfo,
+ const bool useGpuForPme,
+ const bool havePpDomainDecomposition,
+ const bool doGpuPmePpTransfer,
+ const bool useGpuForUpdate,
+ const bool useTiming) :
+ context_(deviceInfo)
+{
+ try
+ {
+ streams_[DeviceStreamType::NonBondedLocal].init(context_, DeviceStreamPriority::Normal, useTiming);
+
+ if (useGpuForPme)
+ {
+ /* Creating a PME GPU stream:
+ * - default high priority with CUDA
+ * - no priorities implemented yet with OpenCL; see #2532
+ */
+ streams_[DeviceStreamType::Pme].init(context_, DeviceStreamPriority::High, useTiming);
+ }
+
+ if (havePpDomainDecomposition)
+ {
+ streams_[DeviceStreamType::NonBondedNonLocal].init(context_, DeviceStreamPriority::High,
+ useTiming);
+ }
+ // Update stream is used both for coordinates transfers and for GPU update/constraints
+ if (useGpuForPme || useGpuForUpdate)
+ {
+ streams_[DeviceStreamType::UpdateAndConstraints].init(
+ context_, DeviceStreamPriority::Normal, useTiming);
+ }
+ if (doGpuPmePpTransfer)
+ {
+ streams_[DeviceStreamType::PmePpTransfer].init(context_, DeviceStreamPriority::Normal, useTiming);
+ }
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+}
+
+DeviceStreamManager::Impl::~Impl() = default;
+
+// DeviceStreamManager
+DeviceStreamManager::DeviceStreamManager(const DeviceInformation& deviceInfo,
+ const bool useGpuForPme,
+ const bool havePpDomainDecomposition,
+ const bool doGpuPmePpTransfer,
+ const bool useGpuForUpdate,
+ const bool useTiming) :
+ impl_(new Impl(deviceInfo, useGpuForPme, havePpDomainDecomposition, doGpuPmePpTransfer, useGpuForUpdate, useTiming))
+{
+}
+
+DeviceStreamManager::~DeviceStreamManager() = default;
+
+const DeviceInformation& DeviceStreamManager::deviceInfo() const
+{
+ return impl_->context_.deviceInfo();
+}
+
+const DeviceContext& DeviceStreamManager::context() const
+{
+ return impl_->context_;
+}
+
+const DeviceStream& DeviceStreamManager::stream(DeviceStreamType streamToGet) const
+{
+ return impl_->streams_[streamToGet];
+}
+
+const DeviceStream& DeviceStreamManager::bondedStream(bool hasPPDomainDecomposition) const
+{
+ if (hasPPDomainDecomposition)
+ {
+ GMX_RELEASE_ASSERT(stream(DeviceStreamType::NonBondedNonLocal).isValid(),
+ "GPU non-bonded non-local stream should be valid in order to use GPU "
+ "version of bonded forces with domain decomposition.");
+ return stream(DeviceStreamType::NonBondedNonLocal);
+ }
+ else
+ {
+ GMX_RELEASE_ASSERT(stream(DeviceStreamType::NonBondedLocal).isValid(),
+ "GPU non-bonded local stream should be valid in order to use GPU "
+ "version of bonded forces without domain decomposition.");
+ return stream(DeviceStreamType::NonBondedLocal);
+ }
+}
+
+bool DeviceStreamManager::streamIsValid(DeviceStreamType streamToCheck) const
+{
+ return impl_->streams_[streamToCheck].isValid();
+}
+
+} // namespace gmx
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ *
+ * \brief This file declares a manager of GPU context and streams needed for
+ * running workloads on GPUs.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \inlibraryapi
+ * \ingroup module_gpu_utils
+ */
+#ifndef GMX_GPU_UTILS_GPUSTREAMMANAGER_H
+#define GMX_GPU_UTILS_GPUSTREAMMANAGER_H
+
+#include <string>
+
+#include "gromacs/utility/classhelpers.h"
+
+class DeviceContext;
+struct DeviceInformation;
+class DeviceStream;
+
+namespace gmx
+{
+
+/*! \brief Class enum to describe the different logical streams used
+ * for GPU work.
+ *
+ * Whether the actual streams differ is an implementation detail of
+ * the manager class.
+ */
+enum class DeviceStreamType : int
+{
+ //! Stream primarily for short-ranged local nonbonded work.
+ NonBondedLocal,
+ //! Stream primarily for short-ranged nonlocal nonbonded work.
+ NonBondedNonLocal,
+ //! Stream primarily for PME work.
+ Pme,
+ //! Stream primarily for data exchange between PME and PP ranks.
+ PmePpTransfer,
+ //! Stream primarily for update and constraints.
+ UpdateAndConstraints,
+ //! Conventional termination of the enumeration.
+ Count
+};
+
+/*! \libinternal
+ * \brief Device stream and context manager.
+ *
+ * Manages the lifetime of the GPU streams and their association
+ * with context and device information that is needed to use them.
+ *
+ * If supported by the GPU API, the available runtime and the
+ * indicated device, some streams will be configured at high
+ * priority. Otherwise, all streams will share the default priority
+ * appropriate to the situation.
+ */
+class DeviceStreamManager
+{
+public:
+ /*! \brief Constructor.
+ *
+ * \throws InternalError If any of the required resources could not be initialized.
+ */
+ DeviceStreamManager(const DeviceInformation& deviceInfo,
+ bool useGpuForPme,
+ bool havePpDomainDecomposition,
+ bool doGpuPmePpTransfer,
+ bool useGpuForUpdate,
+ bool useTiming);
+ ~DeviceStreamManager();
+
+ /*! \brief Get the device information object of the associated device.
+ *
+ * \returns reference to device info.
+ */
+ const DeviceInformation& deviceInfo() const;
+
+ /*! \brief Returns a handle to the GPU context.
+ *
+ * \todo This relies on the fact that only one unique device
+ * is described by nonbondedDeviceInfo and pmeDeviceInfo.
+ */
+ const DeviceContext& context() const;
+
+ /*! \brief Returns a handle to the requested GPU stream.
+ *
+ * \param[in] streamToGet Which stream to get.
+ */
+ const DeviceStream& stream(DeviceStreamType streamToGet) const;
+
+ /*! \brief Returns a handle to the GPU stream to compute bonded forces in.
+ *
+ * \param[in] hasPPDomainDecomposition Whether there is a particle-particle domain decomposition.
+ */
+ const DeviceStream& bondedStream(bool hasPPDomainDecomposition) const;
+
+ /*! \brief Return whether the requested GPU stream is valid for use.
+ *
+ * \param[in] streamToCheck Which stream to check.
+ *
+ * \returns Whether the stream was initialized.
+ */
+ bool streamIsValid(DeviceStreamType streamToCheck) const;
+
+private:
+ class Impl;
+ PrivateImplPointer<Impl> impl_;
+};
+
+} // namespace gmx
+
+#endif
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ *
+ * \brief Implements the DeviceStream for OpenCL.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ */
+#include "gmxpre.h"
+
+#include "gromacs/gpu_utils/device_context_ocl.h"
+#include "gromacs/gpu_utils/device_stream.h"
+#include "gromacs/gpu_utils/gputraits_ocl.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+
+DeviceStream::DeviceStream()
+{
+ stream_ = nullptr;
+}
+
+void DeviceStream::init(const DeviceContext& deviceContext, DeviceStreamPriority /* priority */, const bool useTiming)
+{
+ const DeviceInformation& deviceInfo = deviceContext.deviceInfo();
+ cl_command_queue_properties queueProperties = useTiming ? CL_QUEUE_PROFILING_ENABLE : 0;
+ cl_device_id deviceId = deviceInfo.oclDeviceId;
+ cl_int clError;
+ stream_ = clCreateCommandQueue(deviceContext.context(), deviceId, queueProperties, &clError);
+ if (clError != CL_SUCCESS)
+ {
+ GMX_THROW(gmx::InternalError(gmx::formatString(
+ "Failed to create OpenCL command queue on GPU %s (OpenCL error ID %d).",
+ deviceInfo.device_name, clError)));
+ }
+}
+
+DeviceStream::~DeviceStream()
+{
+ if (isValid())
+ {
+ cl_int clError = clReleaseCommandQueue(stream_);
+ GMX_RELEASE_ASSERT(
+ clError == CL_SUCCESS,
+ gmx::formatString("Failed to release OpenCL stream (OpenCL error ID %d).", clError).c_str());
+ stream_ = nullptr;
+ }
+}
+
+cl_command_queue DeviceStream::stream() const
+{
+ return stream_;
+}
+
+bool DeviceStream::isValid() const
+{
+ return (stream_ != nullptr);
+}
+
+void DeviceStream::synchronize() const
+{
+ cl_int clError = clFinish(stream_);
+ GMX_RELEASE_ASSERT(
+ CL_SUCCESS == clError,
+ gmx::formatString("Error caught during clFinish (OpenCL error ID %d).", clError).c_str());
+}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \inlibraryapi
*/
+#include "gromacs/gpu_utils/cuda_arch_utils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gpu_utils.h" //only for GpuApiCallBehavior
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
/*! \brief
* Allocates a device-side buffer.
* \param[in] deviceContext The buffer's dummy device context - not managed explicitly in CUDA RT.
*/
template<typename ValueType>
-void allocateDeviceBuffer(DeviceBuffer<ValueType>* buffer, size_t numValues, DeviceContext /* deviceContext */)
+void allocateDeviceBuffer(DeviceBuffer<ValueType>* buffer, size_t numValues, const DeviceContext& /* deviceContext */)
{
GMX_ASSERT(buffer, "needs a buffer pointer");
cudaError_t stat = cudaMalloc((void**)buffer, numValues * sizeof(ValueType));
/*! \brief
* Performs the host-to-device data copy, synchronous or asynchronously on request.
*
- * TODO: This is meant to gradually replace cu/ocl_copy_h2d.
- *
* \tparam ValueType Raw value type of the \p buffer.
* \param[in,out] buffer Pointer to the device-side buffer
* \param[in] hostBuffer Pointer to the raw host-side memory, also typed \p ValueType
* \param[in] startingOffset Offset (in values) at the device-side buffer to copy into.
* \param[in] numValues Number of values to copy.
- * \param[in] stream GPU stream to perform asynchronous copy in.
+ * \param[in] deviceStream GPU stream to perform asynchronous copy in.
* \param[in] transferKind Copy type: synchronous or asynchronous.
* \param[out] timingEvent A dummy pointer to the H2D copy timing event to be filled in.
* Not used in CUDA implementation.
const ValueType* hostBuffer,
size_t startingOffset,
size_t numValues,
- CommandStream stream,
+ const DeviceStream& deviceStream,
GpuApiCallBehavior transferKind,
CommandEvent* /*timingEvent*/)
{
if (numValues == 0)
{
- return; // such calls are actually made with empty domains
+ return;
}
GMX_ASSERT(buffer, "needs a buffer pointer");
GMX_ASSERT(hostBuffer, "needs a host buffer pointer");
GMX_ASSERT(isHostMemoryPinned(hostBuffer),
"Source host buffer was not pinned for CUDA");
stat = cudaMemcpyAsync(*((ValueType**)buffer) + startingOffset, hostBuffer, bytes,
- cudaMemcpyHostToDevice, stream);
+ cudaMemcpyHostToDevice, deviceStream.stream());
GMX_RELEASE_ASSERT(stat == cudaSuccess, "Asynchronous H2D copy failed");
break;
}
}
-
/*! \brief
* Performs the device-to-host data copy, synchronous or asynchronously on request.
*
- * TODO: This is meant to gradually replace cu/ocl_copy_d2h.
- *
* \tparam ValueType Raw value type of the \p buffer.
* \param[in,out] hostBuffer Pointer to the raw host-side memory, also typed \p ValueType
* \param[in] buffer Pointer to the device-side buffer
* \param[in] startingOffset Offset (in values) at the device-side buffer to copy from.
* \param[in] numValues Number of values to copy.
- * \param[in] stream GPU stream to perform asynchronous copy in.
+ * \param[in] deviceStream GPU stream to perform asynchronous copy in.
* \param[in] transferKind Copy type: synchronous or asynchronous.
* \param[out] timingEvent A dummy pointer to the H2D copy timing event to be filled in.
* Not used in CUDA implementation.
DeviceBuffer<ValueType>* buffer,
size_t startingOffset,
size_t numValues,
- CommandStream stream,
+ const DeviceStream& deviceStream,
GpuApiCallBehavior transferKind,
CommandEvent* /*timingEvent*/)
{
+ if (numValues == 0)
+ {
+ return;
+ }
GMX_ASSERT(buffer, "needs a buffer pointer");
GMX_ASSERT(hostBuffer, "needs a host buffer pointer");
GMX_ASSERT(isHostMemoryPinned(hostBuffer),
"Destination host buffer was not pinned for CUDA");
stat = cudaMemcpyAsync(hostBuffer, *((ValueType**)buffer) + startingOffset, bytes,
- cudaMemcpyDeviceToHost, stream);
+ cudaMemcpyDeviceToHost, deviceStream.stream());
GMX_RELEASE_ASSERT(stat == cudaSuccess, "Asynchronous D2H copy failed");
break;
/*! \brief
* Clears the device buffer asynchronously.
*
- * \tparam ValueType Raw value type of the \p buffer.
- * \param[in,out] buffer Pointer to the device-side buffer
- * \param[in] startingOffset Offset (in values) at the device-side buffer to start clearing
- * at. \param[in] numValues Number of values to clear. \param[in] stream GPU stream.
+ * \tparam ValueType Raw value type of the \p buffer.
+ * \param[in,out] buffer Pointer to the device-side buffer
+ * \param[in] startingOffset Offset (in values) at the device-side buffer to start clearing at.
+ * \param[in] numValues Number of values to clear.
+ * \param[in] deviceStream GPU stream.
*/
template<typename ValueType>
-void clearDeviceBufferAsync(DeviceBuffer<ValueType>* buffer, size_t startingOffset, size_t numValues, CommandStream stream)
+void clearDeviceBufferAsync(DeviceBuffer<ValueType>* buffer,
+ size_t startingOffset,
+ size_t numValues,
+ const DeviceStream& deviceStream)
{
GMX_ASSERT(buffer, "needs a buffer pointer");
const size_t bytes = numValues * sizeof(ValueType);
const char pattern = 0;
- cudaError_t stat = cudaMemsetAsync(*((ValueType**)buffer) + startingOffset, pattern, bytes, stream);
+ cudaError_t stat = cudaMemsetAsync(*((ValueType**)buffer) + startingOffset, pattern, bytes,
+ deviceStream.stream());
GMX_RELEASE_ASSERT(stat == cudaSuccess, "Couldn't clear the device buffer");
}
+/*! \brief Check the validity of the device buffer.
+ *
+ * Checks if the buffer is not nullptr.
+ *
+ * \todo Add checks on the buffer size when it will be possible.
+ *
+ * \param[in] buffer Device buffer to be checked.
+ * \param[in] requiredSize Number of elements that the buffer will have to accommodate.
+ *
+ * \returns Whether the device buffer can be set.
+ */
+template<typename T>
+static bool checkDeviceBuffer(DeviceBuffer<T> buffer, gmx_unused int requiredSize)
+{
+ GMX_ASSERT(buffer != nullptr, "The device pointer is nullptr");
+ return buffer != nullptr;
+}
+
+//! Device texture wrapper.
+using DeviceTexture = cudaTextureObject_t;
+
+/*! \brief Create a texture object for an array of type ValueType.
+ *
+ * Creates the device buffer, copies data and binds texture object for an array of type ValueType.
+ *
+ * \todo Test if using textures is still relevant on modern hardware.
+ *
+ * \tparam ValueType Raw data type.
+ *
+ * \param[out] deviceBuffer Device buffer to store data in.
+ * \param[out] deviceTexture Device texture object to initialize.
+ * \param[in] hostBuffer Host buffer to get date from
+ * \param[in] numValues Number of elements in the buffer.
+ * \param[in] deviceContext GPU device context.
+ */
+template<typename ValueType>
+void initParamLookupTable(DeviceBuffer<ValueType>* deviceBuffer,
+ DeviceTexture* deviceTexture,
+ const ValueType* hostBuffer,
+ int numValues,
+ const DeviceContext& deviceContext)
+{
+ if (numValues == 0)
+ {
+ return;
+ }
+ GMX_ASSERT(hostBuffer, "Host buffer should be specified.");
+
+ allocateDeviceBuffer(deviceBuffer, numValues, deviceContext);
+
+ const size_t sizeInBytes = numValues * sizeof(ValueType);
+
+ cudaError_t stat =
+ cudaMemcpy(*((ValueType**)deviceBuffer), hostBuffer, sizeInBytes, cudaMemcpyHostToDevice);
+
+ GMX_RELEASE_ASSERT(
+ stat == cudaSuccess,
+ gmx::formatString("Synchronous H2D copy failed (CUDA error: %s).", cudaGetErrorName(stat))
+ .c_str());
+
+ if (!c_disableCudaTextures)
+ {
+ cudaResourceDesc rd;
+ cudaTextureDesc td;
+
+ memset(&rd, 0, sizeof(rd));
+ rd.resType = cudaResourceTypeLinear;
+ rd.res.linear.devPtr = *deviceBuffer;
+ rd.res.linear.desc = cudaCreateChannelDesc<ValueType>();
+ rd.res.linear.sizeInBytes = sizeInBytes;
+
+ memset(&td, 0, sizeof(td));
+ td.readMode = cudaReadModeElementType;
+ stat = cudaCreateTextureObject(deviceTexture, &rd, &td, nullptr);
+ GMX_RELEASE_ASSERT(stat == cudaSuccess,
+ gmx::formatString("cudaCreateTextureObject failed (CUDA error: %s).",
+ cudaGetErrorName(stat))
+ .c_str());
+ }
+}
+
+/*! \brief Unbind the texture and release the CUDA texture object.
+ *
+ * \tparam ValueType Raw data type
+ *
+ * \param[in,out] deviceBuffer Device buffer to store data in.
+ * \param[in,out] deviceTexture Device texture object to unbind.
+ */
+template<typename ValueType>
+void destroyParamLookupTable(DeviceBuffer<ValueType>* deviceBuffer, DeviceTexture& deviceTexture)
+{
+ if (!c_disableCudaTextures && deviceTexture && deviceBuffer)
+ {
+ cudaError_t stat = cudaDestroyTextureObject(deviceTexture);
+ GMX_RELEASE_ASSERT(
+ stat == cudaSuccess,
+ gmx::formatString(
+ "cudaDestroyTextureObject on texture object failed (CUDA error: %s).",
+ cudaGetErrorName(stat))
+ .c_str());
+ }
+ freeDeviceBuffer(deviceBuffer);
+}
+
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
size_t numValues,
int* currentNumValues,
int* currentMaxNumValues,
- DeviceContext deviceContext)
+ const DeviceContext& deviceContext)
{
GMX_ASSERT(buffer, "needs a buffer pointer");
GMX_ASSERT(currentNumValues, "needs a size pointer");
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \inlibraryapi
*/
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gpu_utils.h" //only for GpuApiCallBehavior
#include "gromacs/gpu_utils/gputraits_ocl.h"
* \param[in] deviceContext The buffer's device context-to-be.
*/
template<typename ValueType>
-void allocateDeviceBuffer(DeviceBuffer<ValueType>* buffer, size_t numValues, DeviceContext deviceContext)
+void allocateDeviceBuffer(DeviceBuffer<ValueType>* buffer, size_t numValues, const DeviceContext& deviceContext)
{
GMX_ASSERT(buffer, "needs a buffer pointer");
void* hostPtr = nullptr;
cl_int clError;
- *buffer = clCreateBuffer(deviceContext, CL_MEM_READ_WRITE, numValues * sizeof(ValueType),
- hostPtr, &clError);
+ *buffer = clCreateBuffer(deviceContext.context(), CL_MEM_READ_WRITE,
+ numValues * sizeof(ValueType), hostPtr, &clError);
GMX_RELEASE_ASSERT(clError == CL_SUCCESS,
gmx::formatString("clCreateBuffer failure (OpenCL error %d: %s)", clError,
ocl_get_error_string(clError).c_str())
* \param[in] hostBuffer Pointer to the raw host-side memory, also typed \p ValueType
* \param[in] startingOffset Offset (in values) at the device-side buffer to copy into.
* \param[in] numValues Number of values to copy.
- * \param[in] stream GPU stream to perform asynchronous copy in.
+ * \param[in] deviceStream GPU stream to perform asynchronous copy in.
* \param[in] transferKind Copy type: synchronous or asynchronous.
* \param[out] timingEvent A pointer to the H2D copy timing event to be filled in.
* If the pointer is not null, the event can further be used
const ValueType* hostBuffer,
size_t startingOffset,
size_t numValues,
- CommandStream stream,
+ const DeviceStream& deviceStream,
GpuApiCallBehavior transferKind,
CommandEvent* timingEvent)
{
switch (transferKind)
{
case GpuApiCallBehavior::Async:
- clError = clEnqueueWriteBuffer(stream, *buffer, CL_FALSE, offset, bytes, hostBuffer, 0,
- nullptr, timingEvent);
+ clError = clEnqueueWriteBuffer(deviceStream.stream(), *buffer, CL_FALSE, offset, bytes,
+ hostBuffer, 0, nullptr, timingEvent);
GMX_RELEASE_ASSERT(
clError == CL_SUCCESS,
gmx::formatString("Asynchronous H2D copy failed (OpenCL error %d: %s)", clError,
break;
case GpuApiCallBehavior::Sync:
- clError = clEnqueueWriteBuffer(stream, *buffer, CL_TRUE, offset, bytes, hostBuffer, 0,
- nullptr, timingEvent);
+ clError = clEnqueueWriteBuffer(deviceStream.stream(), *buffer, CL_TRUE, offset, bytes,
+ hostBuffer, 0, nullptr, timingEvent);
GMX_RELEASE_ASSERT(
clError == CL_SUCCESS,
gmx::formatString("Synchronous H2D copy failed (OpenCL error %d: %s)", clError,
* \param[in] buffer Pointer to the device-side buffer
* \param[in] startingOffset Offset (in values) at the device-side buffer to copy from.
* \param[in] numValues Number of values to copy.
- * \param[in] stream GPU stream to perform asynchronous copy in.
+ * \param[in] deviceStream GPU stream to perform asynchronous copy in.
* \param[in] transferKind Copy type: synchronous or asynchronous.
* \param[out] timingEvent A pointer to the H2D copy timing event to be filled in.
* If the pointer is not null, the event can further be used
DeviceBuffer<ValueType>* buffer,
size_t startingOffset,
size_t numValues,
- CommandStream stream,
+ const DeviceStream& deviceStream,
GpuApiCallBehavior transferKind,
CommandEvent* timingEvent)
{
switch (transferKind)
{
case GpuApiCallBehavior::Async:
- clError = clEnqueueReadBuffer(stream, *buffer, CL_FALSE, offset, bytes, hostBuffer, 0,
- nullptr, timingEvent);
+ clError = clEnqueueReadBuffer(deviceStream.stream(), *buffer, CL_FALSE, offset, bytes,
+ hostBuffer, 0, nullptr, timingEvent);
GMX_RELEASE_ASSERT(
clError == CL_SUCCESS,
gmx::formatString("Asynchronous D2H copy failed (OpenCL error %d: %s)", clError,
break;
case GpuApiCallBehavior::Sync:
- clError = clEnqueueReadBuffer(stream, *buffer, CL_TRUE, offset, bytes, hostBuffer, 0,
- nullptr, timingEvent);
+ clError = clEnqueueReadBuffer(deviceStream.stream(), *buffer, CL_TRUE, offset, bytes,
+ hostBuffer, 0, nullptr, timingEvent);
GMX_RELEASE_ASSERT(
clError == CL_SUCCESS,
gmx::formatString("Synchronous D2H copy failed (OpenCL error %d: %s)", clError,
/*! \brief
* Clears the device buffer asynchronously.
*
- * \tparam ValueType Raw value type of the \p buffer.
- * \param[in,out] buffer Pointer to the device-side buffer
- * \param[in] startingOffset Offset (in values) at the device-side buffer to start clearing
- * at. \param[in] numValues Number of values to clear. \param[in] stream GPU stream.
+ * \tparam ValueType Raw value type of the \p buffer.
+ * \param[in,out] buffer Pointer to the device-side buffer
+ * \param[in] startingOffset Offset (in values) at the device-side buffer to start clearing at.
+ * \param[in] numValues Number of values to clear.
+ * \param[in] deviceStream GPU stream.
*/
template<typename ValueType>
-void clearDeviceBufferAsync(DeviceBuffer<ValueType>* buffer, size_t startingOffset, size_t numValues, CommandStream stream)
+void clearDeviceBufferAsync(DeviceBuffer<ValueType>* buffer,
+ size_t startingOffset,
+ size_t numValues,
+ const DeviceStream& deviceStream)
{
GMX_ASSERT(buffer, "needs a buffer pointer");
const size_t offset = startingOffset * sizeof(ValueType);
const size_t bytes = numValues * sizeof(ValueType);
- const ValueType pattern = 0;
+ const int pattern = 0;
const cl_uint numWaitEvents = 0;
const cl_event* waitEvents = nullptr;
cl_event commandEvent;
- cl_int clError = clEnqueueFillBuffer(stream, *buffer, &pattern, sizeof(pattern), offset, bytes,
- numWaitEvents, waitEvents, &commandEvent);
+ cl_int clError = clEnqueueFillBuffer(deviceStream.stream(), *buffer, &pattern, sizeof(pattern),
+ offset, bytes, numWaitEvents, waitEvents, &commandEvent);
GMX_RELEASE_ASSERT(clError == CL_SUCCESS,
gmx::formatString("Couldn't clear the device buffer (OpenCL error %d: %s)",
clError, ocl_get_error_string(clError).c_str())
.c_str());
}
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunused-template"
+#endif
+
+/*! \brief Check the validity of the device buffer.
+ *
+ * Checks if the buffer is not nullptr and if its allocation is big enough.
+ *
+ * \param[in] buffer Device buffer to be checked.
+ * \param[in] requiredSize Number of elements that the buffer will have to accommodate.
+ *
+ * \returns Whether the device buffer can be set.
+ */
+template<typename T>
+static bool checkDeviceBuffer(DeviceBuffer<T> buffer, int requiredSize)
+{
+ size_t size;
+ int retval = clGetMemObjectInfo(buffer, CL_MEM_SIZE, sizeof(size), &size, nullptr);
+ GMX_ASSERT(retval == CL_SUCCESS,
+ gmx::formatString("clGetMemObjectInfo failed with error code #%d", retval).c_str());
+ GMX_ASSERT(static_cast<int>(size) >= requiredSize,
+ "Number of atoms in device buffer is smaller then required size.");
+ return retval == CL_SUCCESS && static_cast<int>(size) >= requiredSize;
+}
+
+//! Device texture wrapper.
+using DeviceTexture = void*;
+
+/*! \brief Create a texture object for an array of type ValueType.
+ *
+ * Creates the device buffer and copies read-only data for an array of type ValueType.
+ *
+ * \todo Decide if using image2d is most efficient.
+ *
+ * \tparam ValueType Raw data type.
+ *
+ * \param[out] deviceBuffer Device buffer to store data in.
+ * \param[in] hostBuffer Host buffer to get date from.
+ * \param[in] numValues Number of elements in the buffer.
+ * \param[in] deviceContext GPU device context.
+ */
+template<typename ValueType>
+void initParamLookupTable(DeviceBuffer<ValueType>* deviceBuffer,
+ DeviceTexture* /* deviceTexture */,
+ const ValueType* hostBuffer,
+ int numValues,
+ const DeviceContext& deviceContext)
+{
+ GMX_ASSERT(hostBuffer, "Host buffer pointer can not be null");
+ const size_t bytes = numValues * sizeof(ValueType);
+ cl_int clError;
+ *deviceBuffer = clCreateBuffer(deviceContext.context(),
+ CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR,
+ bytes, const_cast<ValueType*>(hostBuffer), &clError);
+
+ GMX_RELEASE_ASSERT(clError == CL_SUCCESS,
+ gmx::formatString("Constant memory allocation failed (OpenCL error %d: %s)",
+ clError, ocl_get_error_string(clError).c_str())
+ .c_str());
+}
+
+/*! \brief Release the OpenCL device buffer.
+ *
+ * \tparam ValueType Raw data type.
+ *
+ * \param[in,out] deviceBuffer Device buffer to store data in.
+ */
+template<typename ValueType>
+void destroyParamLookupTable(DeviceBuffer<ValueType>* deviceBuffer, DeviceTexture& /* deviceTexture*/)
+{
+ freeDeviceBuffer(deviceBuffer);
+}
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void free_gpu_info(const gmx_gpu_info_t* gpu_info)
{
- sfree(static_cast<void*>(gpu_info->gpu_dev)); // circumvent is_pod check in sfree
+ sfree(static_cast<void*>(gpu_info->deviceInfo)); // circumvent is_pod check in sfree
}
std::vector<int> getCompatibleGpus(const gmx_gpu_info_t& gpu_info)
compatibleGpus.reserve(gpu_info.n_dev);
for (int i = 0; i < gpu_info.n_dev; i++)
{
- assert(gpu_info.gpu_dev);
+ assert(gpu_info.deviceInfo);
if (gpu_info_get_stat(gpu_info, i) == egpuCompatible)
{
compatibleGpus.push_back(i);
#include <cuda_profiler_api.h>
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/pmalloc_cuda.h"
#include "gromacs/hardware/gpu_hw_info.h"
#include "gromacs/utility/basedefinitions.h"
try
{
KernelLaunchConfig config;
- config.blockSize[0] = 512;
- const auto dummyArguments = prepareGpuKernelArguments(k_dummy_test, config);
- launchGpuKernel(k_dummy_test, config, nullptr, "Dummy kernel", dummyArguments);
+ config.blockSize[0] = 512;
+ const auto dummyArguments = prepareGpuKernelArguments(k_dummy_test, config);
+ DeviceInformation deviceInfo;
+ const DeviceContext deviceContext(deviceInfo);
+ const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+ launchGpuKernel(k_dummy_test, config, deviceStream, nullptr, "Dummy kernel", dummyArguments);
}
catch (gmx::GromacsException& ex)
{
return 0;
}
-void init_gpu(const gmx_device_info_t* deviceInfo)
+void init_gpu(const DeviceInformation* deviceInfo)
{
cudaError_t stat;
}
}
-void free_gpu(const gmx_device_info_t* deviceInfo)
+void free_gpu(const DeviceInformation* deviceInfo)
{
// One should only attempt to clear the device context when
// it has been used, but currently the only way to know that a GPU
}
}
-gmx_device_info_t* getDeviceInfo(const gmx_gpu_info_t& gpu_info, int deviceId)
+DeviceInformation* getDeviceInfo(const gmx_gpu_info_t& gpu_info, int deviceId)
{
if (deviceId < 0 || deviceId >= gpu_info.n_dev)
{
gmx_incons("Invalid GPU deviceId requested");
}
- return &gpu_info.gpu_dev[deviceId];
+ return &gpu_info.deviceInfo[deviceId];
}
/*! \brief Returns true if the gpu characterized by the device properties is
// We expect to start device support/sanity checks with a clean runtime error state
gmx::ensureNoPendingCudaError("");
- gmx_device_info_t* devs;
+ DeviceInformation* devs;
snew(devs, ndev);
for (int i = 0; i < ndev; i++)
{
cudaGetErrorName(stat), cudaGetErrorString(stat))
.c_str());
- gpu_info->n_dev = ndev;
- gpu_info->gpu_dev = devs;
+ gpu_info->n_dev = ndev;
+ gpu_info->deviceInfo = devs;
}
void get_gpu_device_info_string(char* s, const gmx_gpu_info_t& gpu_info, int index)
return;
}
- gmx_device_info_t* dinfo = &gpu_info.gpu_dev[index];
+ DeviceInformation* dinfo = &gpu_info.deviceInfo[index];
bool bGpuExists = (dinfo->stat != egpuNonexistent && dinfo->stat != egpuInsane);
size_t sizeof_gpu_dev_info(void)
{
- return sizeof(gmx_device_info_t);
+ return sizeof(DeviceInformation);
}
void startGpuProfiler(void)
int gpu_info_get_stat(const gmx_gpu_info_t& info, int index)
{
- return info.gpu_dev[index].stat;
+ return info.deviceInfo[index].stat;
}
/*! \brief Check status returned from peer access CUDA call, and error out or warn appropriately
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2010, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/gpu_macros.h"
#include "gromacs/utility/basedefinitions.h"
-struct gmx_device_info_t;
+struct DeviceInformation;
struct gmx_gpu_info_t;
namespace gmx
* Will detect every GPU supported by the device driver in use.
* Must only be called if canPerformGpuDetection() has returned true.
* This routine also checks for the compatibility of each and fill the
- * gpu_info->gpu_dev array with the required information on each the
+ * gpu_info->deviceInfo array with the required information on each the
* device: ID, device properties, status.
*
* Note that this function leaves the GPU runtime API error state clean;
* initialization.
*/
GPU_FUNC_QUALIFIER
-void init_gpu(const gmx_device_info_t* GPU_FUNC_ARGUMENT(deviceInfo)) GPU_FUNC_TERM;
+void init_gpu(const DeviceInformation* GPU_FUNC_ARGUMENT(deviceInfo)) GPU_FUNC_TERM;
/*! \brief Frees up the CUDA GPU used by the active context at the time of calling.
*
* \returns true if no error occurs during the freeing.
*/
CUDA_FUNC_QUALIFIER
-void free_gpu(const gmx_device_info_t* CUDA_FUNC_ARGUMENT(deviceInfo)) CUDA_FUNC_TERM;
+void free_gpu(const DeviceInformation* CUDA_FUNC_ARGUMENT(deviceInfo)) CUDA_FUNC_TERM;
/*! \brief Return a pointer to the device info for \c deviceId
*
* \returns Pointer to the device info for \c deviceId.
*/
GPU_FUNC_QUALIFIER
-gmx_device_info_t* getDeviceInfo(const gmx_gpu_info_t& GPU_FUNC_ARGUMENT(gpu_info),
+DeviceInformation* getDeviceInfo(const gmx_gpu_info_t& GPU_FUNC_ARGUMENT(gpu_info),
int GPU_FUNC_ARGUMENT(deviceId)) GPU_FUNC_TERM_WITH_RETURN(nullptr);
/*! \brief Returns the device ID of the CUDA GPU currently in use.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
/*!
- * \brief Checks that device \c devInfo is sane (ie can run a kernel).
+ * \brief Checks that device \c deviceInfo is sane (ie can run a kernel).
*
* Compiles and runs a dummy kernel to determine whether the given
* OpenCL device functions properly.
*
*
- * \param[in] devInfo The device info pointer.
+ * \param[in] deviceInfo The device info pointer.
* \param[out] errorMessage An error message related to a failing OpenCL API call.
* \throws std::bad_alloc When out of memory.
* \returns Whether the device passed sanity checks
*/
-static bool isDeviceSane(const gmx_device_info_t* devInfo, std::string* errorMessage)
+static bool isDeviceSane(const DeviceInformation* deviceInfo, std::string* errorMessage)
{
cl_context_properties properties[] = {
- CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(devInfo->ocl_gpu_id.ocl_platform_id), 0
+ CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(deviceInfo->oclPlatformId), 0
};
// uncrustify spacing
cl_int status;
- auto deviceId = devInfo->ocl_gpu_id.ocl_device_id;
+ auto deviceId = deviceInfo->oclDeviceId;
ClContext context(clCreateContext(properties, 1, &deviceId, nullptr, nullptr, &status));
if (status != CL_SUCCESS)
{
}
/*!
- * \brief Checks that device \c devInfo is compatible with GROMACS.
+ * \brief Checks that device \c deviceInfo is compatible with GROMACS.
*
* Vendor and OpenCL version support checks are executed an the result
* of these returned.
*
- * \param[in] devInfo The device info pointer.
- * \returns The result of the compatibility checks.
+ * \param[in] deviceInfo The device info pointer.
+ * \returns The result of the compatibility checks.
*/
-static int isDeviceSupported(const gmx_device_info_t* devInfo)
+static int isDeviceSupported(const DeviceInformation* deviceInfo)
{
if (getenv("GMX_OCL_DISABLE_COMPATIBILITY_CHECK") != nullptr)
{
// the device which has the following format:
// OpenCL<space><major_version.minor_version><space><vendor-specific information>
unsigned int deviceVersionMinor, deviceVersionMajor;
- const int valuesScanned = std::sscanf(devInfo->device_version, "OpenCL %u.%u",
+ const int valuesScanned = std::sscanf(deviceInfo->device_version, "OpenCL %u.%u",
&deviceVersionMajor, &deviceVersionMinor);
const bool versionLargeEnough =
((valuesScanned == 2)
}
/* Only AMD, Intel, and NVIDIA GPUs are supported for now */
- switch (devInfo->vendor_e)
+ switch (deviceInfo->deviceVendor)
{
- case OCL_VENDOR_NVIDIA: return egpuCompatible;
- case OCL_VENDOR_AMD:
+ case DeviceVendor::Nvidia: return egpuCompatible;
+ case DeviceVendor::Amd:
return runningOnCompatibleOSForAmd() ? egpuCompatible : egpuIncompatible;
- case OCL_VENDOR_INTEL:
+ case DeviceVendor::Intel:
return GMX_OPENCL_NB_CLUSTER_SIZE == 4 ? egpuCompatible : egpuIncompatibleClusterSize;
default: return egpuIncompatible;
}
* \returns An e_gpu_detect_res_t to indicate how the GPU coped with
* the sanity and compatibility check.
*/
-static int checkGpu(size_t deviceId, const gmx_device_info_t* deviceInfo)
+static int checkGpu(size_t deviceId, const DeviceInformation* deviceInfo)
{
int supportStatus = isDeviceSupported(deviceInfo);
} // namespace gmx
-/*! \brief Returns an ocl_vendor_id_t value corresponding to the input OpenCL vendor name.
+/*! \brief Returns an DeviceVendor value corresponding to the input OpenCL vendor name.
*
- * \param[in] vendor_name String with OpenCL vendor name.
- * \returns ocl_vendor_id_t value for the input vendor_name
+ * \param[in] vendorName String with OpenCL vendor name.
+ * \returns DeviceVendor value for the input vendor name
*/
-static ocl_vendor_id_t get_vendor_id(char* vendor_name)
+static DeviceVendor getDeviceVendor(const char* vendorName)
{
- if (vendor_name)
+ if (vendorName)
{
- if (strstr(vendor_name, "NVIDIA"))
+ if (strstr(vendorName, "NVIDIA"))
{
- return OCL_VENDOR_NVIDIA;
+ return DeviceVendor::Nvidia;
}
- else if (strstr(vendor_name, "AMD") || strstr(vendor_name, "Advanced Micro Devices"))
+ else if (strstr(vendorName, "AMD") || strstr(vendorName, "Advanced Micro Devices"))
{
- return OCL_VENDOR_AMD;
+ return DeviceVendor::Amd;
}
- else if (strstr(vendor_name, "Intel"))
+ else if (strstr(vendorName, "Intel"))
{
- return OCL_VENDOR_INTEL;
+ return DeviceVendor::Intel;
}
}
- return OCL_VENDOR_UNKNOWN;
+ return DeviceVendor::Unknown;
}
bool isGpuDetectionFunctional(std::string* errorMessage)
break;
}
- snew(gpu_info->gpu_dev, gpu_info->n_dev);
+ snew(gpu_info->deviceInfo, gpu_info->n_dev);
{
int device_index;
for (unsigned int j = 0; j < ocl_device_count; j++)
{
- gpu_info->gpu_dev[device_index].ocl_gpu_id.ocl_platform_id = ocl_platform_ids[i];
- gpu_info->gpu_dev[device_index].ocl_gpu_id.ocl_device_id = ocl_device_ids[j];
+ gpu_info->deviceInfo[device_index].oclPlatformId = ocl_platform_ids[i];
+ gpu_info->deviceInfo[device_index].oclDeviceId = ocl_device_ids[j];
- gpu_info->gpu_dev[device_index].device_name[0] = 0;
+ gpu_info->deviceInfo[device_index].device_name[0] = 0;
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_NAME,
- sizeof(gpu_info->gpu_dev[device_index].device_name),
- gpu_info->gpu_dev[device_index].device_name, nullptr);
+ sizeof(gpu_info->deviceInfo[device_index].device_name),
+ gpu_info->deviceInfo[device_index].device_name, nullptr);
- gpu_info->gpu_dev[device_index].device_version[0] = 0;
+ gpu_info->deviceInfo[device_index].device_version[0] = 0;
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_VERSION,
- sizeof(gpu_info->gpu_dev[device_index].device_version),
- gpu_info->gpu_dev[device_index].device_version, nullptr);
+ sizeof(gpu_info->deviceInfo[device_index].device_version),
+ gpu_info->deviceInfo[device_index].device_version, nullptr);
- gpu_info->gpu_dev[device_index].device_vendor[0] = 0;
+ gpu_info->deviceInfo[device_index].vendorName[0] = 0;
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_VENDOR,
- sizeof(gpu_info->gpu_dev[device_index].device_vendor),
- gpu_info->gpu_dev[device_index].device_vendor, nullptr);
+ sizeof(gpu_info->deviceInfo[device_index].vendorName),
+ gpu_info->deviceInfo[device_index].vendorName, nullptr);
- gpu_info->gpu_dev[device_index].compute_units = 0;
+ gpu_info->deviceInfo[device_index].compute_units = 0;
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_MAX_COMPUTE_UNITS,
- sizeof(gpu_info->gpu_dev[device_index].compute_units),
- &(gpu_info->gpu_dev[device_index].compute_units), nullptr);
+ sizeof(gpu_info->deviceInfo[device_index].compute_units),
+ &(gpu_info->deviceInfo[device_index].compute_units), nullptr);
- gpu_info->gpu_dev[device_index].adress_bits = 0;
+ gpu_info->deviceInfo[device_index].adress_bits = 0;
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_ADDRESS_BITS,
- sizeof(gpu_info->gpu_dev[device_index].adress_bits),
- &(gpu_info->gpu_dev[device_index].adress_bits), nullptr);
+ sizeof(gpu_info->deviceInfo[device_index].adress_bits),
+ &(gpu_info->deviceInfo[device_index].adress_bits), nullptr);
- gpu_info->gpu_dev[device_index].vendor_e =
- get_vendor_id(gpu_info->gpu_dev[device_index].device_vendor);
+ gpu_info->deviceInfo[device_index].deviceVendor =
+ getDeviceVendor(gpu_info->deviceInfo[device_index].vendorName);
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_MAX_WORK_ITEM_SIZES, 3 * sizeof(size_t),
- &gpu_info->gpu_dev[device_index].maxWorkItemSizes, nullptr);
+ &gpu_info->deviceInfo[device_index].maxWorkItemSizes, nullptr);
clGetDeviceInfo(ocl_device_ids[j], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t),
- &gpu_info->gpu_dev[device_index].maxWorkGroupSize, nullptr);
+ &gpu_info->deviceInfo[device_index].maxWorkGroupSize, nullptr);
- gpu_info->gpu_dev[device_index].stat =
- gmx::checkGpu(device_index, gpu_info->gpu_dev + device_index);
+ gpu_info->deviceInfo[device_index].stat =
+ gmx::checkGpu(device_index, gpu_info->deviceInfo + device_index);
- if (egpuCompatible == gpu_info->gpu_dev[device_index].stat)
+ if (egpuCompatible == gpu_info->deviceInfo[device_index].stat)
{
gpu_info->n_dev_compatible++;
}
int last = -1;
for (int i = 0; i < gpu_info->n_dev; i++)
{
- if (OCL_VENDOR_AMD == gpu_info->gpu_dev[i].vendor_e)
+ if (gpu_info->deviceInfo[i].deviceVendor == DeviceVendor::Amd)
{
last++;
if (last < i)
{
- gmx_device_info_t ocl_gpu_info;
- ocl_gpu_info = gpu_info->gpu_dev[i];
- gpu_info->gpu_dev[i] = gpu_info->gpu_dev[last];
- gpu_info->gpu_dev[last] = ocl_gpu_info;
+ std::swap(gpu_info->deviceInfo[i], gpu_info->deviceInfo[last]);
}
}
}
{
for (int i = 0; i < gpu_info->n_dev; i++)
{
- if (OCL_VENDOR_NVIDIA == gpu_info->gpu_dev[i].vendor_e)
+ if (gpu_info->deviceInfo[i].deviceVendor == DeviceVendor::Nvidia)
{
last++;
if (last < i)
{
- gmx_device_info_t ocl_gpu_info;
- ocl_gpu_info = gpu_info->gpu_dev[i];
- gpu_info->gpu_dev[i] = gpu_info->gpu_dev[last];
- gpu_info->gpu_dev[last] = ocl_gpu_info;
+ std::swap(gpu_info->deviceInfo[i], gpu_info->deviceInfo[last]);
}
}
}
return;
}
- gmx_device_info_t* dinfo = &gpu_info.gpu_dev[index];
+ DeviceInformation* dinfo = &gpu_info.deviceInfo[index];
bool bGpuExists = (dinfo->stat != egpuNonexistent && dinfo->stat != egpuInsane);
else
{
sprintf(s, "#%d: name: %s, vendor: %s, device version: %s, stat: %s", index, dinfo->device_name,
- dinfo->device_vendor, dinfo->device_version, gpu_detect_res_str[dinfo->stat]);
+ dinfo->vendorName, dinfo->device_version, gpu_detect_res_str[dinfo->stat]);
}
}
-void init_gpu(const gmx_device_info_t* deviceInfo)
+void init_gpu(const DeviceInformation* deviceInfo)
{
assert(deviceInfo);
// the cache does not always get regenerated when the source code changes,
// e.g. if the path to the kernel sources remains the same
- if (deviceInfo->vendor_e == OCL_VENDOR_NVIDIA)
+ if (deviceInfo->deviceVendor == DeviceVendor::Nvidia)
{
// Ignore return values, failing to set the variable does not mean
// that something will go wrong later.
}
}
-gmx_device_info_t* getDeviceInfo(const gmx_gpu_info_t& gpu_info, int deviceId)
+DeviceInformation* getDeviceInfo(const gmx_gpu_info_t& gpu_info, int deviceId)
{
if (deviceId < 0 || deviceId >= gpu_info.n_dev)
{
gmx_incons("Invalid GPU deviceId requested");
}
- return &gpu_info.gpu_dev[deviceId];
+ return &gpu_info.deviceInfo[deviceId];
}
size_t sizeof_gpu_dev_info()
{
- return sizeof(gmx_device_info_t);
+ return sizeof(DeviceInformation);
}
int gpu_info_get_stat(const gmx_gpu_info_t& info, int index)
{
- return info.gpu_dev[index].stat;
+ return info.deviceInfo[index].stat;
}
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#ifndef GMX_GPU_UTILS_GPU_VEC_CUH
-#define GMX_GPU_UTILS_GPU_VEC_CUH
-
-/* Note that because of the duplicate of ivec, this header (or an
- * OpenCL port of it) cannot be included in a translation unit that
- * also includes the normal vectypes.h */
-#define XX 0 /* Defines for indexing in */
-#define YY 1 /* vectors */
-#define ZZ 2
-#define DIM 3 /* Dimension of vectors */
-typedef int ivec[DIM];
-typedef float fvec[DIM];
-
-/* maths operations */
-/* imported from cpu versions in math/vec.h */
-__forceinline__ __device__ void svmul_gpu(float a, const fvec v1, fvec v2)
-{
- v2[XX] = a * v1[XX];
- v2[YY] = a * v1[YY];
- v2[ZZ] = a * v1[ZZ];
-}
-
-
-__forceinline__ __device__ void fvec_add_gpu(const fvec a, const fvec b, fvec c)
-{
- float x, y, z;
-
- x = a[XX] + b[XX];
- y = a[YY] + b[YY];
- z = a[ZZ] + b[ZZ];
-
- c[XX] = x;
- c[YY] = y;
- c[ZZ] = z;
-}
-
-__forceinline__ __device__ void ivec_add_gpu(const ivec a, const ivec b, ivec c)
-{
- int x, y, z;
-
- x = a[XX] + b[XX];
- y = a[YY] + b[YY];
- z = a[ZZ] + b[ZZ];
-
- c[XX] = x;
- c[YY] = y;
- c[ZZ] = z;
-}
-
-__forceinline__ __device__ void fvec_inc_atomic(fvec a, const fvec b)
-{
- atomicAdd(&a[XX], b[XX]);
- atomicAdd(&a[YY], b[YY]);
- atomicAdd(&a[ZZ], b[ZZ]);
-}
-
-__forceinline__ __device__ void fvec_inc_gpu(fvec a, const fvec b)
-{
- float x, y, z;
-
- x = a[XX] + b[XX];
- y = a[YY] + b[YY];
- z = a[ZZ] + b[ZZ];
-
- a[XX] = x;
- a[YY] = y;
- a[ZZ] = z;
-}
-
-__forceinline__ __device__ void fvec_dec_atomic(fvec a, const fvec b)
-{
- atomicAdd(&a[XX], -1.0f * b[XX]);
- atomicAdd(&a[YY], -1.0f * b[YY]);
- atomicAdd(&a[ZZ], -1.0f * b[ZZ]);
-}
-
-__forceinline__ __device__ void fvec_dec_gpu(fvec a, const fvec b)
-{
- float x, y, z;
-
- x = a[XX] - b[XX];
- y = a[YY] - b[YY];
- z = a[ZZ] - b[ZZ];
-
- a[XX] = x;
- a[YY] = y;
- a[ZZ] = z;
-}
-
-__forceinline__ __device__ void cprod_gpu(const fvec a, const fvec b, fvec c)
-{
- c[XX] = a[YY] * b[ZZ] - a[ZZ] * b[YY];
- c[YY] = a[ZZ] * b[XX] - a[XX] * b[ZZ];
- c[ZZ] = a[XX] * b[YY] - a[YY] * b[XX];
-}
-
-__forceinline__ __device__ float iprod_gpu(const fvec a, const fvec b)
-{
- return (a[XX] * b[XX] + a[YY] * b[YY] + a[ZZ] * b[ZZ]);
-}
-
-__forceinline__ __device__ float norm_gpu(const fvec a)
-{
- return sqrt(iprod_gpu(a, a));
-}
-
-__forceinline__ __device__ float gmx_angle_gpu(const fvec a, const fvec b)
-{
- fvec w;
- float wlen, s;
-
- cprod_gpu(a, b, w);
-
- wlen = norm_gpu(w);
- s = iprod_gpu(a, b);
-
- return atan2f(wlen, s); // requires float
-}
-
-__forceinline__ __device__ void clear_ivec_gpu(ivec a)
-{
- a[XX] = 0;
- a[YY] = 0;
- a[ZZ] = 0;
-}
-__forceinline__ __device__ void fvec_sub_gpu(const fvec a, const fvec b, fvec c)
-{
- float x, y, z;
-
- x = a[XX] - b[XX];
- y = a[YY] - b[YY];
- z = a[ZZ] - b[ZZ];
-
- c[XX] = x;
- c[YY] = y;
- c[ZZ] = z;
-}
-
-__forceinline__ __device__ float norm2_gpu(const fvec a)
-{
- return a[XX] * a[XX] + a[YY] * a[YY] + a[ZZ] * a[ZZ];
-}
-
-__forceinline__ __device__ void copy_fvec_gpu(const fvec a, fvec b)
-{
- b[XX] = a[XX];
- b[YY] = a[YY];
- b[ZZ] = a[ZZ];
-}
-
-__forceinline__ __device__ void copy_ivec_gpu(const ivec a, ivec b)
-{
- b[XX] = a[XX];
- b[YY] = a[YY];
- b[ZZ] = a[ZZ];
-}
-
-__forceinline__ __device__ float cos_angle_gpu(const fvec a, const fvec b)
-{
- /*
- * ax*bx + ay*by + az*bz
- * cos-vec (a,b) = ---------------------
- * ||a|| * ||b||
- */
- float cosval;
- int m;
- float aa, bb, ip, ipa, ipb, ipab;
-
- ip = ipa = ipb = 0.0f;
- for (m = 0; (m < DIM); m++)
- {
- aa = a[m];
- bb = b[m];
- ip += aa * bb;
- ipa += aa * aa;
- ipb += bb * bb;
- }
- ipab = ipa * ipb;
- if (ipab > 0.0f)
- {
- cosval = ip * rsqrt(ipab);
- }
- else
- {
- cosval = 1.0f;
- }
- if (cosval > 1.0f)
- {
- return 1.0f;
- }
- if (cosval < -1.0f)
- {
- return -1.0f;
- }
-
- return cosval;
-}
-
-
-__device__ static inline void unitv_gpu(const fvec src, fvec dest)
-{
- float linv;
-
- linv = rsqrt(norm2_gpu(src));
- dest[XX] = linv * src[XX];
- dest[YY] = linv * src[YY];
- dest[ZZ] = linv * src[ZZ];
-}
-
-#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief Marks the synchronization point in the \p stream.
* Should be followed by waitForEvent().
*/
- inline void markEvent(CommandStream stream)
+ inline void markEvent(const DeviceStream& deviceStream)
{
- cudaError_t gmx_used_in_debug stat = cudaEventRecord(event_, stream);
+ cudaError_t gmx_used_in_debug stat = cudaEventRecord(event_, deviceStream.stream());
GMX_ASSERT(stat == cudaSuccess, "cudaEventRecord failed");
}
/*! \brief Synchronizes the host thread on the marked event. */
GMX_ASSERT(stat == cudaSuccess, "cudaEventSynchronize failed");
}
/*! \brief Enqueues a wait for the recorded event in stream \p stream */
- inline void enqueueWaitEvent(CommandStream stream)
+ inline void enqueueWaitEvent(const DeviceStream& deviceStream)
{
- cudaError_t gmx_used_in_debug stat = cudaStreamWaitEvent(stream, event_, 0);
+ cudaError_t gmx_used_in_debug stat = cudaStreamWaitEvent(deviceStream.stream(), event_, 0);
GMX_ASSERT(stat == cudaSuccess, "cudaStreamWaitEvent failed");
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief Marks the synchronization point in the \p stream.
* Should be called first and then followed by waitForEvent().
*/
- inline void markEvent(CommandStream stream)
+ inline void markEvent(const DeviceStream& deviceStream)
{
GMX_ASSERT(nullptr == event_, "Do not call markEvent more than once!");
- cl_int clError = clEnqueueMarkerWithWaitList(stream, 0, nullptr, &event_);
+ cl_int clError = clEnqueueMarkerWithWaitList(deviceStream.stream(), 0, nullptr, &event_);
if (CL_SUCCESS != clError)
{
GMX_THROW(gmx::InternalError("Failed to enqueue the GPU synchronization event: "
* After enqueue, the associated event is released, so this method should
* be only called once per markEvent() call.
*/
- inline void enqueueWaitEvent(CommandStream stream)
+ inline void enqueueWaitEvent(const DeviceStream& deviceStream)
{
- cl_int clError = clEnqueueBarrierWithWaitList(stream, 1, &event_, nullptr);
+ cl_int clError = clEnqueueBarrierWithWaitList(deviceStream.stream(), 1, &event_, nullptr);
if (CL_SUCCESS != clError)
{
GMX_THROW(gmx::InternalError("Failed to enqueue device barrier for the GPU event: "
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
GpuRegionTimerImpl(GpuRegionTimerImpl&&) = delete;
/*! \brief Will be called before the region start. */
- inline void openTimingRegion(CommandStream s)
+ inline void openTimingRegion(const DeviceStream& deviceStream)
{
- CU_RET_ERR(cudaEventRecord(eventStart_, s), "GPU timing recording failure");
+ CU_RET_ERR(cudaEventRecord(eventStart_, deviceStream.stream()),
+ "GPU timing recording failure");
}
/*! \brief Will be called after the region end. */
- inline void closeTimingRegion(CommandStream s)
+ inline void closeTimingRegion(const DeviceStream& deviceStream)
{
- CU_RET_ERR(cudaEventRecord(eventStop_, s), "GPU timing recording failure");
+ CU_RET_ERR(cudaEventRecord(eventStop_, deviceStream.stream()),
+ "GPU timing recording failure");
}
/*! \brief Returns the last measured region timespan (in milliseconds) and calls reset() */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief
* To be called before the region start.
*
- * \param[in] s The GPU command stream where the event being measured takes place.
+ * \param[in] deviceStream The GPU command stream where the event being measured takes place.
*/
- void openTimingRegion(CommandStream s)
+ void openTimingRegion(const DeviceStream& deviceStream)
{
if (c_debugTimerState)
{
GMX_ASSERT(debugState_ == TimerState::Idle, error.c_str());
debugState_ = TimerState::Recording;
}
- impl_.openTimingRegion(s);
+ impl_.openTimingRegion(deviceStream);
}
/*! \brief
* To be called after the region end.
*
- * \param[in] s The GPU command stream where the event being measured takes place.
+ * \param[in] deviceStream The GPU command stream where the event being measured takes place.
*/
- void closeTimingRegion(CommandStream s)
+ void closeTimingRegion(const DeviceStream& deviceStream)
{
if (c_debugTimerState)
{
debugState_ = TimerState::Stopped;
}
callCount_++;
- impl_.closeTimingRegion(s);
+ impl_.closeTimingRegion(deviceStream);
}
/*! \brief
* Accumulates the last timespan of all the events used into the total duration,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/gputraits_ocl.h"
#include "gromacs/gpu_utils/oclutils.h"
+#include "gromacs/utility/stringutil.h"
#include "gpuregiontimer.h"
GpuRegionTimerImpl(GpuRegionTimerImpl&&) = delete;
/*! \brief Should be called before the region start. */
- inline void openTimingRegion(CommandStream /*unused*/) {}
+ inline void openTimingRegion(const DeviceStream& /*unused*/) {}
/*! \brief Should be called after the region end. */
- inline void closeTimingRegion(CommandStream /*unused*/) {}
+ inline void closeTimingRegion(const DeviceStream& /*unused*/) {}
/*! \brief Returns the last measured region timespan (in milliseconds) and calls reset(). */
inline double getLastRangeTime()
{
cl_error = clGetEventProfilingInfo(events_[i], CL_PROFILING_COMMAND_START,
sizeof(cl_ulong), &start_ns, nullptr);
- GMX_ASSERT(CL_SUCCESS == cl_error, "GPU timing update failure");
+ GMX_ASSERT(CL_SUCCESS == cl_error,
+ gmx::formatString("GPU timing update failure (OpenCL error %d: %s).",
+ cl_error, ocl_get_error_string(cl_error).c_str())
+ .c_str());
cl_error = clGetEventProfilingInfo(events_[i], CL_PROFILING_COMMAND_END,
sizeof(cl_ulong), &end_ns, nullptr);
- GMX_ASSERT(CL_SUCCESS == cl_error, "GPU timing update failure");
+ GMX_ASSERT(CL_SUCCESS == cl_error,
+ gmx::formatString("GPU timing update failure (OpenCL error %d: %s).",
+ cl_error, ocl_get_error_string(cl_error).c_str())
+ .c_str());
milliseconds += (end_ns - start_ns) / 1000000.0;
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \libinternal \file
* \brief Declares the CUDA type traits.
+ *
* \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
*
* \inlibraryapi
* \ingroup module_gpu_utils
*/
-//! \brief GPU command stream
-using CommandStream = cudaStream_t;
+#include "gromacs/gpu_utils/device_stream.h"
+
+/*! \brief CUDA device information.
+ *
+ * The CUDA device information is queried and set at detection and contains
+ * both information about the device/hardware returned by the runtime as well
+ * as additional data like support status.
+ */
+struct DeviceInformation
+{
+ //! ID of the CUDA device.
+ int id;
+ //! CUDA device properties.
+ cudaDeviceProp prop;
+ //! Result of the device check.
+ int stat;
+};
+
//! \brief Single GPU call timing event - meaningless in CUDA
using CommandEvent = void;
-//! \brief Context used explicitly in OpenCL, does nothing in CUDA
-using DeviceContext = void*;
/*! \internal \brief
* GPU kernels scheduling description. This is same in OpenCL/CUDA.
*/
struct KernelLaunchConfig
{
- size_t gridSize[3] = { 1, 1, 1 }; //!< Block counts
- size_t blockSize[3] = { 1, 1, 1 }; //!< Per-block thread counts
- size_t sharedMemorySize = 0; //!< Shared memory size in bytes
- CommandStream stream = nullptr; //!< Stream to launch kernel in
+ //! Block counts
+ size_t gridSize[3] = { 1, 1, 1 };
+ //! Per-block thread counts
+ size_t blockSize[3] = { 1, 1, 1 };
+ //! Shared memory size in bytes
+ size_t sharedMemorySize = 0;
};
//! Sets whether device code can use arrays that are embedded in structs.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_GPU_UTILS_GPUTRAITS_H
/*! \libinternal \file
- * \brief Declares the GPU type traits for non-GPU builds
+ * \brief Declares the GPU type traits for non-GPU builds.
+ *
* \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
*
* \inlibraryapi
* \ingroup module_gpu_utils
#else
-//! \brief GPU command stream
-using CommandStream = void*;
+//! Stub for device information.
+struct DeviceInformation
+{
+ // No member needed
+};
+
//! \brief Single GPU call timing event
using CommandEvent = void*;
-//! \brief GPU context
-using DeviceContext = void*;
#endif // GMX_GPU
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \libinternal \file
* \brief Declares the OpenCL type traits.
+ *
* \author Aleksei Iupinov <a.yupinov@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
*
* \inlibraryapi
* \ingroup module_gpu_utils
#include "gromacs/gpu_utils/gmxopencl.h"
-//! \brief GPU command stream
-using CommandStream = cl_command_queue;
+//! OpenCL device vendors
+enum class DeviceVendor : int
+{
+ Unknown = 0, //!< No data
+ Nvidia = 1, //!< NVIDIA
+ Amd = 2, //!< Advanced Micro Devices
+ Intel = 3, //!< Intel
+ Count = 4
+};
+
+/*! \internal
+ * \brief OpenCL device information.
+ *
+ * The OpenCL device information is queried and set at detection and contains
+ * both information about the device/hardware returned by the runtime as well
+ * as additional data like support status.
+ */
+struct DeviceInformation
+{
+ cl_platform_id oclPlatformId; //!< OpenCL Platform ID.
+ cl_device_id oclDeviceId; //!< OpenCL Device ID.
+ char device_name[256]; //!< Device name.
+ char device_version[256]; //!< Device version.
+ char vendorName[256]; //!< Device vendor name.
+ int compute_units; //!< Number of compute units.
+ int adress_bits; //!< Number of address bits the device is capable of.
+ int stat; //!< Device status takes values of e_gpu_detect_res_t.
+ DeviceVendor deviceVendor; //!< Device vendor.
+ size_t maxWorkItemSizes[3]; //!< Workgroup size limits (CL_DEVICE_MAX_WORK_ITEM_SIZES).
+ size_t maxWorkGroupSize; //!< Workgroup total size limit (CL_DEVICE_MAX_WORK_GROUP_SIZE).
+};
+
//! \brief Single GPU call timing event
using CommandEvent = cl_event;
-//! \brief Context used explicitly in OpenCL
-using DeviceContext = cl_context;
/*! \internal \brief
* GPU kernels scheduling description. This is same in OpenCL/CUDA.
*/
struct KernelLaunchConfig
{
- size_t gridSize[3] = { 1, 1, 1 }; //!< Work groups (CUDA blocks) counts
- size_t blockSize[3] = { 1, 1, 1 }; //!< Per work group (CUDA block) thread counts
- size_t sharedMemorySize = 0; //!< Shared memory size in bytes
- CommandStream stream = nullptr; //!< Stream to launch kernel in
+ //! Work groups (CUDA blocks) counts
+ size_t gridSize[3] = { 1, 1, 1 };
+ //! Per work group (CUDA block) thread counts
+ size_t blockSize[3] = { 1, 1, 1 };
+ //! Shared memory size in bytes
+ size_t sharedMemorySize = 0;
};
/*! \brief Sets whether device code can use arrays that are embedded in structs.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Propagate for move
using propagate_on_container_swap = std::true_type;
//! Use default allocator for copy (same as construct+copy)
+ // NOLINTNEXTLINE readability-convert-member-functions-to-static
HostAllocationPolicy select_on_container_copy_construction() const { return {}; }
private:
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief Construct compiler options string
*
- * \param deviceVendorId Device vendor id. Used to
- * automatically enable some vendor-specific options
+ * \param deviceVendor Device vendor. Used to automatically enable some
+ * vendor-specific options.
* \return The string with the compiler options
*/
-static std::string selectCompilerOptions(ocl_vendor_id_t deviceVendorId)
+static std::string selectCompilerOptions(DeviceVendor deviceVendor)
{
std::string compilerOptions;
compilerOptions += " -cl-denorms-are-zero";
}
- if ((deviceVendorId == OCL_VENDOR_NVIDIA) && getenv("GMX_OCL_VERBOSE"))
+ if ((deviceVendor == DeviceVendor::Nvidia) && getenv("GMX_OCL_VERBOSE"))
{
compilerOptions += " -cl-nv-verbose";
}
- if ((deviceVendorId == OCL_VENDOR_AMD) && getenv("GMX_OCL_DUMP_INTERM_FILES"))
+ if ((deviceVendor == DeviceVendor::Amd) && getenv("GMX_OCL_DUMP_INTERM_FILES"))
{
/* To dump OpenCL build intermediate files, caching must be off */
if (!useBuildCache)
/*! \brief Select a compilation-line define for a vendor-specific kernel choice from vendor id
*
- * \param[in] vendorId Vendor id enumerator
+ * \param[in] deviceVendor Vendor id enumerator
*
* \return The appropriate compilation-line define
*/
-static const char* makeVendorFlavorChoice(ocl_vendor_id_t vendorId)
+static std::string makeVendorFlavorChoice(DeviceVendor deviceVendor)
{
- const char* choice;
- switch (vendorId)
+ switch (deviceVendor)
{
- case OCL_VENDOR_AMD: choice = "-D_AMD_SOURCE_"; break;
- case OCL_VENDOR_NVIDIA: choice = "-D_NVIDIA_SOURCE_"; break;
- case OCL_VENDOR_INTEL: choice = "-D_INTEL_SOURCE_"; break;
- default: choice = ""; break;
+ case DeviceVendor::Amd: return "-D_AMD_SOURCE_";
+ case DeviceVendor::Nvidia: return "-D_NVIDIA_SOURCE_";
+ case DeviceVendor::Intel: return "-D_INTEL_SOURCE_";
+ default: return "";
}
- return choice;
}
/*! \brief Create include paths for kernel sources.
static std::string makePreprocessorOptions(const std::string& kernelRootPath,
const std::string& includeRootPath,
size_t warpSize,
- ocl_vendor_id_t deviceVendorId,
+ DeviceVendor deviceVendor,
const std::string& extraDefines)
{
std::string preprocessorOptions;
/* Compose the complete build options */
preprocessorOptions = formatString("-DWARP_SIZE_TEST=%d", static_cast<int>(warpSize));
preprocessorOptions += ' ';
- preprocessorOptions += makeVendorFlavorChoice(deviceVendorId);
+ preprocessorOptions += makeVendorFlavorChoice(deviceVendor);
preprocessorOptions += ' ';
preprocessorOptions += extraDefines;
preprocessorOptions += ' ';
- preprocessorOptions += selectCompilerOptions(deviceVendorId);
+ preprocessorOptions += selectCompilerOptions(deviceVendor);
preprocessorOptions += ' ';
preprocessorOptions += makeKernelIncludePathOption(kernelRootPath);
preprocessorOptions += ' ';
const std::string& extraDefines,
cl_context context,
cl_device_id deviceId,
- ocl_vendor_id_t deviceVendorId)
+ DeviceVendor deviceVendor)
{
cl_int cl_error;
// Let the kernel find include files from its module.
/* Make the build options */
std::string preprocessorOptions = makePreprocessorOptions(
- kernelRootPath, rootPath, getDeviceWarpSize(context, deviceId), deviceVendorId, extraDefines);
+ kernelRootPath, rootPath, getDeviceWarpSize(context, deviceId), deviceVendor, extraDefines);
bool buildCacheWasRead = false;
}
}
}
- if ((OCL_VENDOR_NVIDIA == deviceVendorId) && getenv("GMX_OCL_DUMP_INTERM_FILES"))
+ if ((deviceVendor == DeviceVendor::Nvidia) && getenv("GMX_OCL_DUMP_INTERM_FILES"))
{
/* If dumping intermediate files has been requested and this is an NVIDIA card
=> write PTX to file */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This is platform implementation dependent and seems to only work on the Nvidia and AMD
* platforms! Nvidia reports 32, AMD for GPU 64. Intel seems to report 16, but that is not correct,
* as it execution width can be between 8-32 and it's picked per-kernel at compile-time.
- * Therefore, for Intel it should actually be queried separately for each kernel (Redmine #2520).
+ * Therefore, for Intel it should actually be queried separately for each kernel (Issue #2520).
*
* \param context Current OpenCL context
* \param deviceId OpenCL device with the context
* \param[in] kernelRelativePath Relative path to the kernel in the source tree,
* e.g. "src/gromacs/mdlib/nbnxn_ocl" for NB kernels.
* \param[in] kernelBaseFilename The name of the kernel source file to compile, e.g.
- * "nbnxn_ocl_kernels.cl" \param[in] extraDefines Preprocessor defines required by the
- * calling code, e.g. for configuring the kernels \param[in] context OpenCL context
- * on the device to compile for \param[in] deviceId OpenCL device id of the device to
- * compile for \param[in] deviceVendorId Enumerator of the device vendor to compile for
+ * "nbnxn_ocl_kernels.cl"
+ * \param[in] extraDefines Preprocessor defines required by the calling code,
+ * e.g. for configuring the kernels
+ * \param[in] context OpenCL context on the device to compile for
+ * \param[in] deviceId OpenCL device id of the device to compile for
+ * \param[in] deviceVendor Enumerator of the device vendor to compile for
*
* \returns The compiled OpenCL program
*
const std::string& extraDefines,
cl_context context,
cl_device_id deviceId,
- ocl_vendor_id_t deviceVendorId);
+ DeviceVendor deviceVendor);
} // namespace ocl
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
case GpuApiCallBehavior::Async:
cl_error = clEnqueueWriteBuffer(command_queue, d_dest, CL_FALSE, offset, bytes, h_src,
0, nullptr, copy_event);
- assert(cl_error == CL_SUCCESS);
- // TODO: handle errors
break;
case GpuApiCallBehavior::Sync:
cl_error = clEnqueueWriteBuffer(command_queue, d_dest, CL_TRUE, offset, bytes, h_src, 0,
nullptr, copy_event);
- assert(cl_error == CL_SUCCESS);
- // TODO: handle errors
break;
default: throw;
}
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clEnqueueWriteBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
return 0;
}
case GpuApiCallBehavior::Async:
cl_error = clEnqueueReadBuffer(command_queue, d_src, CL_FALSE, offset, bytes, h_dest, 0,
nullptr, copy_event);
- assert(cl_error == CL_SUCCESS);
- // TODO: handle errors
break;
case GpuApiCallBehavior::Sync:
cl_error = clEnqueueReadBuffer(command_queue, d_src, CL_TRUE, offset, bytes, h_dest, 0,
nullptr, copy_event);
- assert(cl_error == CL_SUCCESS);
- // TODO: handle errors
break;
default: throw;
}
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clEnqueueWriteBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
+
return 0;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <string>
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/gmxopencl.h"
#include "gromacs/gpu_utils/gputraits_ocl.h"
#include "gromacs/utility/exceptions.h"
enum class GpuApiCallBehavior;
-/*! \brief OpenCL vendor IDs */
-typedef enum
-{
- OCL_VENDOR_NVIDIA = 0,
- OCL_VENDOR_AMD,
- OCL_VENDOR_INTEL,
- OCL_VENDOR_UNKNOWN
-} ocl_vendor_id_t;
-
-/*! \internal
- * \brief OpenCL GPU device identificator
- *
- * An OpenCL device is identified by its ID.
- * The platform ID is also included for caching reasons.
- */
-typedef struct
-{
- cl_platform_id ocl_platform_id; /**< Platform ID */
- cl_device_id ocl_device_id; /**< Device ID */
-} ocl_gpu_id_t;
-
-/*! \internal
- * \brief OpenCL device information.
- *
- * The OpenCL device information is queried and set at detection and contains
- * both information about the device/hardware returned by the runtime as well
- * as additional data like support status.
- */
-struct gmx_device_info_t
-{
- ocl_gpu_id_t ocl_gpu_id; /**< device ID assigned at detection */
- char device_name[256]; /**< device name */
- char device_version[256]; /**< device version */
- char device_vendor[256]; /**< device vendor */
- int compute_units; /**< number of compute units */
- int adress_bits; /**< number of adress bits the device is capable of */
- int stat; /**< device status takes values of e_gpu_detect_res_t */
- ocl_vendor_id_t vendor_e; /**< device vendor as defined by ocl_vendor_id_t */
- size_t maxWorkItemSizes[3]; /**< workgroup size limits (CL_DEVICE_MAX_WORK_ITEM_SIZES) */
- size_t maxWorkGroupSize; /**< workgroup total size limit (CL_DEVICE_MAX_WORK_GROUP_SIZE) */
-};
-
/*! \internal
* \brief OpenCL GPU runtime data
*
*/
struct gmx_device_runtime_data_t
{
- cl_context context; /**< OpenCL context */
- cl_program program; /**< OpenCL program */
+ //! OpenCL program
+ cl_program program;
};
/*! \brief Launches synchronous or asynchronous device to host memory copy.
/*! \brief Convert error code to diagnostic string */
std::string ocl_get_error_string(cl_int error);
-/*! \brief Calls clFinish() in the stream \p s.
- *
- * \param[in] s stream to synchronize with
- */
-static inline void gpuStreamSynchronize(cl_command_queue s)
-{
- cl_int cl_error = clFinish(s);
- GMX_RELEASE_ASSERT(CL_SUCCESS == cl_error,
- ("Error caught during clFinish:" + ocl_get_error_string(cl_error)).c_str());
-}
-
//! A debug checker to track cl_events being released correctly
inline void ensureReferenceCount(const cl_event& event, unsigned int refCount)
{
/*! \brief Pretend to synchronize an OpenCL stream (dummy implementation).
*
- * \param[in] s queue to check
- *
- * \returns True if all tasks enqueued in the stream \p s (at the time of this call) have completed.
+ * \returns Not implemented in OpenCL.
*/
-static inline bool haveStreamTasksCompleted(cl_command_queue gmx_unused s)
+static inline bool haveStreamTasksCompleted(const DeviceStream& /* deviceStream */)
{
GMX_RELEASE_ASSERT(false, "haveStreamTasksCompleted is not implemented for OpenCL");
return false;
*
* \param[in] kernel Kernel function handle
* \param[in] config Kernel configuration for launching
+ * \param[in] deviceStream GPU stream to launch kernel in
* \param[in] timingEvent Timing event, fetched from GpuRegionTimer
* \param[in] kernelName Human readable kernel description, for error handling only
* \throws gmx::InternalError on kernel launch failure
*/
inline void launchGpuKernel(cl_kernel kernel,
const KernelLaunchConfig& config,
+ const DeviceStream& deviceStream,
CommandEvent* timingEvent,
const char* kernelName,
const void* /*kernelArgs*/)
{
globalWorkSize[i] = config.gridSize[i] * config.blockSize[i];
}
- cl_int clError = clEnqueueNDRangeKernel(config.stream, kernel, workDimensions, globalWorkOffset,
- globalWorkSize, config.blockSize, waitListSize,
- waitList, timingEvent);
+ cl_int clError = clEnqueueNDRangeKernel(deviceStream.stream(), kernel, workDimensions,
+ globalWorkOffset, globalWorkSize, config.blockSize,
+ waitListSize, waitList, timingEvent);
if (CL_SUCCESS != clError)
{
const std::string errorMessage = "GPU kernel (" + std::string(kernelName)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# different files and strategies for the different GPU implementation
# flavours.
-# Always compiled as plain C++
-file(GLOB SOURCES_FROM_CXX
- clfftinitializer.cpp
- hostallocator.cpp
- )
+gmx_add_unit_test(GpuUtilsUnitTests gpu_utils-test
+ CPP_SOURCE_FILES
+ # Infrastructure
+ gputest.cpp
+ # Tests of code
+ clfftinitializer.cpp
+ hostallocator.cpp
-if(GMX_USE_CUDA)
- # CUDA-only test
- list(APPEND SOURCES_FROM_CXX
- pinnedmemorychecker.cpp
- )
- # TODO Making a separate library is heavy handed, but nothing else
- # seems to work. Also don't use a hyphen in its name, because nvcc
- # can't cope with that.
- #
- # Perhaps FindCUDA's support for single compilation units will help?
- if (NOT GMX_CLANG_CUDA)
- # Work around FindCUDA that prevents using target_link_libraries()
- # with keywords otherwise...
- set(CUDA_LIBRARIES PRIVATE ${CUDA_LIBRARIES})
- cuda_add_library(gpu_utilstest_cuda
- devicetransfers.cu
- )
- else()
- include(gmxClangCudaUtils)
- gmx_compile_cuda_file_with_clang(devicetransfers.cu)
- add_library(gpu_utilstest_cuda
- devicetransfers.cu
- )
- endif()
+ CUDA_CU_SOURCE_FILES
+ devicetransfers.cu
+ typecasts_runner.cu
- target_link_libraries(gpu_utilstest_cuda PRIVATE ${GMX_EXTRA_LIBRARIES} libgromacs)
+ CUDA_CPP_SOURCE_FILES
+ device_stream_manager.cpp
+ pinnedmemorychecker.cpp
+ typecasts.cpp
+ typecasts_runner.cpp
-elseif(GMX_USE_OPENCL)
- # Do normal compilation of OpenCL files
- list(APPEND SOURCES_FROM_CXX
+ OPENCL_CPP_SOURCE_FILES
devicetransfers_ocl.cpp
- )
-else()
- # Do normal compilation of files with null implementations
- list(APPEND SOURCES_FROM_CXX
- devicetransfers.cpp
- )
-endif()
-gmx_add_unit_test(GpuUtilsUnitTests gpu_utils-test
- # Infrastructure
- gputest.cpp
- # Tests of code
- ${SOURCES_FROM_CXX}
+ NON_GPU_CPP_SOURCE_FILES
+ device_stream_manager.cpp
+ devicetransfers.cpp
)
-
-if(GMX_USE_CUDA)
- target_link_libraries(gpu_utils-test PRIVATE gpu_utilstest_cuda)
-endif()
-if(GMX_USE_OPENCL)
- target_link_libraries(gpu_utils-test PRIVATE ${OpenCL_LIBRARIES})
-endif()
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief Tests GPU stream manager
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_gpu_utils
+ */
+#include "gmxpre.h"
+
+#include "gromacs/gpu_utils/device_stream_manager.h"
+
+#include "config.h"
+
+#include <initializer_list>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/utility/enumerationhelpers.h"
+
+#include "gputest.h"
+
+namespace gmx
+{
+
+namespace test
+{
+
+namespace
+{
+
+//! GPU device stream names for outputs.
+const EnumerationArray<DeviceStreamType, std::string> c_deviceStreamNames = {
+ { "non-bonded local", "non-bonded non-local", "PME", "PME-PP transfer", "update" }
+};
+
+/*! \brief Non-GPU builds return nullptr instead of streams,
+ * so we have to expect that in such build configurations. */
+const bool c_canExpectValidStreams = (GMX_GPU != GMX_GPU_NONE);
+
+//! Helper function to implement readable testing
+void expectValidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
+{
+ if (c_canExpectValidStreams)
+ {
+ for (const DeviceStreamType type : types)
+ {
+ SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
+ EXPECT_TRUE(manager->streamIsValid(type));
+ }
+ }
+}
+//! Helper function to implement readable testing
+void expectInvalidStreams(DeviceStreamManager* manager, std::initializer_list<DeviceStreamType> types)
+{
+ for (const DeviceStreamType type : types)
+ {
+ SCOPED_TRACE("Testing " + c_deviceStreamNames[type] + " stream.");
+ EXPECT_FALSE(manager->streamIsValid(type));
+ }
+}
+
+//! Test fixture
+class DeviceStreamManagerTest : public GpuTest
+{
+public:
+};
+
+TEST_F(DeviceStreamManagerTest, CorrectStreamsAreReturnedOnNonbondedDevice)
+{
+ // It would be nice to test that the priority is high when it can
+ // be, but that requires calling the same API calls we're testing
+ // that we've called, so it is not very useful.
+ const bool useTiming = false;
+
+ // TODO Is it enough to only test one device?
+ for (const auto* deviceInfo : getDeviceInfos())
+ {
+ EXPECT_FALSE(deviceInfo == nullptr)
+ << "Device information should be provided for the GPU builds.";
+ // Test all the different cases successively.
+
+ {
+ SCOPED_TRACE("No DD, no PME rank, no GPU update");
+ bool useGpuForPme = false;
+ bool havePpDomainDecomposition = false;
+ bool doGpuPmePpTransfer = false;
+ bool useGpuForUpdate = false;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal });
+ expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal,
+ DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ }
+
+ {
+ SCOPED_TRACE("With DD, no PME rank, no GPU update");
+ bool useGpuForPme = false;
+ bool havePpDomainDecomposition = true;
+ bool doGpuPmePpTransfer = false;
+ bool useGpuForUpdate = false;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::NonBondedNonLocal });
+ expectInvalidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ }
+
+ {
+ SCOPED_TRACE("No DD, with PME rank, no GPU update");
+ bool useGpuForPme = true;
+ bool havePpDomainDecomposition = false;
+ bool doGpuPmePpTransfer = true;
+ bool useGpuForUpdate = false;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal });
+ }
+
+ {
+ SCOPED_TRACE("With DD, with PME rank, no GPU update");
+ bool useGpuForPme = true;
+ bool havePpDomainDecomposition = true;
+ bool doGpuPmePpTransfer = true;
+ bool useGpuForUpdate = false;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ }
+
+ {
+ SCOPED_TRACE("No DD, no PME rank, with GPU update");
+ bool useGpuForPme = false;
+ bool havePpDomainDecomposition = false;
+ bool doGpuPmePpTransfer = false;
+ bool useGpuForUpdate = true;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::UpdateAndConstraints });
+ expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal,
+ DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer });
+ }
+
+ {
+ SCOPED_TRACE("With DD, no PME rank, with GPU update");
+ bool useGpuForPme = false;
+ bool havePpDomainDecomposition = true;
+ bool doGpuPmePpTransfer = false;
+ bool useGpuForUpdate = true;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::NonBondedLocal, DeviceStreamType::NonBondedNonLocal,
+ DeviceStreamType::UpdateAndConstraints });
+ expectInvalidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::PmePpTransfer });
+ }
+
+ {
+ SCOPED_TRACE("No DD, with PME rank, with GPU update");
+ bool useGpuForPme = true;
+ bool havePpDomainDecomposition = false;
+ bool doGpuPmePpTransfer = true;
+ bool useGpuForUpdate = true;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ expectInvalidStreams(&manager, { DeviceStreamType::NonBondedNonLocal });
+ }
+
+ {
+ SCOPED_TRACE("With DD, with PME rank, with GPU update");
+ bool useGpuForPme = true;
+ bool havePpDomainDecomposition = true;
+ bool doGpuPmePpTransfer = true;
+ bool useGpuForUpdate = true;
+ DeviceStreamManager manager(*deviceInfo, useGpuForPme, havePpDomainDecomposition,
+ doGpuPmePpTransfer, useGpuForUpdate, useTiming);
+
+ expectValidStreams(&manager, { DeviceStreamType::Pme, DeviceStreamType::NonBondedLocal,
+ DeviceStreamType::NonBondedNonLocal, DeviceStreamType::PmePpTransfer,
+ DeviceStreamType::UpdateAndConstraints });
+ }
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const auto* device = getDeviceInfo(gpuInfo, compatibleGpus[0]);
cl_context_properties properties[] = {
- CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(device->ocl_gpu_id.ocl_platform_id), 0
+ CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(device->oclPlatformId), 0
};
// Give uncrustify more space
- auto deviceId = device->ocl_gpu_id.ocl_device_id;
+ auto deviceId = device->oclDeviceId;
auto context = clCreateContext(properties, 1, &deviceId, nullptr, nullptr, &status);
throwUponFailure(status, "creating context");
auto commandQueue = clCreateCommandQueue(context, deviceId, 0, &status);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
if (isGpuDetectionFunctional(nullptr))
{
findGpus(gpuInfo_);
+ compatibleGpuIds_ = getCompatibleGpus(*gpuInfo_);
}
// Failing to find valid GPUs does not require further action
}
sfree(gpuInfo_);
}
-bool GpuTest::haveValidGpus() const
+bool GpuTest::haveCompatibleGpus() const
{
- return gpuInfo_->n_dev_compatible > 0;
+ return !compatibleGpuIds_.empty();
+}
+
+std::vector<const DeviceInformation*> GpuTest::getDeviceInfos() const
+{
+ std::vector<const DeviceInformation*> deviceInfos;
+ deviceInfos.reserve(compatibleGpuIds_.size());
+ for (const auto& id : compatibleGpuIds_)
+ {
+ deviceInfos.emplace_back(getDeviceInfo(*gpuInfo_, id));
+ }
+ return deviceInfos;
}
} // namespace test
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <gtest/gtest.h>
+struct DeviceInformation;
struct gmx_gpu_info_t;
namespace gmx
public:
//! Information about GPUs that are present.
gmx_gpu_info_t* gpuInfo_;
+ //! Contains the IDs of all compatible GPUs
+ std::vector<int> compatibleGpuIds_;
GpuTest();
~GpuTest() override;
- //! Getter for convenience in testing
- bool haveValidGpus() const;
+ //! Return whether compatible GPUs were found
+ bool haveCompatibleGpus() const;
+ //! Return a vector of handles, each to a device info for a compatible GPU.
+ std::vector<const DeviceInformation*> getDeviceInfos() const;
};
} // namespace test
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
TYPED_TEST(HostAllocatorTestCopyable, TransfersWithPinningWorkWithCuda)
{
- if (!this->haveValidGpus())
+ if (!this->haveCompatibleGpus())
{
return;
}
TYPED_TEST(HostAllocatorTestCopyable, ManualPinningOperationsWorkWithCuda)
{
- if (!this->haveValidGpus())
+ if (!this->haveCompatibleGpus())
{
return;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
TEST_F(PinnedMemoryCheckerTest, DefaultContainerIsRecognized)
{
- if (!haveValidGpus())
+ if (!haveCompatibleGpus())
{
return;
}
TEST_F(PinnedMemoryCheckerTest, NonpinnedContainerIsRecognized)
{
- if (!haveValidGpus())
+ if (!haveCompatibleGpus())
{
return;
}
TEST_F(PinnedMemoryCheckerTest, PinnedContainerIsRecognized)
{
- if (!haveValidGpus())
+ if (!haveCompatibleGpus())
{
return;
}
TEST_F(PinnedMemoryCheckerTest, DefaultCBufferIsRecognized)
{
- if (!haveValidGpus())
+ if (!haveCompatibleGpus())
{
return;
}
TEST_F(PinnedMemoryCheckerTest, PinnedCBufferIsRecognized)
{
- if (!haveValidGpus())
+ if (!haveCompatibleGpus())
{
return;
}
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for CUDA float3 type layout.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ */
+#include "gmxpre.h"
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/gpu_utils/gpu_testutils.h"
+#include "gromacs/utility/exceptions.h"
+
+#include "testutils/testasserts.h"
+#include "testutils/testmatchers.h"
+
+#include "typecasts_runner.h"
+
+namespace gmx
+{
+
+namespace test
+{
+
+//! Test data in RVec format
+static const std::vector<RVec> rVecInput = { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } };
+
+TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3OnHost)
+{
+ std::vector<RVec> rVecOutput(rVecInput.size());
+ convertRVecToFloat3OnHost(rVecOutput, rVecInput);
+ EXPECT_THAT(rVecInput, testing::Pointwise(RVecEq(ulpTolerance(0)), rVecOutput));
+}
+
+TEST(GpuDataTypesCompatibilityTest, RVecAndFloat3OnDevice)
+{
+ if (canComputeOnGpu())
+ {
+ std::vector<RVec> rVecOutput(rVecInput.size());
+ convertRVecToFloat3OnDevice(rVecOutput, rVecInput);
+ EXPECT_THAT(rVecInput, testing::Pointwise(RVecEq(ulpTolerance(0)), rVecOutput));
+ }
+}
+
+} // namespace test
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-/*! \libinternal \file
- * \brief Provides C++14-compatible implementation of std::optional.
+/*! \internal \file
+ * \brief
+ * Stub for runners for tests types compatibility.
*
- * This imports the implementation found in src/external from
- * https://github.com/martinmoene/optional-lite.git.
- *
- * There is no Doxygen for this code, but it is intended to conform to
- * that of std::optional, so look in the usual C++17 documentation for
- * std::optional for that.
- *
- * \todo Remove when requiring C++17, which has a standardized version
- * of std::optional.
- *
- * \author Mark Abraham <mark.j.abraham@gmail.com>
- * \ingroup module_compat
- * \inlibraryapi
+ * \author Artem Zhmurov <zhmurov@gmail.com>
*/
-#ifndef GMX_COMPAT_OPTIONAL_H
-#define GMX_COMPAT_OPTIONAL_H
+#include "gmxpre.h"
+
+#include "typecasts_runner.h"
+
+#include "config.h"
+
+#include <vector>
-#include <nonstd/optional.hpp>
+#include "testutils/testasserts.h"
+
+#if GMX_GPU != GMX_GPU_CUDA
namespace gmx
{
-namespace compat
+
+namespace test
{
-using nonstd::bad_optional_access;
-using nonstd::in_place;
-using nonstd::make_optional;
-using nonstd::nullopt;
-using nonstd::optional;
+void convertRVecToFloat3OnHost(std::vector<gmx::RVec>& /* rVecOutput */,
+ const std::vector<gmx::RVec>& /* rVecInput */)
+{
+ FAIL() << "Can't test float3 and RVec compatibility without CUDA.";
+}
+
+void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& /* rVecOutput */,
+ const std::vector<gmx::RVec>& /* rVecInput*/)
+{
+ FAIL() << "Can't test float3 and RVec compatibility without CUDA.";
+}
-} // namespace compat
+} // namespace test
} // namespace gmx
-#endif
+#endif // GMX_GPU != GMX_GPU_CUDA
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Runners for tests of CUDA types compatibility.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ */
+#include "gmxpre.h"
+
+#include "typecasts_runner.h"
+
+#include "config.h"
+
+#include <vector>
+
+#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/devicebuffer.h"
+#include "gromacs/gpu_utils/typecasts.cuh"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/stringutil.h"
+
+#if GMX_GPU == GMX_GPU_CUDA
+
+namespace gmx
+{
+
+namespace test
+{
+
+/* \brief Perform a component-wise conversion of the float3 vector back to RVec format.
+ *
+ * This is needed to pass the data back to the CPU testing code for comparison with the initial input.
+ *
+ * \param[out] rVecOutput Output data in RVec format for the output.
+ * \param[in] float3Output Output data in float3 format.
+ * \param[in] numElements Size of the data buffers.
+ */
+void inline saveFloat3InRVecFormat(std::vector<gmx::RVec>& rVecOutput, const float3* float3Output, int numElements)
+{
+ for (int i = 0; i < numElements; i++)
+ {
+ rVecOutput[i][XX] = float3Output[i].x;
+ rVecOutput[i][YY] = float3Output[i].y;
+ rVecOutput[i][ZZ] = float3Output[i].z;
+ }
+}
+
+void convertRVecToFloat3OnHost(std::vector<gmx::RVec>& rVecOutput, const std::vector<gmx::RVec>& rVecInput)
+{
+ const int numElements = rVecInput.size();
+
+ float3* dataFloat3 = asFloat3(const_cast<RVec*>(rVecInput.data()));
+
+ saveFloat3InRVecFormat(rVecOutput, dataFloat3, numElements);
+}
+
+//! Number of CUDA threads in a block.
+constexpr static int c_threadsPerBlock = 256;
+
+/*! \brief GPU kernel to perform type conversion on the device.
+ *
+ * \param[out] gm_float3Output Buffer to write the output into.
+ * \param[in] gm_rVecInput Input data in RVec format.
+ * \param[in] size Size of the data buffers.
+ *
+ */
+static __global__ void convertRVecToFloat3OnDevice_kernel(DeviceBuffer<float3> gm_float3Output,
+ DeviceBuffer<RVec> gm_rVecInput,
+ const int size)
+{
+ int threadIndex = blockIdx.x * blockDim.x + threadIdx.x;
+ if (threadIndex < size)
+ {
+ gm_float3Output[threadIndex] = asFloat3(gm_rVecInput)[threadIndex];
+ }
+}
+
+void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& h_rVecOutput, const std::vector<gmx::RVec>& h_rVecInput)
+{
+ DeviceInformation deviceInfo;
+ const DeviceContext deviceContext(deviceInfo);
+ const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+
+ const int numElements = h_rVecInput.size();
+
+ DeviceBuffer<RVec> d_rVecInput;
+ allocateDeviceBuffer(&d_rVecInput, numElements, deviceContext);
+ copyToDeviceBuffer(&d_rVecInput, h_rVecInput.data(), 0, numElements, deviceStream,
+ GpuApiCallBehavior::Sync, nullptr);
+
+ DeviceBuffer<float3> d_float3Output;
+ allocateDeviceBuffer(&d_float3Output, numElements * DIM, deviceContext);
+
+ std::vector<float3> h_float3Output(numElements);
+
+ KernelLaunchConfig kernelLaunchConfig;
+ kernelLaunchConfig.gridSize[0] = (numElements + c_threadsPerBlock - 1) / c_threadsPerBlock;
+ kernelLaunchConfig.blockSize[0] = c_threadsPerBlock;
+ kernelLaunchConfig.blockSize[1] = 1;
+ kernelLaunchConfig.blockSize[2] = 1;
+ kernelLaunchConfig.sharedMemorySize = 0;
+
+ auto kernelPtr = convertRVecToFloat3OnDevice_kernel;
+ const auto kernelArgs = prepareGpuKernelArguments(kernelPtr, kernelLaunchConfig,
+ &d_float3Output, &d_rVecInput, &numElements);
+ launchGpuKernel(kernelPtr, kernelLaunchConfig, deviceStream, nullptr,
+ "convertRVecToFloat3OnDevice_kernel", kernelArgs);
+
+ copyFromDeviceBuffer(h_float3Output.data(), &d_float3Output, 0, numElements, deviceStream,
+ GpuApiCallBehavior::Sync, nullptr);
+
+ saveFloat3InRVecFormat(h_rVecOutput, h_float3Output.data(), numElements);
+
+ freeDeviceBuffer(&d_rVecInput);
+ freeDeviceBuffer(&d_float3Output);
+}
+
+} // namespace test
+} // namespace gmx
+
+#endif // GMX_GPU == GMX_GPU_CUDA
\ No newline at end of file
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#ifndef GMX_MDLIB_QMGAUSSIAN_H
-#define GMX_MDLIB_QMGAUSSIAN_H
+/*! \internal \file
+ * \brief
+ * Header for runner for CUDA float3 type layout tests.
+ *
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ */
+#ifndef GMX_GPU_UTILS_TESTS_TYPECASTS_RUNNER_H
+#define GMX_GPU_UTILS_TESTS_TYPECASTS_RUNNER_H
+
+#include "gmxpre.h"
+
+#include <vector>
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdlib/qmmm.h"
-struct t_forcerec;
+namespace gmx
+{
-/*! \brief
- * Initialize gaussian datastructures.
- *
- * \param[in] qm QM forcerec.
- */
-void init_gaussian(t_QMrec* qm);
+namespace test
+{
-/*! \brief
- * Call gaussian to do qm calculation.
+/*! \brief Tests the compatibility of RVec and float3 using the conversion on host.
*
- * \param[in] fr Global forcerec.
- * \param[in] qm QM part of forcerec.
- * \param[in] mm mm part of forcerec.
- * \param[in] f force vector.
- * \param[in] fshift shift of force vector.
+ * \param[out] rVecOutput Data in RVec format for the output.
+ * \param[in] rVecInput Data in RVec format with the input.
*/
-real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+void convertRVecToFloat3OnHost(std::vector<gmx::RVec>& rVecOutput, const std::vector<gmx::RVec>& rVecInput);
-/*! \brief
- * Call gaussian SH(?) to do qm calculation.
+/*! \brief Tests the compatibility of RVec and float3 using the conversion on device.
*
- * \param[in] fr Global forcerec.
- * \param[in] qm QM part of forcerec.
- * \param[in] mm mm part of forcerec.
- * \param[in] f force vector.
- * \param[in] fshift shift of force vector.
+ * \param[out] rVecOutput Data in RVec format for the output.
+ * \param[in] rVecInput Data in RVec format with the input.
*/
-real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+void convertRVecToFloat3OnDevice(std::vector<gmx::RVec>& rVecOutput, const std::vector<gmx::RVec>& rVecInput);
+
+} // namespace test
+} // namespace gmx
-#endif
+#endif // GMX_GPU_UTILS_TESTS_TYPECASTS_RUNNER_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* the research papers on the package. Check out http://www.gromacs.org.
*/
/*! \libinternal \file
- * \brief Sets gmx_nbnxn_gpu_t to the correct type depending on the build
+ * \brief Declare functions to be used to cast CPU types to compatible GPU types.
*
- * \ingroup module_nbnxm
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \inlibraryapi
*/
+#ifndef GMX_GPU_UTILS_TYPECASTS_CUH
+#define GMX_GPU_UTILS_TYPECASTS_CUH
-#ifndef GMX_NBNXN_GPU_TYPES_H
-#define GMX_NBNXN_GPU_TYPES_H
-
-#include "config.h"
-
-#ifndef DOXYGEN
-
-# if GMX_GPU == GMX_GPU_OPENCL
-struct gmx_nbnxn_ocl_t;
-using gmx_nbnxn_gpu_t = gmx_nbnxn_ocl_t;
-# endif
-
-# if GMX_GPU == GMX_GPU_CUDA
-struct gmx_nbnxn_cuda_t;
-using gmx_nbnxn_gpu_t = gmx_nbnxn_cuda_t;
-# endif
+#include "gmxpre.h"
-# if GMX_GPU == GMX_GPU_NONE
-using gmx_nbnxn_gpu_t = int;
-# endif
+#include "gromacs/math/vectypes.h"
-#endif // !DOXYGEN
-
-#endif
+/*! \brief Cast RVec buffer to float3 buffer.
+ *
+ * \param[in] in The RVec buffer to cast.
+ *
+ * \returns Buffer, casted to float3*.
+ */
+static inline __host__ __device__ float3* asFloat3(gmx::RVec* in)
+{
+ static_assert(sizeof(in[0]) == sizeof(float3),
+ "Size of the host-side data-type is different from the size of the device-side "
+ "counterpart.");
+ return reinterpret_cast<float3*>(in);
+}
+
+#endif // GMX_GPU_UTILS_TYPECASTS_CUH
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return norm(b - a);
}
+/* \brief Compute the scalar product of two vectors.
+ *
+ * \param[in] a First vector.
+ * \param[in] b Second vector.
+ * \returns Scalar product.
+ */
+__forceinline__ __device__ float iprod(const float3 a, const float3 b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+/* \brief Compute the vector product of two vectors.
+ *
+ * \param[in] a First vector.
+ * \param[in] b Second vector.
+ * \returns Vector product.
+ */
+__forceinline__ __device__ float3 cprod(const float3 a, const float3 b)
+{
+ float3 c;
+ c.x = a.y * b.z - a.z * b.y;
+ c.y = a.z * b.x - a.x * b.z;
+ c.z = a.x * b.y - a.y * b.x;
+ return c;
+}
+
+/* \brief Cosine of an angle between two vectors.
+ *
+ * Computes cosine using the following formula:
+ *
+ * ax*bx + ay*by + az*bz
+ * cos-vec (a,b) = ---------------------
+ * ||a|| * ||b||
+ *
+ * This function also makes sure that the cosine does not leave the [-1, 1]
+ * interval, which can happen due to numerical errors.
+ *
+ * \param[in] a First vector.
+ * \param[in] b Second vector.
+ * \returns Cosine between a and b.
+ */
+__forceinline__ __device__ float cos_angle(const float3 a, const float3 b)
+{
+ float cosval;
+
+ float ipa = norm2(a);
+ float ipb = norm2(b);
+ float ip = iprod(a, b);
+ float ipab = ipa * ipb;
+ if (ipab > 0.0f)
+ {
+ cosval = ip * rsqrt(ipab);
+ }
+ else
+ {
+ cosval = 1.0f;
+ }
+ if (cosval > 1.0f)
+ {
+ return 1.0f;
+ }
+ if (cosval < -1.0f)
+ {
+ return -1.0f;
+ }
+
+ return cosval;
+}
+
+/* \brief Compute the angle between two vectors.
+ *
+ * Uses atan( |axb| / a.b ) formula.
+ *
+ * \param[in] a First vector.
+ * \param[in] b Second vector.
+ * \returns Angle between vectors in radians.
+ */
+__forceinline__ __device__ float gmx_angle(const float3 a, const float3 b)
+{
+ float3 w = cprod(a, b);
+
+ float wlen = norm(w);
+ float s = iprod(a, b);
+
+ return atan2f(wlen, s); // requires float
+}
+
+/* \brief Atomically add components of the vector.
+ *
+ * Executes atomicAdd one-by-one on all components of the float3 vector.
+ *
+ * \param[in] a First vector.
+ * \param[in] b Second vector.
+ * \returns Angle between vectors.
+ */
+__forceinline__ __device__ void atomicAdd(float3& a, const float3 b)
+{
+ atomicAdd(&a.x, b.x);
+ atomicAdd(&a.y, b.y);
+ atomicAdd(&a.z, b.z);
+}
+
#endif /* VECTYPE_OPS_CUH */
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2016,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
include(${_gmx_import_file})
unset(_gmx_import_file)
-get_target_property(_libs libgromacs INTERFACE_LINK_LIBRARIES)
+get_target_property(_libs Gromacs::libgromacs INTERFACE_LINK_LIBRARIES)
if (_libs MATCHES "tng_io::tng_io")
include(CMakeFindDependencyMacro)
- find_dependency(TNG_IO)
+ find_dependency(TNG_IO REQUIRED)
+endif()
+if (_libs MATCHES "OpenMP::OpenMP_CXX")
+ include(CMakeFindDependencyMacro)
+ find_dependency(OpenMP REQUIRED)
endif()
unset(_libs)
list(APPEND GROMACS_INCLUDE_DIRS ${_gmx_root_dir}/${_dir})
endif()
endforeach()
-set(GROMACS_LIBRARIES libgromacs)
+set(GROMACS_LIBRARIES Gromacs::libgromacs)
set(GROMACS_DEFINITIONS @INSTALLED_HEADER_DEFINITIONS@)
set(GROMACS_IS_DOUBLE @GMX_DOUBLE@)
if (DEFINED GROMACS_SUFFIX AND NOT "${GROMACS_SUFFIX}" STREQUAL "@GMX_LIBS_SUFFIX@")
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
if (!isMasterRankOfPhysicalNode)
{
- hardwareInfo->gpu_info.gpu_dev = (struct gmx_device_info_t*)malloc(dev_size);
+ hardwareInfo->gpu_info.deviceInfo = (struct DeviceInformation*)malloc(dev_size);
}
- MPI_Bcast(hardwareInfo->gpu_info.gpu_dev, dev_size, MPI_BYTE, 0, physicalNodeComm.comm_);
+ MPI_Bcast(hardwareInfo->gpu_info.deviceInfo, dev_size, MPI_BYTE, 0, physicalNodeComm.comm_);
MPI_Bcast(&hardwareInfo->gpu_info.n_dev_compatible, 1, MPI_INT, 0, physicalNodeComm.comm_);
}
}
// Detect GPUs
hardwareInfo->gpu_info.n_dev = 0;
hardwareInfo->gpu_info.n_dev_compatible = 0;
- hardwareInfo->gpu_info.gpu_dev = nullptr;
+ hardwareInfo->gpu_info.deviceInfo = nullptr;
gmx_detect_gpus(mdlog, physicalNodeComm, compat::make_not_null(hardwareInfo));
gmx_collect_hardware_mpi(*hardwareInfo->cpuInfo, physicalNodeComm, compat::make_not_null(hardwareInfo));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
-struct gmx_device_info_t;
+struct DeviceInformation;
/*! \brief Possible results of the GPU detection/check.
*
//! Total number of GPU devices detected on this physical node
int n_dev;
//! Information about each GPU device detected on this physical node
- gmx_device_info_t* gpu_dev;
+ DeviceInformation* deviceInfo;
//! Number of GPU devices detected on this physical node that are compatible.
int n_dev_compatible;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2015, by the GROMACS development team, led by
+# Copyright (c) 2015,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(HardwareUnitTests hardware-test
- cpuinfo.cpp
- hardwaretopology.cpp)
+ CPP_SOURCE_FILES
+ cpuinfo.cpp
+ hardwaretopology.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/stat.h"
#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/multisim.h"
+#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/imdmodule.h"
#include "gromacs/mdtypes/inputrec.h"
IMdpOptionProvider* mdpOptionProvider() override { return nullptr; }
IMDOutputProvider* outputProvider() override { return nullptr; }
void initForceProviders(ForceProviders* /* forceProviders */) override {}
+ void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
};
std::unique_ptr<IMDModule> createInteractiveMolecularDynamicsModule()
if (bIMD)
{
IMDatoms = gmx_mtop_global_atoms(sys);
- write_sto_conf_indexed(opt2fn("-imd", nfile, fnm), "IMDgroup", &IMDatoms, state->x.rvec_array(),
- state->v.rvec_array(), ir->ePBC, state->box, ir->imd->nat, ir->imd->ind);
+ write_sto_conf_indexed(opt2fn("-imd", nfile, fnm), "IMDgroup", &IMDatoms,
+ state->x.rvec_array(), state->v.rvec_array(), ir->pbcType,
+ state->box, ir->imd->nat, ir->imd->ind);
}
}
/* Notify the other nodes whether we are still connected. */
if (PAR(cr))
{
- block_bc(cr, bConnected);
+ block_bc(cr->mpi_comm_mygroup, bConnected);
}
/* ...if not connected, the job is done here. */
/* Let the other nodes know whether we got a new IMD synchronization frequency. */
if (PAR(cr))
{
- block_bc(cr, nstimd_new);
+ block_bc(cr->mpi_comm_mygroup, nstimd_new);
}
/* Now we all set the (new) nstimd communication time step */
/* make new_forces known to the clients */
if (PAR(cr))
{
- block_bc(cr, new_nforces);
+ block_bc(cr->mpi_comm_mygroup, new_nforces);
}
/* When new_natoms < 0 then we know that these are still the same forces
/* In parallel mode we communicate the to-be-applied forces to the other nodes */
if (PAR(cr))
{
- nblock_bc(cr, nforces, f_ind);
- nblock_bc(cr, nforces, f);
+ nblock_bc(cr->mpi_comm_mygroup, nforces, f_ind);
+ nblock_bc(cr->mpi_comm_mygroup, nforces, f);
}
/* done communicating the forces, reset bNewForces */
/* Communicate initial coordinates xa_old to all processes */
if (PAR(cr))
{
- gmx_bcast(nat * sizeof(xa_old[0]), xa_old, cr);
+ gmx_bcast(nat * sizeof(xa_old[0]), xa_old, cr->mpi_comm_mygroup);
}
}
/* Let the other nodes know whether we want IMD */
if (PAR(cr))
{
- block_bc(cr, createSession);
+ block_bc(cr->mpi_comm_mygroup, createSession);
}
/*... if not we are done.*/
/* do we allow interactive pulling? If so let the other nodes know. */
if (PAR(cr))
{
- block_bc(cr, impl->bForceActivated);
+ block_bc(cr->mpi_comm_mygroup, impl->bForceActivated);
}
/* setup the listening socket on master process */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2004 David van der Spoel, Erik Lindahl, University of Groningen.
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/fcdata.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/pbc_simd.h"
#include "gromacs/simd/simd.h"
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
/*! \brief Spreads and accumulates the bonded forces to the two atoms and adds the virial contribution when needed
*
- * When \p g==nullptr, \p shiftIndex is used as the periodic shift.
- * When \p g!=nullptr, the graph is used to compute the periodic shift.
+ * \p shiftIndex is used as the periodic shift.
*/
template<BondedKernelFlavor flavor>
-inline void spreadBondForces(const real bondForce,
- const rvec dx,
- const int ai,
- const int aj,
- rvec4* f,
- int shiftIndex,
- const t_graph* g,
- rvec* fshift)
+inline void spreadBondForces(const real bondForce,
+ const rvec dx,
+ const int ai,
+ const int aj,
+ rvec4* f,
+ int shiftIndex,
+ rvec* fshift)
{
- if (computeVirial(flavor) && g)
- {
- ivec dt;
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
- shiftIndex = IVEC2IS(dt);
- }
-
for (int m = 0; m < DIM; m++) /* 15 */
{
const real fij = bondForce * dx[m];
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
*dvdlambda += (cbB - cbA) * omtemp * omtemp
- (2 - 2 * omtemp) * omtemp * cb * ((b0B - b0A) * be - (beB - beA) * (dr - b0)); /* 15 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 83 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 83 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += vbond; /* 21 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 54 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 54 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += vbond; /* 35 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 58 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 58 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += vbond; /* 1*/
fbond *= gmx::invsqrt(dr2); /* 6 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 59 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 59 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += vbond; /* 1*/
fbond *= gmx::invsqrt(dr2); /* 6 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 59 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 59 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
vtot += vbond; /* 1*/
fbond *= gmx::invsqrt(dr2); /* 6 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 59 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 59 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
fbond *= gmx::invsqrt(dr2); /* 6 */
vtot += vbond; /* 1*/
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 72 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 72 TOTAL */
return vtot;
}
rvec4 f[],
rvec gmx_unused fshift[],
const t_pbc gmx_unused* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
* three spatial dimensions in the molecular frame.
*/
int i, m, aO, aH1, aH2, aD, aS, type, type0, ki;
- ivec dt;
rvec dOH1, dOH2, dHH, dOD, dDS, nW, kk, dx, kdx, proj;
real vtot, fij, r_HH, r_OD, r_nW, tx, ty, tz, qS;
kdx[ZZ] = kk[ZZ] * dx[ZZ];
vtot += iprod(dx, kdx);
- if (computeVirial(flavor) && g)
- {
- ivec_sub(SHIFT_IVEC(g, aS), SHIFT_IVEC(g, aD), dt);
- ki = IVEC2IS(dt);
- }
-
for (m = 0; (m < DIM); m++)
{
/* This is a tensor operation but written out for speed */
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms* md,
return V;
}
-// Avoid gcc 386 -O3 code generation bug in this function (see Redmine
+// Avoid gcc 386 -O3 code generation bug in this function (see Issue
// #3205 for more information)
#if defined(__GNUC__) && defined(__i386__) && defined(__OPTIMIZE__)
# pragma GCC push_options
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
int i, ai, aj, ak, t1, t2, type;
rvec r_ij, r_kj;
real cos_theta, cos_theta2, theta, dVdt, va, vtot;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; i < nbonds;)
}
if (computeVirial(flavor))
{
- if (g != nullptr)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
rvec4 f[],
rvec gmx_unused fshift[],
const t_pbc* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
int i, m, ai, aj, ak, t1, t2, type;
rvec f_i, f_j, f_k;
real L1, kA, kB, aA, aB, dr, dr2, va, vtot, a, b, klin;
- ivec jt, dt_ij, dt_kj;
rvec r_ij, r_kj, r_ik, dx;
L1 = 1 - lambda;
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
real cos_theta, cos_theta2, theta;
real dVdt, va, vtot, dr, dr2, vbond, fbond, fik;
real kthA, th0A, kUBA, r13A, kthB, th0B, kUBB, r13B;
- ivec jt, dt_ij, dt_kj, dt_ik;
vtot = 0.0;
for (i = 0; (i < nbonds);)
}
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
vtot += vbond; /* 1*/
fbond *= gmx::invsqrt(dr2); /* 6 */
- if (computeVirial(flavor) && g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ak), dt_ik);
- ki = IVEC2IS(dt_ik);
- }
for (m = 0; (m < DIM); m++) /* 15 */
{
fik = fbond * r_ik[m];
rvec4 f[],
rvec gmx_unused fshift[],
const t_pbc* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
int i, j, ai, aj, ak, t1, t2, type;
rvec r_ij, r_kj;
real cos_theta, cos_theta2, theta, dt, dVdt, va, dtp, c, vtot;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; (i < nbonds);)
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
} // namespace
template<BondedKernelFlavor flavor>
-void do_dih_fup(int i,
- int j,
- int k,
- int l,
- real ddphi,
- rvec r_ij,
- rvec r_kj,
- rvec r_kl,
- rvec m,
- rvec n,
- rvec4 f[],
- rvec fshift[],
- const t_pbc* pbc,
- const t_graph* g,
- const rvec x[],
- int t1,
- int t2,
- int t3)
+void do_dih_fup(int i,
+ int j,
+ int k,
+ int l,
+ real ddphi,
+ rvec r_ij,
+ rvec r_kj,
+ rvec r_kl,
+ rvec m,
+ rvec n,
+ rvec4 f[],
+ rvec fshift[],
+ const t_pbc* pbc,
+ const rvec x[],
+ int t1,
+ int t2,
+ int t3)
{
/* 143 FLOPS */
rvec f_i, f_j, f_k, f_l;
rvec uvec, vvec, svec, dx_jl;
real iprm, iprn, nrkj, nrkj2, nrkj_1, nrkj_2;
real a, b, p, q, toler;
- ivec jt, dt_ij, dt_kj, dt_lj;
iprm = iprod(m, m); /* 5 */
iprn = iprod(n, n); /* 5 */
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, j), jt);
- ivec_sub(SHIFT_IVEC(g, i), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, k), jt, dt_kj);
- ivec_sub(SHIFT_IVEC(g, l), jt, dt_lj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- t3 = IVEC2IS(dt_lj);
- }
- else if (pbc)
+ if (pbc)
{
t3 = pbc_rvec_sub(pbc, x[l], x[j], dx_jl);
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
} while (i < nbonds && forceatoms[i + 1] == ai && forceatoms[i + 2] == aj
&& forceatoms[i + 3] == ak && forceatoms[i + 4] == al);
- do_dih_fup<flavor>(ai, aj, ak, al, ddphi_tot, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, g, x,
- t1, t2, t3); /* 112 */
- } /* 223 TOTAL */
+ do_dih_fup<flavor>(ai, aj, ak, al, ddphi_tot, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, x, t1,
+ t2, t3); /* 112 */
+ } /* 223 TOTAL */
return vtot;
}
rvec4 f[],
rvec gmx_unused fshift[],
const t_pbc* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec4 f[],
rvec gmx_unused fshift[],
const t_pbc* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
dvdl_term += 0.5 * (kB - kA) * dp2 - kk * dphi0 * dp;
- do_dih_fup<flavor>(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, g, x, t1,
+ do_dih_fup<flavor>(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, x, t1,
t2, t3); /* 112 */
/* 218 TOTAL */
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
gmx_bool bZAxis)
rvec r_ij, r_kl, f_i, f_k = { 0, 0, 0 };
real st, sth, nrij2, nrkl2, c, cij, ckl;
- ivec dt;
t2 = 0; /* avoid warning with gcc-3.3. It is never used uninitialized */
vtot = 0.0;
if (computeVirial(flavor))
{
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
- t1 = IVEC2IS(dt);
- }
rvec_inc(fshift[t1], f_i);
rvec_dec(fshift[CENTRAL], f_i);
if (!bZAxis)
{
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, al), dt);
- t2 = IVEC2IS(dt);
- }
rvec_inc(fshift[t2], f_k);
rvec_dec(fshift[CENTRAL], f_k);
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
t_fcdata gmx_unused* fcd,
int gmx_unused* global_atom_index)
{
- return low_angres<flavor>(nbonds, forceatoms, forceparams, x, f, fshift, pbc, g, lambda,
- dvdlambda, FALSE);
+ return low_angres<flavor>(nbonds, forceatoms, forceparams, x, f, fshift, pbc, lambda, dvdlambda, FALSE);
}
template<BondedKernelFlavor flavor>
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
t_fcdata gmx_unused* fcd,
int gmx_unused* global_atom_index)
{
- return low_angres<flavor>(nbonds, forceatoms, forceparams, x, f, fshift, pbc, g, lambda,
- dvdlambda, TRUE);
+ return low_angres<flavor>(nbonds, forceatoms, forceparams, x, f, fshift, pbc, lambda, dvdlambda, TRUE);
}
template<BondedKernelFlavor flavor>
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
{
*dvdlambda += kfac * ddp * ((dphiB - dphiA) - (phi0B - phi0A));
}
- do_dih_fup<flavor>(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, g, x,
- t1, t2, t3); /* 112 */
+ do_dih_fup<flavor>(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, x, t1,
+ t2, t3); /* 112 */
}
}
return vtot;
rvec4 gmx_unused f[],
rvec gmx_unused fshift[],
const t_pbc gmx_unused* pbc,
- const t_graph gmx_unused* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
int i, d, ai, aj, ak, type, m;
int t1, t2;
real v, vtot;
- ivec jt, dt_ij, dt_kj;
rvec f_i, f_j, f_k;
double prefactor, ratio_ante, ratio_post;
rvec delta_ante, delta_post, vec_temp;
real restrangles(int nbonds,
const t_iatom forceatoms[],const t_iparams forceparams[],
const rvec x[],rvec4 f[],rvec fshift[],
- const t_pbc *pbc,const t_graph *g,
+ const t_pbc *pbc,
real gmx_unused lambda,real gmx_unused *dvdlambda,
const t_mdatoms gmx_unused *md,t_fcdata gmx_unused *fcd,
int gmx_unused *global_atom_index)
int t1, t2;
rvec r_ij,r_kj;
real v, vtot;
- ivec jt,dt_ij,dt_kj;
rvec f_i, f_j, f_k;
real prefactor, ratio_ante, ratio_post;
rvec delta_ante, delta_post, vec_temp;
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
-
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvlambda,
const t_mdatoms gmx_unused* md,
int i, d, type, ai, aj, ak, al;
rvec f_i, f_j, f_k, f_l;
rvec dx_jl;
- ivec jt, dt_ij, dt_kj, dt_lj;
int t1, t2, t3;
real v, vtot;
rvec delta_ante, delta_crnt, delta_post, vec_temp;
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- ivec_sub(SHIFT_IVEC(g, al), jt, dt_lj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- t3 = IVEC2IS(dt_lj);
- }
- else if (pbc)
+ if (pbc)
{
t3 = pbc_rvec_sub(pbc, x[al], x[aj], dx_jl);
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
real v, vtot;
rvec vec_temp;
rvec f_i, f_j, f_k, f_l;
- ivec jt, dt_ij, dt_kj, dt_lj;
rvec dx_jl;
rvec delta_ante, delta_crnt, delta_post;
rvec f_phi_ai, f_phi_aj, f_phi_ak, f_phi_al;
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- ivec_sub(SHIFT_IVEC(g, al), jt, dt_lj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- t3 = IVEC2IS(dt_lj);
- }
- else if (pbc)
+ if (pbc)
{
t3 = pbc_rvec_sub(pbc, x[al], x[aj], dx_jl);
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
ddphi = -ddphi * sin_phi; /* 11 */
- do_dih_fup<flavor>(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, g, x, t1,
- t2, t3); /* 112 */
+ do_dih_fup<flavor>(ai, aj, ak, al, ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, x, t1, t2,
+ t3); /* 112 */
vtot += v;
}
*dvdlambda += dvdl_term;
} // namespace
-real cmap_dihs(int nbonds,
- const t_iatom forceatoms[],
- const t_iparams forceparams[],
- const gmx_cmap_t* cmap_grid,
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph* g,
+real cmap_dihs(int nbonds,
+ const t_iatom forceatoms[],
+ const t_iparams forceparams[],
+ const gmx_cmap_t* cmap_grid,
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec a1, b1, a2, b2;
rvec f1, g1, h1, f2, g2, h2;
rvec dtf1, dtg1, dth1, dtf2, dtg2, dth2;
- ivec jt1, dt1_ij, dt1_kj, dt1_lj;
- ivec jt2, dt2_ij, dt2_kj, dt2_lj;
int loop_index[4][4] = { { 0, 4, 8, 12 }, { 1, 5, 9, 13 }, { 2, 6, 10, 14 }, { 3, 7, 11, 15 } };
/* Shift forces */
if (fshift != nullptr)
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, a1j), jt1);
- ivec_sub(SHIFT_IVEC(g, a1i), jt1, dt1_ij);
- ivec_sub(SHIFT_IVEC(g, a1k), jt1, dt1_kj);
- ivec_sub(SHIFT_IVEC(g, a1l), jt1, dt1_lj);
- t11 = IVEC2IS(dt1_ij);
- t21 = IVEC2IS(dt1_kj);
- t31 = IVEC2IS(dt1_lj);
-
- copy_ivec(SHIFT_IVEC(g, a2j), jt2);
- ivec_sub(SHIFT_IVEC(g, a2i), jt2, dt2_ij);
- ivec_sub(SHIFT_IVEC(g, a2k), jt2, dt2_kj);
- ivec_sub(SHIFT_IVEC(g, a2l), jt2, dt2_lj);
- t12 = IVEC2IS(dt2_ij);
- t22 = IVEC2IS(dt2_kj);
- t32 = IVEC2IS(dt2_lj);
- }
- else if (pbc)
+ if (pbc)
{
t31 = pbc_rvec_sub(pbc, x[a1l], x[a1j], h1);
t32 = pbc_rvec_sub(pbc, x[a2l], x[a2j], h2);
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += 0.5 * vbond; /* 1*/
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 44 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 44 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
real cos_theta, dVdt, va, vtot;
real rij_1, rij_2, rkj_1, rkj_2, rijrkj_1;
rvec f_i, f_j, f_k;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; (i < nbonds);)
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k); /* 9 */
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec r_ij, r_kj;
real vtot, vrr, s1, s2, r1, r2, r1e, r2e, krr;
rvec f_i, f_j, f_k;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; (i < nbonds);)
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k); /* 9 */
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
rvec r_ij, r_kj, r_ik;
real vtot, vrt, s1, s2, s3, r1, r2, r3, r1e, r2e, r3e, krt, k1, k2, k3;
rvec f_i, f_j, f_k;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; (i < nbonds);)
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k); /* 9 */
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
vtot += vbond; /* 1*/
fbond *= gmx::invsqrt(dr2); /* 6 */
- spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, g, fshift); /* 15 */
- } /* 62 TOTAL */
+ spreadBondForces<flavor>(fbond, dx, ai, aj, f, ki, fshift); /* 15 */
+ } /* 62 TOTAL */
return vtot;
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
int i, ai, aj, ak, t1, t2, type, table;
rvec r_ij, r_kj;
real cos_theta, cos_theta2, theta, dVdt, va, vtot;
- ivec jt, dt_ij, dt_kj;
vtot = 0.0;
for (i = 0; (i < nbonds);)
if (computeVirial(flavor))
{
- if (g)
- {
- copy_ivec(SHIFT_IVEC(g, aj), jt);
-
- ivec_sub(SHIFT_IVEC(g, ai), jt, dt_ij);
- ivec_sub(SHIFT_IVEC(g, ak), jt, dt_kj);
- t1 = IVEC2IS(dt_ij);
- t2 = IVEC2IS(dt_kj);
- }
rvec_inc(fshift[t1], f_i);
rvec_inc(fshift[CENTRAL], f_j);
rvec_inc(fshift[t2], f_k);
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms gmx_unused* md,
forceparams[type].tab.kB, phi + M_PI, lambda, &vpd, &ddphi);
vtot += vpd;
- do_dih_fup<flavor>(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, g, x, t1,
+ do_dih_fup<flavor>(ai, aj, ak, al, -ddphi, r_ij, r_kj, r_kl, m, n, f, fshift, pbc, x, t1,
t2, t3); /* 112 */
} /* 227 TOTAL */
} // namespace
-real calculateSimpleBond(const int ftype,
- const int numForceatoms,
- const t_iatom forceatoms[],
- const t_iparams forceparams[],
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph gmx_unused* g,
- const real lambda,
- real* dvdlambda,
- const t_mdatoms* md,
- t_fcdata* fcd,
+real calculateSimpleBond(const int ftype,
+ const int numForceatoms,
+ const t_iatom forceatoms[],
+ const t_iparams forceparams[],
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
+ const real lambda,
+ real* dvdlambda,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
int gmx_unused* global_atom_index,
const BondedKernelFlavor bondedKernelFlavor)
{
const BondedInteractions& bonded = c_bondedInteractionFunctionsPerFlavor[bondedKernelFlavor][ftype];
- real v = bonded.function(numForceatoms, forceatoms, forceparams, x, f, fshift, pbc, g, lambda,
+ real v = bonded.function(numForceatoms, forceatoms, forceparams, x, f, fshift, pbc, lambda,
dvdlambda, md, fcd, global_atom_index);
return v;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_cmap_t;
struct t_fcdata;
-struct t_graph;
struct t_mdatom;
struct t_nrnb;
struct t_pbc;
int* t3);
/*! \brief Do an update of the forces for dihedral potentials */
-void do_dih_fup(int i,
- int j,
- int k,
- int l,
- real ddphi,
- rvec r_ij,
- rvec r_kj,
- rvec r_kl,
- rvec m,
- rvec n,
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph* g,
- const rvec* x,
- int t1,
- int t2,
- int t3);
+void do_dih_fup(int i,
+ int j,
+ int k,
+ int l,
+ real ddphi,
+ rvec r_ij,
+ rvec r_kj,
+ rvec r_kl,
+ rvec m,
+ rvec n,
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
+ const rvec* x,
+ int t1,
+ int t2,
+ int t3);
/*! \brief Make a dihedral fall in the range (-pi,pi) */
void make_dp_periodic(real* dp);
/*! \brief Compute CMAP dihedral energies and forces */
-real cmap_dihs(int nbonds,
- const t_iatom forceatoms[],
- const t_iparams forceparams[],
- const gmx_cmap_t* cmap_grid,
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph* g,
+real cmap_dihs(int nbonds,
+ const t_iatom forceatoms[],
+ const t_iparams forceparams[],
+ const gmx_cmap_t* cmap_grid,
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
* All pointers should be non-null, except for pbc and g which can be nullptr.
* \returns the energy or 0 when \p bondedKernelFlavor did not request the energy.
*/
-real calculateSimpleBond(int ftype,
- int numForceatoms,
- const t_iatom forceatoms[],
- const t_iparams forceparams[],
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph gmx_unused* g,
- real lambda,
- real* dvdlambda,
- const t_mdatoms* md,
- t_fcdata* fcd,
+real calculateSimpleBond(int ftype,
+ int numForceatoms,
+ const t_iatom forceatoms[],
+ const t_iparams forceparams[],
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
+ real lambda,
+ real* dvdlambda,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
int gmx_unused* global_atom_index,
BondedKernelFlavor bondedKernelFlavor);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
void init_disres(FILE* fplog,
const gmx_mtop_t* mtop,
t_inputrec* ir,
- const t_commrec* cr,
+ DisResRunMode disResRunMode,
+ DDRole ddRole,
+ NumRanks numRanks,
+ MPI_Comm communicator,
const gmx_multisim_t* ms,
t_fcdata* fcd,
t_state* state,
{
/* We store the r^-6 time averages in an array that is indexed
* with the local disres iatom index, so this doesn't work with DD.
- * Note that DD is not initialized yet here, so we check for PAR(cr),
+ * Note that DD is not initialized yet here, so we check that we are on multiple ranks,
* but there are probably also issues with e.g. NM MPI parallelization.
*/
- if (cr && PAR(cr))
+ if ((disResRunMode == DisResRunMode::MDRun) && (numRanks == NumRanks::Multiple))
{
gmx_fatal(FARGS,
"Time-averaged distance restraints are not supported with MPI "
iloop = gmx_mtop_ilistloop_init(mtop);
while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
{
- if (nmol > 1 && (*il)[F_DISRES].size() > 0 && ir->eDisre != edrEnsemble)
+ if (nmol > 1 && !(*il)[F_DISRES].empty() && ir->eDisre != edrEnsemble)
{
gmx_fatal(FARGS,
"NMR distance restraints with multiple copies of the same molecule are "
}
}
- if (cr && PAR(cr) && ir->nstdisreout > 0)
+ if ((disResRunMode == DisResRunMode::MDRun) && (numRanks == NumRanks::Multiple) && ir->nstdisreout > 0)
{
/* With DD we currently only have local pair information available */
gmx_fatal(FARGS,
dd->Rtav_6 = &(dd->Rt_6[dd->nres]);
ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE");
- if (cr && ms != nullptr && ptr != nullptr && !bIsREMD)
+ if ((disResRunMode == DisResRunMode::MDRun) && ms != nullptr && ptr != nullptr && !bIsREMD)
{
#if GMX_MPI
dd->nsystems = 0;
/* This check is only valid on MASTER(cr), so probably
* ensemble-averaged distance restraints are broken on more
* than one processor per simulation system. */
- if (MASTER(cr))
+ if (ddRole == DDRole::Master)
{
check_multi_int(fplog, ms, dd->nsystems, "the number of systems per ensemble", FALSE);
}
- gmx_bcast_sim(sizeof(int), &dd->nsystems, cr);
+ gmx_bcast(sizeof(int), &dd->nsystems, communicator);
/* We use to allow any value of nsystems which was a divisor
* of ms->nsim. But this required an extra communicator which
* checks from appropriate processes (since check_multi_int is
* too broken to check whether the communication will
* succeed...) */
- if (cr && ms && dd->nsystems > 1 && MASTER(cr))
+ if ((disResRunMode == DisResRunMode::MDRun) && ms && dd->nsystems > 1 && (ddRole == DDRole::Master))
{
check_multi_int(fplog, ms, fcd->disres.nres, "the number of distance restraints", FALSE);
}
if (DOMAINDECOMP(cr))
{
- gmx_bcast(2 * dd->nres, dd->Rt_6, cr);
+ gmx_bcast(2 * dd->nres, dd->Rt_6, cr->mpi_comm_mygroup);
}
}
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
real tav_viol_Rtav7, instant_viol_Rtav7;
real up1, up2, low;
gmx_bool bConservative, bMixed, bViolation;
- ivec dt;
t_disresdata* dd;
int dr_weighting;
gmx_bool dr_bMixed;
fk_scal = f_scal * weight_rt_1;
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
- ki = IVEC2IS(dt);
- }
-
for (int m = 0; m < DIM; m++)
{
fij = fk_scal * dx[m];
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/ifunc.h"
#include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/gmxmpi.h"
struct gmx_mtop_t;
struct gmx_multisim_t;
struct t_inputrec;
struct t_pbc;
class t_state;
+enum class DDRole;
+enum class NumRanks;
+
+//! Whether distance restraints are called from mdrun or from an analysis tool
+enum class DisResRunMode
+{
+ MDRun,
+ AnalysisTool
+};
/*! \brief
* Initiates *fcd data.
void init_disres(FILE* fplog,
const gmx_mtop_t* mtop,
t_inputrec* ir,
- const t_commrec* cr,
+ DisResRunMode disResRunMode,
+ DDRole ddRole,
+ NumRanks numRanks,
+ MPI_Comm communicator,
const gmx_multisim_t* ms,
t_fcdata* fcd,
t_state* state,
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_LISTED_FORCES_GPUBONDED_H
#define GMX_LISTED_FORCES_GPUBONDED_H
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/idef.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/classhelpers.h"
+class DeviceContext;
+class DeviceStream;
+
struct gmx_enerdata_t;
struct gmx_ffparams_t;
struct gmx_mtop_t;
-struct t_forcerec;
-struct t_idef;
struct t_inputrec;
struct gmx_wallcycle;
class GpuBonded
{
public:
- //! Construct the manager with constant data and the stream to use.
- GpuBonded(const gmx_ffparams_t& ffparams, void* streamPtr, gmx_wallcycle* wcycle);
+ /*! \brief Construct the manager with constant data and the stream to use.
+ *
+ * \param[in] ffparams Force-field parameters.
+ * \param[in] electrostaticsScaleFactor Scaling factor for the electrostatic potential
+ * (Coulomb constant, multiplied by the Fudge factor).
+ * \param[in] deviceContext GPU device context (not used in CUDA).
+ * \param[in] deviceStream GPU device stream.
+ * \param[in] wcycle The wallclock counter.
+ *
+ */
+ GpuBonded(const gmx_ffparams_t& ffparams,
+ float electrostaticsScaleFactor,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ gmx_wallcycle* wcycle);
//! Destructor
~GpuBonded();
* Intended to be called after each neighbour search
* stage. Copies the bonded interactions assigned to the GPU
* to device data structures, and updates device buffers that
- * may have been updated after search. */
- void updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
- const t_idef& idef,
- void* xqDevice,
- void* forceDevice,
- void* fshiftDevice);
+ * may have been updated after search.
+ *
+ * \param[in] nbnxnAtomOrder Mapping between rvec and NBNXM formats.
+ * \param[in] idef List of interactions to compute.
+ * \param[in] xqDevice Device buffer with coordinates and charge in xyzq-format.
+ * \param[in,out] forceDevice Device buffer with forces.
+ * \param[in,out] fshiftDevice Device buffer with shift forces.
+ */
+ void updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
+ const InteractionDefinitions& idef,
+ void* xqDevice,
+ DeviceBuffer<RVec> forceDevice,
+ DeviceBuffer<RVec> fshiftDevice);
+ /*! \brief
+ * Update PBC data.
+ *
+ * Converts PBC data from t_pbc into the PbcAiuc format and stores the latter.
+ *
+ * \param[in] pbcType The type of the periodic boundary.
+ * \param[in] box The periodic boundary box matrix.
+ * \param[in] canMoleculeSpanPbc Whether one molecule can have atoms in different PBC cells.
+ */
+ void setPbc(PbcType pbcType, const matrix box, bool canMoleculeSpanPbc);
+
/*! \brief Returns whether there are bonded interactions
- * assigned to the GPU */
+ * assigned to the GPU
+ *
+ * \returns If the list of interaction has elements.
+ */
bool haveInteractions() const;
- /*! \brief Launches bonded kernel on a GPU */
- void launchKernel(const t_forcerec* fr, const gmx::StepWorkload& stepWork, const matrix box);
- /*! \brief Launches the transfer of computed bonded energies. */
+
+ /*! \brief Launches bonded kernel on a GPU
+ *
+ * \param[in] stepWork Simulation step work to determine if energy/virial are to be computed on this step.
+ */
+ void launchKernel(const gmx::StepWorkload& stepWork);
+
+ /*! \brief Sets the PBC and launches bonded kernel on a GPU
+ *
+ * \param[in] pbcType The type of the periodic boundary.
+ * \param[in] box The periodic boundary box matrix.
+ * \param[in] canMoleculeSpanPbc Whether one molecule can have atoms in different PBC cells.
+ * \param[in] stepWork Simulation step work to determine if energy/virial are to be computed on this step.
+ */
+ void setPbcAndlaunchKernel(PbcType pbcType,
+ const matrix box,
+ bool canMoleculeSpanPbc,
+ const gmx::StepWorkload& stepWork);
+
+ /*! \brief Launches the transfer of computed bonded energies.
+ */
void launchEnergyTransfer();
- /*! \brief Waits on the energy transfer, and accumulates bonded energies to \c enerd. */
+
+ /*! \brief Waits on the energy transfer, and accumulates bonded energies to \c enerd.
+ *
+ * \param[in,out] enerd The energy data object to add energy terms to.
+ */
void waitAccumulateEnergyTerms(gmx_enerdata_t* enerd);
- /*! \brief Clears the device side energy buffer */
+
+ /*! \brief Clears the device side energy buffer
+ */
void clearEnergies();
private:
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
};
-GpuBonded::GpuBonded(const gmx_ffparams_t& /* ffparams */, void* /*streamPtr */, gmx_wallcycle* /* wcycle */) :
+GpuBonded::GpuBonded(const gmx_ffparams_t& /* ffparams */,
+ const float /* electrostaticsScaleFactor */,
+ const DeviceContext& /* deviceContext */,
+ const DeviceStream& /* deviceStream */,
+ gmx_wallcycle* /* wcycle */) :
impl_(nullptr)
{
}
GpuBonded::~GpuBonded() = default;
void GpuBonded::updateInteractionListsAndDeviceBuffers(ArrayRef<const int> /* nbnxnAtomOrder */,
- const t_idef& /* idef */,
+ const InteractionDefinitions& /* idef */,
void* /* xqDevice */,
- void* /* forceDevice */,
- void* /* fshiftDevice */)
+ DeviceBuffer<RVec> /* forceDevice */,
+ DeviceBuffer<RVec> /* fshiftDevice */)
+{
+}
+
+void GpuBonded::setPbc(PbcType /* pbcType */, const matrix /* box */, bool /* canMoleculeSpanPbc */)
{
}
bool GpuBonded::haveInteractions() const
{
- return false;
+ return !impl_;
}
-void GpuBonded::launchKernel(const t_forcerec* /* fr */,
- const gmx::StepWorkload& /* stepWork */,
- const matrix /* box */)
+void GpuBonded::launchKernel(const gmx::StepWorkload& /* stepWork */) {}
+
+void GpuBonded::setPbcAndlaunchKernel(PbcType /* pbcType */,
+ const matrix /* box */,
+ bool /* canMoleculeSpanPbc */,
+ const gmx::StepWorkload& /* stepWork */)
{
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/cuda_arch_utils.cuh"
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/devicebuffer.h"
+#include "gromacs/gpu_utils/typecasts.cuh"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/topology/forcefieldparameters.h"
namespace gmx
{
+// Number of CUDA threads in a block
+constexpr static int c_threadsPerBlock = 256;
// ---- GpuBonded::Impl
-GpuBonded::Impl::Impl(const gmx_ffparams_t& ffparams, void* streamPtr, gmx_wallcycle* wcycle)
+GpuBonded::Impl::Impl(const gmx_ffparams_t& ffparams,
+ const float electrostaticsScaleFactor,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ gmx_wallcycle* wcycle) :
+ deviceContext_(deviceContext),
+ deviceStream_(deviceStream)
{
- stream_ = *static_cast<CommandStream*>(streamPtr);
+ GMX_RELEASE_ASSERT(deviceStream.isValid(),
+ "Can't run GPU version of bonded forces in stream that is not valid.");
+
+ static_assert(c_threadsPerBlock >= SHIFTS,
+ "Threads per block in GPU bonded must be >= SHIFTS for the virial kernel "
+ "(calcVir=true)");
+
wcycle_ = wcycle;
- allocateDeviceBuffer(&d_forceParams_, ffparams.numTypes(), nullptr);
+ allocateDeviceBuffer(&d_forceParams_, ffparams.numTypes(), deviceContext_);
// This could be an async transfer (if the source is pinned), so
// long as it uses the same stream as the kernels and we are happy
// to consume additional pinned pages.
- copyToDeviceBuffer(&d_forceParams_, ffparams.iparams.data(), 0, ffparams.numTypes(), stream_,
- GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_forceParams_, ffparams.iparams.data(), 0, ffparams.numTypes(),
+ deviceStream_, GpuApiCallBehavior::Sync, nullptr);
vTot_.resize(F_NRE);
- allocateDeviceBuffer(&d_vTot_, F_NRE, nullptr);
- clearDeviceBufferAsync(&d_vTot_, 0, F_NRE, stream_);
-
- for (int fType = 0; fType < F_NRE; fType++)
- {
- d_iLists_[fType].nr = 0;
- d_iLists_[fType].iatoms = nullptr;
- d_iLists_[fType].nalloc = 0;
- }
-
- kernelParams_.d_forceParams = d_forceParams_;
- kernelParams_.d_xq = d_xq_;
- kernelParams_.d_f = d_f_;
- kernelParams_.d_fShift = d_fShift_;
- kernelParams_.d_vTot = d_vTot_;
+ allocateDeviceBuffer(&d_vTot_, F_NRE, deviceContext_);
+ clearDeviceBufferAsync(&d_vTot_, 0, F_NRE, deviceStream_);
+
+ kernelParams_.electrostaticsScaleFactor = electrostaticsScaleFactor;
+ kernelParams_.d_forceParams = d_forceParams_;
+ kernelParams_.d_xq = d_xq_;
+ kernelParams_.d_f = d_f_;
+ kernelParams_.d_fShift = d_fShift_;
+ kernelParams_.d_vTot = d_vTot_;
for (int i = 0; i < numFTypesOnGpu; i++)
{
kernelParams_.d_iatoms[i] = nullptr;
kernelParams_.fTypeRangeStart[i] = 0;
kernelParams_.fTypeRangeEnd[i] = -1;
}
+
+ int fTypeRangeEnd = kernelParams_.fTypeRangeEnd[numFTypesOnGpu - 1];
+
+ kernelLaunchConfig_.blockSize[0] = c_threadsPerBlock;
+ kernelLaunchConfig_.blockSize[1] = 1;
+ kernelLaunchConfig_.blockSize[2] = 1;
+ kernelLaunchConfig_.gridSize[0] = (fTypeRangeEnd + c_threadsPerBlock) / c_threadsPerBlock;
+ kernelLaunchConfig_.gridSize[1] = 1;
+ kernelLaunchConfig_.gridSize[2] = 1;
}
GpuBonded::Impl::~Impl()
}
//! Return whether function type \p fType in \p idef has perturbed interactions
-static bool fTypeHasPerturbedEntries(const t_idef& idef, int fType)
+static bool fTypeHasPerturbedEntries(const InteractionDefinitions& idef, int fType)
{
GMX_ASSERT(idef.ilsort == ilsortNO_FE || idef.ilsort == ilsortFE_SORTED,
"Perturbed interations should be sorted here");
- const t_ilist& ilist = idef.il[fType];
+ const InteractionList& ilist = idef.il[fType];
- return (idef.ilsort != ilsortNO_FE && ilist.nr_nonperturbed != ilist.nr);
+ return (idef.ilsort != ilsortNO_FE && idef.numNonperturbedInteractions[fType] != ilist.size());
}
//! Converts \p src with atom indices in state order to \p dest in nbnxn order
-static void convertIlistToNbnxnOrder(const t_ilist& src,
- HostInteractionList* dest,
- int numAtomsPerInteraction,
- ArrayRef<const int> nbnxnAtomOrder)
+static void convertIlistToNbnxnOrder(const InteractionList& src,
+ HostInteractionList* dest,
+ int numAtomsPerInteraction,
+ ArrayRef<const int> nbnxnAtomOrder)
{
GMX_ASSERT(src.size() == 0 || !nbnxnAtomOrder.empty(), "We need the nbnxn atom order");
* types are assigned in blocks sized as <warp_size>. The beginning and end (thread index) of each
* interaction type are stored in kernelParams_. Pointers to the relevant data structures on the
* GPU are also stored in kernelParams_.
+ *
+ * \todo Use DeviceBuffer for the d_xqPtr.
*/
void GpuBonded::Impl::updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
- const t_idef& idef,
- void* d_xqPtr,
- void* d_fPtr,
- void* d_fShiftPtr)
+ const InteractionDefinitions& idef,
+ void* d_xqPtr,
+ DeviceBuffer<RVec> d_fPtr,
+ DeviceBuffer<RVec> d_fShiftPtr)
{
// TODO wallcycle sub start
haveInteractions_ = false;
* But instead of doing all interactions on the CPU, we can
* still easily handle the types that have no perturbed
* interactions on the GPU. */
- if (idef.il[fType].nr > 0 && !fTypeHasPerturbedEntries(idef, fType))
+ if (!idef.il[fType].empty() && !fTypeHasPerturbedEntries(idef, fType))
{
haveInteractions_ = true;
{
t_ilist& d_iList = d_iLists_[fType];
- reallocateDeviceBuffer(&d_iList.iatoms, iList.size(), &d_iList.nr, &d_iList.nalloc, nullptr);
+ reallocateDeviceBuffer(&d_iList.iatoms, iList.size(), &d_iList.nr, &d_iList.nalloc,
+ deviceContext_);
- copyToDeviceBuffer(&d_iList.iatoms, iList.iatoms.data(), 0, iList.size(), stream_,
+ copyToDeviceBuffer(&d_iList.iatoms, iList.iatoms.data(), 0, iList.size(), deviceStream_,
GpuApiCallBehavior::Async, nullptr);
}
kernelParams_.fTypesOnGpu[fTypesCounter] = fType;
fTypesCounter++;
}
+ int fTypeRangeEnd = kernelParams_.fTypeRangeEnd[numFTypesOnGpu - 1];
+ kernelLaunchConfig_.gridSize[0] = (fTypeRangeEnd + c_threadsPerBlock) / c_threadsPerBlock;
+
d_xq_ = static_cast<float4*>(d_xqPtr);
- d_f_ = static_cast<fvec*>(d_fPtr);
- d_fShift_ = static_cast<fvec*>(d_fShiftPtr);
+ d_f_ = asFloat3(d_fPtr);
+ d_fShift_ = asFloat3(d_fShiftPtr);
kernelParams_.d_xq = d_xq_;
kernelParams_.d_f = d_f_;
// TODO wallcycle sub stop
}
+void GpuBonded::Impl::setPbc(PbcType pbcType, const matrix box, bool canMoleculeSpanPbc)
+{
+ PbcAiuc pbcAiuc;
+ setPbcAiuc(canMoleculeSpanPbc ? numPbcDimensions(pbcType) : 0, box, &pbcAiuc);
+ kernelParams_.pbcAiuc = pbcAiuc;
+}
+
bool GpuBonded::Impl::haveInteractions() const
{
return haveInteractions_;
GMX_ASSERT(haveInteractions_,
"No GPU bonded interactions, so no energies will be computed, so transfer should "
"not be called");
-
wallcycle_sub_start_nocount(wcycle_, ewcsLAUNCH_GPU_BONDED);
// TODO add conditional on whether there has been any compute (and make sure host buffer doesn't contain garbage)
float* h_vTot = vTot_.data();
- copyFromDeviceBuffer(h_vTot, &d_vTot_, 0, F_NRE, stream_, GpuApiCallBehavior::Async, nullptr);
+ copyFromDeviceBuffer(h_vTot, &d_vTot_, 0, F_NRE, deviceStream_, GpuApiCallBehavior::Async, nullptr);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_GPU_BONDED);
}
"accumulation should not occur");
wallcycle_start(wcycle_, ewcWAIT_GPU_BONDED);
- cudaError_t stat = cudaStreamSynchronize(stream_);
+ cudaError_t stat = cudaStreamSynchronize(deviceStream_.stream());
CU_RET_ERR(stat, "D2H transfer of bonded energies failed");
wallcycle_stop(wcycle_, ewcWAIT_GPU_BONDED);
{
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start_nocount(wcycle_, ewcsLAUNCH_GPU_BONDED);
- clearDeviceBufferAsync(&d_vTot_, 0, F_NRE, stream_);
+ clearDeviceBufferAsync(&d_vTot_, 0, F_NRE, deviceStream_);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_GPU_BONDED);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
}
// ---- GpuBonded
-GpuBonded::GpuBonded(const gmx_ffparams_t& ffparams, void* streamPtr, gmx_wallcycle* wcycle) :
- impl_(new Impl(ffparams, streamPtr, wcycle))
+GpuBonded::GpuBonded(const gmx_ffparams_t& ffparams,
+ const float electrostaticsScaleFactor,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ gmx_wallcycle* wcycle) :
+ impl_(new Impl(ffparams, electrostaticsScaleFactor, deviceContext, deviceStream, wcycle))
{
}
GpuBonded::~GpuBonded() = default;
-void GpuBonded::updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
- const t_idef& idef,
- void* d_xq,
- void* d_f,
- void* d_fShift)
+void GpuBonded::updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
+ const InteractionDefinitions& idef,
+ void* d_xq,
+ DeviceBuffer<RVec> d_f,
+ DeviceBuffer<RVec> d_fShift)
{
impl_->updateInteractionListsAndDeviceBuffers(nbnxnAtomOrder, idef, d_xq, d_f, d_fShift);
}
+void GpuBonded::setPbc(PbcType pbcType, const matrix box, bool canMoleculeSpanPbc)
+{
+ impl_->setPbc(pbcType, box, canMoleculeSpanPbc);
+}
+
bool GpuBonded::haveInteractions() const
{
return impl_->haveInteractions();
}
+void GpuBonded::setPbcAndlaunchKernel(PbcType pbcType,
+ const matrix box,
+ bool canMoleculeSpanPbc,
+ const gmx::StepWorkload& stepWork)
+{
+ setPbc(pbcType, box, canMoleculeSpanPbc);
+ launchKernel(stepWork);
+}
+
void GpuBonded::launchEnergyTransfer()
{
impl_->launchEnergyTransfer();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_LISTED_FORCES_GPUBONDED_IMPL_H
#define GMX_LISTED_FORCES_GPUBONDED_IMPL_H
-#include "gromacs/gpu_utils/gpu_vec.cuh"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/listed_forces/gpubonded.h"
//! Periodic boundary data
PbcAiuc pbcAiuc;
//! Scale factor
- float scaleFactor;
+ float electrostaticsScaleFactor;
//! The bonded types on GPU
int fTypesOnGpu[numFTypesOnGpu];
//! The number of interaction atom (iatom) elements for every function type
//! Coordinates before the timestep (on GPU)
const float4* d_xq;
//! Forces on atoms (on GPU)
- fvec* d_f;
+ float3* d_f;
//! Force shifts on atoms (on GPU)
- fvec* d_fShift;
+ float3* d_fShift;
//! Total Energy (on GPU)
float* d_vTot;
//! Interaction list atoms (on GPU)
setPbcAiuc(0, boxDummy, &pbcAiuc);
- scaleFactor = 1.0;
- d_forceParams = nullptr;
- d_xq = nullptr;
- d_f = nullptr;
- d_fShift = nullptr;
- d_vTot = nullptr;
+ electrostaticsScaleFactor = 1.0;
+ d_forceParams = nullptr;
+ d_xq = nullptr;
+ d_f = nullptr;
+ d_fShift = nullptr;
+ d_vTot = nullptr;
}
};
{
public:
//! Constructor
- Impl(const gmx_ffparams_t& ffparams, void* streamPtr, gmx_wallcycle* wcycle);
+ Impl(const gmx_ffparams_t& ffparams,
+ const float electrostaticsScaleFactor,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ gmx_wallcycle* wcycle);
/*! \brief Destructor, non-default needed for freeing
* device-side buffers */
~Impl();
* stage. Copies the bonded interactions assigned to the GPU
* to device data structures, and updates device buffers that
* may have been updated after search. */
- void updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
- const t_idef& idef,
- void* xqDevice,
- void* forceDevice,
- void* fshiftDevice);
+ void updateInteractionListsAndDeviceBuffers(ArrayRef<const int> nbnxnAtomOrder,
+ const InteractionDefinitions& idef,
+ void* xqDevice,
+ DeviceBuffer<RVec> forceDevice,
+ DeviceBuffer<RVec> fshiftDevice);
+ /*! \brief
+ * Update PBC data.
+ *
+ * Converts PBC data from t_pbc into the PbcAiuc format and stores the latter.
+ *
+ * \param[in] pbcType The type of the periodic boundary.
+ * \param[in] box The periodic boundary box matrix.
+ * \param[in] canMoleculeSpanPbc Whether one molecule can have atoms in different PBC cells.
+ */
+ void setPbc(PbcType pbcType, const matrix box, bool canMoleculeSpanPbc);
/*! \brief Launches bonded kernel on a GPU */
template<bool calcVir, bool calcEner>
- void launchKernel(const t_forcerec* fr, const matrix box);
+ void launchKernel();
/*! \brief Returns whether there are bonded interactions
* assigned to the GPU */
bool haveInteractions() const;
//! Tells whether there are any interaction in iLists.
bool haveInteractions_;
//! Interaction lists on the device.
- t_ilist d_iLists_[F_NRE];
+ t_ilist d_iLists_[F_NRE] = {};
//! Bonded parameters for device-side use.
t_iparams* d_forceParams_ = nullptr;
//! Position-charge vector on the device.
const float4* d_xq_ = nullptr;
//! Force vector on the device.
- fvec* d_f_ = nullptr;
+ float3* d_f_ = nullptr;
//! Shift force vector on the device.
- fvec* d_fShift_ = nullptr;
+ float3* d_fShift_ = nullptr;
//! \brief Host-side virial buffer
HostVector<float> vTot_ = { {}, gmx::HostAllocationPolicy(gmx::PinningPolicy::PinnedIfSupported) };
//! \brief Device-side total virial
float* d_vTot_ = nullptr;
+ //! GPU context object
+ const DeviceContext& deviceContext_;
//! \brief Bonded GPU stream, not owned by this module
- CommandStream stream_;
+ const DeviceStream& deviceStream_;
//! Parameters and pointers, passed to the CUDA kernel
BondedCudaKernelParameters kernelParams_;
+ //! GPU kernel launch configuration
+ KernelLaunchConfig kernelLaunchConfig_;
+
//! \brief Pointer to wallcycle structure.
gmx_wallcycle* wcycle_;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <math_constants.h>
#include "gromacs/gpu_utils/cudautils.cuh"
-#include "gromacs/gpu_utils/gpu_vec.cuh"
+#include "gromacs/gpu_utils/typecasts.cuh"
+#include "gromacs/gpu_utils/vectype_ops.cuh"
#include "gromacs/listed_forces/gpubonded.h"
#include "gromacs/math/units.h"
#include "gromacs/mdlib/force_flags.h"
-#include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/simulation_workload.h"
-#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/pbc_aiuc_cuda.cuh"
#include "gromacs/utility/gmxassert.h"
# include <limits>
#endif
-// CUDA threads per block
-#define TPB_BONDED 256
-
/*-------------------------------- CUDA kernels-------------------------------- */
/*------------------------------------------------------------------------------*/
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
if (i < numBonds)
int aj = bondData.z;
/* dx = xi - xj, corrected for periodic boundary conditions. */
- fvec dx;
- int ki = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[aj], dx);
+ float3 dx;
+ int ki = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[aj], dx);
- float dr2 = iprod_gpu(dx, dx);
+ float dr2 = norm2(dx);
float dr = sqrt(dr2);
float vbond;
{
fbond *= rsqrtf(dr2);
-#pragma unroll
- for (int m = 0; m < DIM; m++)
+ float3 fij = fbond * dx;
+ atomicAdd(&gm_f[ai], fij);
+ atomicAdd(&gm_f[aj], -fij);
+ if (calcVir && ki != CENTRAL)
{
- float fij = fbond * dx[m];
- atomicAdd(&gm_f[ai][m], fij);
- atomicAdd(&gm_f[aj][m], -fij);
- if (calcVir && ki != CENTRAL)
- {
- atomicAdd(&sm_fShiftLoc[ki][m], fij);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], -fij);
- }
+ atomicAdd(&sm_fShiftLoc[ki], fij);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], -fij);
}
}
}
const float4 xj,
const float4 xk,
const PbcAiuc& pbcAiuc,
- fvec r_ij,
- fvec r_kj,
+ float3* r_ij,
+ float3* r_kj,
float* costh,
int* t1,
int* t2)
/* Return value is the angle between the bonds i-j and j-k */
{
- *t1 = pbcDxAiuc<returnShift>(pbcAiuc, xi, xj, r_ij);
- *t2 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xj, r_kj);
+ *t1 = pbcDxAiuc<returnShift>(pbcAiuc, xi, xj, *r_ij);
+ *t2 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xj, *r_kj);
- *costh = cos_angle_gpu(r_ij, r_kj);
+ *costh = cos_angle(*r_ij, *r_kj);
float th = acosf(*costh);
return th;
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
if (i < numBonds)
int aj = angleData.z;
int ak = angleData.w;
- fvec r_ij;
- fvec r_kj;
- float cos_theta;
- int t1;
- int t2;
- float theta = bond_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], pbcAiuc, r_ij, r_kj,
- &cos_theta, &t1, &t2);
+ float3 r_ij;
+ float3 r_kj;
+ float cos_theta;
+ int t1;
+ int t2;
+ float theta = bond_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], pbcAiuc, &r_ij,
+ &r_kj, &cos_theta, &t1, &t2);
float va;
float dVdt;
{
float st = dVdt * rsqrtf(1.0f - cos_theta2);
float sth = st * cos_theta;
- float nrij2 = iprod_gpu(r_ij, r_ij);
- float nrkj2 = iprod_gpu(r_kj, r_kj);
+ float nrij2 = norm2(r_ij);
+ float nrkj2 = norm2(r_kj);
float nrij_1 = rsqrtf(nrij2);
float nrkj_1 = rsqrtf(nrkj2);
float cii = sth * nrij_1 * nrij_1;
float ckk = sth * nrkj_1 * nrkj_1;
- fvec f_i;
- fvec f_k;
- fvec f_j;
-#pragma unroll
- for (int m = 0; m < DIM; m++)
+ float3 f_i = cii * r_ij - cik * r_kj;
+ float3 f_k = ckk * r_kj - cik * r_ij;
+ float3 f_j = -f_i - f_k;
+
+ atomicAdd(&gm_f[ai], f_i);
+ atomicAdd(&gm_f[aj], f_j);
+ atomicAdd(&gm_f[ak], f_k);
+
+ if (calcVir)
{
- f_i[m] = -(cik * r_kj[m] - cii * r_ij[m]);
- f_k[m] = -(cik * r_ij[m] - ckk * r_kj[m]);
- f_j[m] = -f_i[m] - f_k[m];
- atomicAdd(&gm_f[ai][m], f_i[m]);
- atomicAdd(&gm_f[aj][m], f_j[m]);
- atomicAdd(&gm_f[ak][m], f_k[m]);
- if (calcVir)
- {
- atomicAdd(&sm_fShiftLoc[t1][m], f_i[m]);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], f_j[m]);
- atomicAdd(&sm_fShiftLoc[t2][m], f_k[m]);
- }
+ atomicAdd(&sm_fShiftLoc[t1], f_i);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], f_j);
+ atomicAdd(&sm_fShiftLoc[t2], f_k);
}
}
}
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
if (i < numBonds)
float r13A = d_forceparams[type].u_b.r13A;
float kUBA = d_forceparams[type].u_b.kUBA;
- fvec r_ij;
- fvec r_kj;
- float cos_theta;
- int t1;
- int t2;
- float theta = bond_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], pbcAiuc, r_ij, r_kj,
- &cos_theta, &t1, &t2);
+ float3 r_ij;
+ float3 r_kj;
+ float cos_theta;
+ int t1;
+ int t2;
+ float theta = bond_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], pbcAiuc, &r_ij,
+ &r_kj, &cos_theta, &t1, &t2);
float va;
float dVdt;
*vtot_loc += va;
}
- fvec r_ik;
- int ki = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[ak], r_ik);
+ float3 r_ik;
+ int ki = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[ak], r_ik);
- float dr2 = iprod_gpu(r_ik, r_ik);
+ float dr2 = norm2(r_ik);
float dr = dr2 * rsqrtf(dr2);
float vbond;
float st = dVdt * rsqrtf(1.0f - cos_theta2);
float sth = st * cos_theta;
- float nrkj2 = iprod_gpu(r_kj, r_kj);
- float nrij2 = iprod_gpu(r_ij, r_ij);
+ float nrkj2 = norm2(r_kj);
+ float nrij2 = norm2(r_ij);
float cik = st * rsqrtf(nrkj2 * nrij2);
float cii = sth / nrij2;
float ckk = sth / nrkj2;
- fvec f_i;
- fvec f_j;
- fvec f_k;
-#pragma unroll
- for (int m = 0; m < DIM; m++)
+ float3 f_i = cii * r_ij - cik * r_kj;
+ float3 f_k = ckk * r_kj - cik * r_ij;
+ float3 f_j = -f_i - f_k;
+
+ atomicAdd(&gm_f[ai], f_i);
+ atomicAdd(&gm_f[aj], f_j);
+ atomicAdd(&gm_f[ak], f_k);
+
+ if (calcVir)
{
- f_i[m] = -(cik * r_kj[m] - cii * r_ij[m]);
- f_k[m] = -(cik * r_ij[m] - ckk * r_kj[m]);
- f_j[m] = -f_i[m] - f_k[m];
- atomicAdd(&gm_f[ai][m], f_i[m]);
- atomicAdd(&gm_f[aj][m], f_j[m]);
- atomicAdd(&gm_f[ak][m], f_k[m]);
- if (calcVir)
- {
- atomicAdd(&sm_fShiftLoc[t1][m], f_i[m]);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], f_j[m]);
- atomicAdd(&sm_fShiftLoc[t2][m], f_k[m]);
- }
+ atomicAdd(&sm_fShiftLoc[t1], f_i);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], f_j);
+ atomicAdd(&sm_fShiftLoc[t2], f_k);
}
}
fbond *= rsqrtf(dr2);
-#pragma unroll
- for (int m = 0; m < DIM; m++)
+ float3 fik = fbond * r_ik;
+ atomicAdd(&gm_f[ai], fik);
+ atomicAdd(&gm_f[ak], -fik);
+
+ if (calcVir && ki != CENTRAL)
{
- float fik = fbond * r_ik[m];
- atomicAdd(&gm_f[ai][m], fik);
- atomicAdd(&gm_f[ak][m], -fik);
-
- if (calcVir && ki != CENTRAL)
- {
- atomicAdd(&sm_fShiftLoc[ki][m], fik);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], -fik);
- }
+ atomicAdd(&sm_fShiftLoc[ki], fik);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], -fik);
}
}
}
const T xk,
const T xl,
const PbcAiuc& pbcAiuc,
- fvec r_ij,
- fvec r_kj,
- fvec r_kl,
- fvec m,
- fvec n,
+ float3* r_ij,
+ float3* r_kj,
+ float3* r_kl,
+ float3* m,
+ float3* n,
int* t1,
int* t2,
int* t3)
{
- *t1 = pbcDxAiuc<returnShift>(pbcAiuc, xi, xj, r_ij);
- *t2 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xj, r_kj);
- *t3 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xl, r_kl);
-
- cprod_gpu(r_ij, r_kj, m);
- cprod_gpu(r_kj, r_kl, n);
- float phi = gmx_angle_gpu(m, n);
- float ipr = iprod_gpu(r_ij, n);
+ *t1 = pbcDxAiuc<returnShift>(pbcAiuc, xi, xj, *r_ij);
+ *t2 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xj, *r_kj);
+ *t3 = pbcDxAiuc<returnShift>(pbcAiuc, xk, xl, *r_kl);
+
+ *m = cprod(*r_ij, *r_kj);
+ *n = cprod(*r_kj, *r_kl);
+ float phi = gmx_angle(*m, *n);
+ float ipr = iprod(*r_ij, *n);
float sign = (ipr < 0.0f) ? -1.0f : 1.0f;
phi = sign * phi;
const int k,
const int l,
const float ddphi,
- const fvec r_ij,
- const fvec r_kj,
- const fvec r_kl,
- const fvec m,
- const fvec n,
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ const float3 r_ij,
+ const float3 r_kj,
+ const float3 r_kl,
+ const float3 m,
+ const float3 n,
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc& pbcAiuc,
const float4 gm_xq[],
const int t1,
const int t2,
const int gmx_unused t3)
{
- float iprm = iprod_gpu(m, m);
- float iprn = iprod_gpu(n, n);
- float nrkj2 = iprod_gpu(r_kj, r_kj);
+ float iprm = norm2(m);
+ float iprn = norm2(n);
+ float nrkj2 = norm2(r_kj);
float toler = nrkj2 * GMX_REAL_EPS;
if ((iprm > toler) && (iprn > toler))
{
- float nrkj_1 = rsqrtf(nrkj2); // replacing std::invsqrt call
- float nrkj_2 = nrkj_1 * nrkj_1;
- float nrkj = nrkj2 * nrkj_1;
- float a = -ddphi * nrkj / iprm;
- fvec f_i;
- svmul_gpu(a, m, f_i);
- float b = ddphi * nrkj / iprn;
- fvec f_l;
- svmul_gpu(b, n, f_l);
- float p = iprod_gpu(r_ij, r_kj);
+ float nrkj_1 = rsqrtf(nrkj2); // replacing std::invsqrt call
+ float nrkj_2 = nrkj_1 * nrkj_1;
+ float nrkj = nrkj2 * nrkj_1;
+ float a = -ddphi * nrkj / iprm;
+ float3 f_i = a * m;
+ float b = ddphi * nrkj / iprn;
+ float3 f_l = b * n;
+ float p = iprod(r_ij, r_kj);
p *= nrkj_2;
- float q = iprod_gpu(r_kl, r_kj);
+ float q = iprod(r_kl, r_kj);
q *= nrkj_2;
- fvec uvec;
- svmul_gpu(p, f_i, uvec);
- fvec vvec;
- svmul_gpu(q, f_l, vvec);
- fvec svec;
- fvec_sub_gpu(uvec, vvec, svec);
- fvec f_j;
- fvec_sub_gpu(f_i, svec, f_j);
- fvec f_k;
- fvec_add_gpu(f_l, svec, f_k);
-#pragma unroll
- for (int m = 0; (m < DIM); m++)
- {
- atomicAdd(&gm_f[i][m], f_i[m]);
- atomicAdd(&gm_f[j][m], -f_j[m]);
- atomicAdd(&gm_f[k][m], -f_k[m]);
- atomicAdd(&gm_f[l][m], f_l[m]);
- }
+ float3 uvec = p * f_i;
+ float3 vvec = q * f_l;
+ float3 svec = uvec - vvec;
+ float3 f_j = f_i - svec;
+ float3 f_k = f_l + svec;
+
+ atomicAdd(&gm_f[i], f_i);
+ atomicAdd(&gm_f[j], -f_j);
+ atomicAdd(&gm_f[k], -f_k);
+ atomicAdd(&gm_f[l], f_l);
if (calcVir)
{
- fvec dx_jl;
- int t3 = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[l], gm_xq[j], dx_jl);
+ float3 dx_jl;
+ int t3 = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[l], gm_xq[j], dx_jl);
-#pragma unroll
- for (int m = 0; (m < DIM); m++)
- {
- atomicAdd(&sm_fShiftLoc[t1][m], f_i[m]);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], -f_j[m]);
- atomicAdd(&sm_fShiftLoc[t2][m], -f_k[m]);
- atomicAdd(&sm_fShiftLoc[t3][m], f_l[m]);
- }
+ atomicAdd(&sm_fShiftLoc[t1], f_i);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], -f_j);
+ atomicAdd(&sm_fShiftLoc[t2], -f_k);
+ atomicAdd(&sm_fShiftLoc[t3], f_l);
}
}
}
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
if (i < numBonds)
int ak = d_forceatoms[5 * i + 3];
int al = d_forceatoms[5 * i + 4];
- fvec r_ij;
- fvec r_kj;
- fvec r_kl;
- fvec m;
- fvec n;
- int t1;
- int t2;
- int t3;
- float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
- r_ij, r_kj, r_kl, m, n, &t1, &t2, &t3);
+ float3 r_ij;
+ float3 r_kj;
+ float3 r_kl;
+ float3 m;
+ float3 n;
+ int t1;
+ int t2;
+ int t3;
+ float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
+ &r_ij, &r_kj, &r_kl, &m, &n, &t1, &t2, &t3);
float vpd;
float ddphi;
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
constexpr float c0 = 0.0f, c1 = 1.0f, c2 = 2.0f, c3 = 3.0f, c4 = 4.0f, c5 = 5.0f;
int ak = d_forceatoms[5 * i + 3];
int al = d_forceatoms[5 * i + 4];
- fvec r_ij;
- fvec r_kj;
- fvec r_kl;
- fvec m;
- fvec n;
- int t1;
- int t2;
- int t3;
- float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
- r_ij, r_kj, r_kl, m, n, &t1, &t2, &t3);
+ float3 r_ij;
+ float3 r_kj;
+ float3 r_kl;
+ float3 m;
+ float3 n;
+ int t1;
+ int t2;
+ int t3;
+ float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
+ &r_ij, &r_kj, &r_kl, &m, &n, &t1, &t2, &t3);
/* Change to polymer convention */
if (phi < c0)
const t_iatom d_forceatoms[],
const t_iparams d_forceparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc)
{
if (i < numBonds)
int ak = d_forceatoms[5 * i + 3];
int al = d_forceatoms[5 * i + 4];
- fvec r_ij;
- fvec r_kj;
- fvec r_kl;
- fvec m;
- fvec n;
- int t1;
- int t2;
- int t3;
- float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
- r_ij, r_kj, r_kl, m, n, &t1, &t2, &t3);
+ float3 r_ij;
+ float3 r_kj;
+ float3 r_kl;
+ float3 m;
+ float3 n;
+ int t1;
+ int t2;
+ int t3;
+ float phi = dih_angle_gpu<calcVir>(gm_xq[ai], gm_xq[aj], gm_xq[ak], gm_xq[al], pbcAiuc,
+ &r_ij, &r_kj, &r_kl, &m, &n, &t1, &t2, &t3);
/* phi can jump if phi0 is close to Pi/-Pi, which will cause huge
* force changes if we just apply a normal harmonic.
const t_iatom d_forceatoms[],
const t_iparams iparams[],
const float4 gm_xq[],
- fvec gm_f[],
- fvec sm_fShiftLoc[],
+ float3 gm_f[],
+ float3 sm_fShiftLoc[],
const PbcAiuc pbcAiuc,
const float scale_factor,
float* vtotVdw_loc,
{
if (i < numBonds)
{
+ // TODO this should be made into a separate type, the GPU and CPU sizes should be compared
int3 pairData = *(int3*)(d_forceatoms + 3 * i);
int type = pairData.x;
int ai = pairData.y;
float c12 = iparams[type].lj14.c12A;
/* Do we need to apply full periodic boundary conditions? */
- fvec dr;
- int fshift_index = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[aj], dr);
+ float3 dr;
+ int fshift_index = pbcDxAiuc<calcVir>(pbcAiuc, gm_xq[ai], gm_xq[aj], dr);
- float r2 = norm2_gpu(dr);
+ float r2 = norm2(dr);
float rinv = rsqrtf(r2);
float rinv2 = rinv * rinv;
float rinv6 = rinv2 * rinv2 * rinv2;
/* Calculate the LJ force * r and add it to the Coulomb part */
float fr = (12.0f * c12 * rinv6 - 6.0f * c6) * rinv6 + velec;
- float finvr = fr * rinv2;
- fvec f;
- svmul_gpu(finvr, dr, f);
+ float finvr = fr * rinv2;
+ float3 f = finvr * dr;
/* Add the forces */
-#pragma unroll
- for (int m = 0; m < DIM; m++)
+ atomicAdd(&gm_f[ai], f);
+ atomicAdd(&gm_f[aj], -f);
+ if (calcVir && fshift_index != CENTRAL)
{
- atomicAdd(&gm_f[ai][m], f[m]);
- atomicAdd(&gm_f[aj][m], -f[m]);
- if (calcVir && fshift_index != CENTRAL)
- {
- atomicAdd(&sm_fShiftLoc[fshift_index][m], f[m]);
- atomicAdd(&sm_fShiftLoc[CENTRAL][m], -f[m]);
- }
+ atomicAdd(&sm_fShiftLoc[fshift_index], f);
+ atomicAdd(&sm_fShiftLoc[CENTRAL], -f);
}
if (calcEner)
float vtot_loc = 0;
float vtotVdw_loc = 0;
float vtotElec_loc = 0;
- __shared__ fvec sm_fShiftLoc[SHIFTS];
+ __shared__ float3 sm_fShiftLoc[SHIFTS];
if (calcVir)
{
if (threadIdx.x < SHIFTS)
{
- sm_fShiftLoc[threadIdx.x][XX] = 0.0f;
- sm_fShiftLoc[threadIdx.x][YY] = 0.0f;
- sm_fShiftLoc[threadIdx.x][ZZ] = 0.0f;
+ sm_fShiftLoc[threadIdx.x] = make_float3(0.0f, 0.0f, 0.0f);
}
__syncthreads();
}
kernelParams.d_f, sm_fShiftLoc, kernelParams.pbcAiuc);
break;
case F_LJ14:
- pairs_gpu<calcVir, calcEner>(fTypeTid, numBonds, iatoms, kernelParams.d_forceParams,
- kernelParams.d_xq, kernelParams.d_f, sm_fShiftLoc,
- kernelParams.pbcAiuc, kernelParams.scaleFactor,
- &vtotVdw_loc, &vtotElec_loc);
+ pairs_gpu<calcVir, calcEner>(
+ fTypeTid, numBonds, iatoms, kernelParams.d_forceParams,
+ kernelParams.d_xq, kernelParams.d_f, sm_fShiftLoc, kernelParams.pbcAiuc,
+ kernelParams.electrostaticsScaleFactor, &vtotVdw_loc, &vtotElec_loc);
break;
}
break;
__syncthreads();
if (threadIdx.x < SHIFTS)
{
- fvec_inc_atomic(kernelParams.d_fShift[threadIdx.x], sm_fShiftLoc[threadIdx.x]);
+ atomicAdd(kernelParams.d_fShift[threadIdx.x], sm_fShiftLoc[threadIdx.x]);
}
}
}
template<bool calcVir, bool calcEner>
-void GpuBonded::Impl::launchKernel(const t_forcerec* fr, const matrix box)
+void GpuBonded::Impl::launchKernel()
{
GMX_ASSERT(haveInteractions_,
"Cannot launch bonded GPU kernels unless bonded GPU work was scheduled");
- static_assert(TPB_BONDED >= SHIFTS,
- "TPB_BONDED must be >= SHIFTS for the virial kernel (calcVir=true)");
-
- PbcAiuc pbcAiuc;
- setPbcAiuc(fr->bMolPBC ? ePBC2npbcdim(fr->ePBC) : 0, box, &pbcAiuc);
int fTypeRangeEnd = kernelParams_.fTypeRangeEnd[numFTypesOnGpu - 1];
return;
}
- KernelLaunchConfig config;
- config.blockSize[0] = TPB_BONDED;
- config.blockSize[1] = 1;
- config.blockSize[2] = 1;
- config.gridSize[0] = (fTypeRangeEnd + TPB_BONDED) / TPB_BONDED;
- config.gridSize[1] = 1;
- config.gridSize[2] = 1;
- config.stream = stream_;
-
- auto kernelPtr = exec_kernel_gpu<calcVir, calcEner>;
- kernelParams_.scaleFactor = fr->ic->epsfac * fr->fudgeQQ;
- kernelParams_.pbcAiuc = pbcAiuc;
+ auto kernelPtr = exec_kernel_gpu<calcVir, calcEner>;
- const auto kernelArgs = prepareGpuKernelArguments(kernelPtr, config, &kernelParams_);
+ const auto kernelArgs = prepareGpuKernelArguments(kernelPtr, kernelLaunchConfig_, &kernelParams_);
- launchGpuKernel(kernelPtr, config, nullptr, "exec_kernel_gpu<calcVir, calcEner>", kernelArgs);
+ launchGpuKernel(kernelPtr, kernelLaunchConfig_, deviceStream_, nullptr,
+ "exec_kernel_gpu<calcVir, calcEner>", kernelArgs);
}
-void GpuBonded::launchKernel(const t_forcerec* fr, const gmx::StepWorkload& stepWork, const matrix box)
+void GpuBonded::launchKernel(const gmx::StepWorkload& stepWork)
{
if (stepWork.computeEnergy)
{
// When we need the energy, we also need the virial
- impl_->launchKernel<true, true>(fr, box);
+ impl_->launchKernel<true, true>();
}
else if (stepWork.computeVirial)
{
- impl_->launchKernel<true, false>(fr, box);
+ impl_->launchKernel<true, false>();
}
else
{
- impl_->launchKernel<false, false>(fr, box);
+ impl_->launchKernel<false, false>();
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/force.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/fcdata.h"
+#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
namespace
{
+using gmx::ArrayRef;
+
/*! \brief Return true if ftype is an explicit pair-listed LJ or
* COULOMB interaction type: bonded LJ (usually 1-4), or special
* listed non-bonded for FEP. */
/*! \brief Calculate one element of the list of bonded interactions
for this thread */
-real calc_one_bond(int thread,
- int ftype,
- const t_idef* idef,
- const WorkDivision& workDivision,
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const t_forcerec* fr,
- const t_pbc* pbc,
- const t_graph* g,
- gmx_grppairener_t* grpp,
- t_nrnb* nrnb,
- const real* lambda,
- real* dvdl,
- const t_mdatoms* md,
- t_fcdata* fcd,
- const gmx::StepWorkload& stepWork,
- int* global_atom_index)
+real calc_one_bond(int thread,
+ int ftype,
+ const InteractionDefinitions& idef,
+ ArrayRef<const int> iatoms,
+ const int numNonperturbedInteractions,
+ const WorkDivision& workDivision,
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const t_forcerec* fr,
+ const t_pbc* pbc,
+ gmx_grppairener_t* grpp,
+ t_nrnb* nrnb,
+ const real* lambda,
+ real* dvdl,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
+ const gmx::StepWorkload& stepWork,
+ int* global_atom_index)
{
- GMX_ASSERT(idef->ilsort == ilsortNO_FE || idef->ilsort == ilsortFE_SORTED,
+ GMX_ASSERT(idef.ilsort == ilsortNO_FE || idef.ilsort == ilsortFE_SORTED,
"The topology should be marked either as no FE or sorted on FE");
const bool havePerturbedInteractions =
- (idef->ilsort == ilsortFE_SORTED && idef->il[ftype].nr_nonperturbed < idef->il[ftype].nr);
+ (idef.ilsort == ilsortFE_SORTED && numNonperturbedInteractions < iatoms.ssize());
BondedKernelFlavor flavor =
selectBondedKernelFlavor(stepWork, fr->use_simd_kernels, havePerturbedInteractions);
int efptFTYPE;
efptFTYPE = efptBONDED;
}
- const int nat1 = interaction_function[ftype].nratoms + 1;
- const int nbonds = idef->il[ftype].nr / nat1;
- const t_iatom* iatoms = idef->il[ftype].iatoms;
+ const int nat1 = interaction_function[ftype].nratoms + 1;
+ const int nbonds = iatoms.ssize() / nat1;
- GMX_ASSERT(fr->gpuBonded != nullptr || workDivision.end(ftype) == idef->il[ftype].nr,
+ GMX_ASSERT(fr->gpuBonded != nullptr || workDivision.end(ftype) == iatoms.ssize(),
"The thread division should match the topology");
const int nb0 = workDivision.bound(ftype, thread);
const int nbn = workDivision.bound(ftype, thread + 1) - nb0;
+ ArrayRef<const t_iparams> iparams = idef.iparams;
+
real v = 0;
if (!isPairInteraction(ftype))
{
nice to account to its own subtimer, but first
wallcycle needs to be extended to support calling from
multiple threads. */
- v = cmap_dihs(nbn, iatoms + nb0, idef->iparams, idef->cmap_grid, x, f, fshift, pbc, g,
- lambda[efptFTYPE], &(dvdl[efptFTYPE]), md, fcd, global_atom_index);
+ v = cmap_dihs(nbn, iatoms.data() + nb0, iparams.data(), &idef.cmap_grid, x, f, fshift,
+ pbc, lambda[efptFTYPE], &(dvdl[efptFTYPE]), md, fcd, global_atom_index);
}
else
{
- v = calculateSimpleBond(ftype, nbn, iatoms + nb0, idef->iparams, x, f, fshift, pbc, g,
- lambda[efptFTYPE], &(dvdl[efptFTYPE]), md, fcd,
+ v = calculateSimpleBond(ftype, nbn, iatoms.data() + nb0, iparams.data(), x, f, fshift,
+ pbc, lambda[efptFTYPE], &(dvdl[efptFTYPE]), md, fcd,
global_atom_index, flavor);
}
}
/* TODO The execution time for pairs might be nice to account
to its own subtimer, but first wallcycle needs to be
extended to support calling from multiple threads. */
- do_pairs(ftype, nbn, iatoms + nb0, idef->iparams, x, f, fshift, pbc, g, lambda, dvdl, md,
- fr, havePerturbedInteractions, stepWork, grpp, global_atom_index);
+ do_pairs(ftype, nbn, iatoms.data() + nb0, iparams.data(), x, f, fshift, pbc, lambda, dvdl,
+ md, fr, havePerturbedInteractions, stepWork, grpp, global_atom_index);
}
if (thread == 0)
/*! \brief Compute the bonded part of the listed forces, parallelized over threads
*/
-static void calcBondedForces(const t_idef* idef,
- const rvec x[],
- const t_forcerec* fr,
- const t_pbc* pbc_null,
- const t_graph* g,
- rvec* fshiftMasterBuffer,
- gmx_enerdata_t* enerd,
- t_nrnb* nrnb,
- const real* lambda,
- real* dvdl,
- const t_mdatoms* md,
- t_fcdata* fcd,
- const gmx::StepWorkload& stepWork,
- int* global_atom_index)
+static void calcBondedForces(const InteractionDefinitions& idef,
+ const rvec x[],
+ const t_forcerec* fr,
+ const t_pbc* pbc_null,
+ rvec* fshiftMasterBuffer,
+ gmx_enerdata_t* enerd,
+ t_nrnb* nrnb,
+ const real* lambda,
+ real* dvdl,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
+ const gmx::StepWorkload& stepWork,
+ int* global_atom_index)
{
bonded_threading_t* bt = fr->bondedThreading;
/* Loop over all bonded force types to calculate the bonded forces */
for (ftype = 0; (ftype < F_NRE); ftype++)
{
- if (idef->il[ftype].nr > 0 && ftype_is_bonded_potential(ftype))
+ const InteractionList& ilist = idef.il[ftype];
+ if (!ilist.empty() && ftype_is_bonded_potential(ftype))
{
- v = calc_one_bond(thread, ftype, idef, fr->bondedThreading->workDivision, x, ft,
- fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdlt, md, fcd,
- stepWork, global_atom_index);
+ ArrayRef<const int> iatoms = gmx::makeConstArrayRef(ilist.iatoms);
+ v = calc_one_bond(thread, ftype, idef, iatoms, idef.numNonperturbedInteractions[ftype],
+ fr->bondedThreading->workDivision, x, ft, fshift, fr, pbc_null,
+ grpp, nrnb, lambda, dvdlt, md, fcd, stepWork, global_atom_index);
epot[ftype] += v;
}
}
}
}
-bool haveRestraints(const t_idef& idef, const t_fcdata& fcd)
+bool haveRestraints(const InteractionDefinitions& idef, const t_fcdata& fcd)
{
- return ((idef.il[F_POSRES].nr > 0) || (idef.il[F_FBPOSRES].nr > 0) || fcd.orires.nr > 0
+ return (!idef.il[F_POSRES].empty() || !idef.il[F_FBPOSRES].empty() || fcd.orires.nr > 0
|| fcd.disres.nres > 0);
}
return fr.bondedThreading->haveBondeds;
}
-bool haveCpuListedForces(const t_forcerec& fr, const t_idef& idef, const t_fcdata& fcd)
+bool haveCpuListedForces(const t_forcerec& fr, const InteractionDefinitions& idef, const t_fcdata& fcd)
{
return haveCpuBondeds(fr) || haveRestraints(idef, fcd);
}
-void calc_listed(const t_commrec* cr,
- const gmx_multisim_t* ms,
- struct gmx_wallcycle* wcycle,
- const t_idef* idef,
- const rvec x[],
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_pbc* pbc_full,
- const struct t_graph* g,
- gmx_enerdata_t* enerd,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- t_fcdata* fcd,
- int* global_atom_index,
- const gmx::StepWorkload& stepWork)
+namespace
{
- const t_pbc* pbc_null;
- bonded_threading_t* bt = fr->bondedThreading;
-
- if (fr->bMolPBC)
- {
- pbc_null = pbc;
- }
- else
- {
- pbc_null = nullptr;
- }
-
- if (haveRestraints(*idef, *fcd))
- {
- /* TODO Use of restraints triggers further function calls
- inside the loop over calc_one_bond(), but those are too
- awkward to account to this subtimer properly in the present
- code. We don't test / care much about performance with
- restraints, anyway. */
- wallcycle_sub_start(wcycle, ewcsRESTRAINTS);
- if (idef->il[F_POSRES].nr > 0)
- {
- posres_wrapper(nrnb, idef, pbc_full, x, enerd, lambda, fr, &forceOutputs->forceWithVirial());
- }
-
- if (idef->il[F_FBPOSRES].nr > 0)
- {
- fbposres_wrapper(nrnb, idef, pbc_full, x, enerd, fr, &forceOutputs->forceWithVirial());
- }
-
- /* Do pre force calculation stuff which might require communication */
- if (fcd->orires.nr > 0)
- {
- /* This assertion is to ensure we have whole molecules.
- * Unfortunately we do not have an mdrun state variable that tells
- * us if molecules in x are not broken over PBC, so we have to make
- * do with checking graph!=nullptr, which should tell us if we made
- * molecules whole before calling the current function.
- */
- GMX_RELEASE_ASSERT(fr->ePBC == epbcNONE || g != nullptr,
- "With orientation restraints molecules should be whole");
- enerd->term[F_ORIRESDEV] = calc_orires_dev(ms, idef->il[F_ORIRES].nr, idef->il[F_ORIRES].iatoms,
- idef->iparams, md, x, pbc_null, fcd, hist);
- }
- if (fcd->disres.nres > 0)
- {
- calc_disres_R_6(cr, ms, idef->il[F_DISRES].nr, idef->il[F_DISRES].iatoms, x, pbc_null,
- fcd, hist);
- }
-
- wallcycle_sub_stop(wcycle, ewcsRESTRAINTS);
- }
+/*! \brief Calculates all listed force interactions. */
+void calc_listed(struct gmx_wallcycle* wcycle,
+ const InteractionDefinitions& idef,
+ const rvec x[],
+ gmx::ForceOutputs* forceOutputs,
+ const t_forcerec* fr,
+ const t_pbc* pbc,
+ gmx_enerdata_t* enerd,
+ t_nrnb* nrnb,
+ const real* lambda,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
+ int* global_atom_index,
+ const gmx::StepWorkload& stepWork)
+{
+ bonded_threading_t* bt = fr->bondedThreading;
if (haveCpuBondeds(*fr))
{
/* The dummy array is to have a place to store the dhdl at other values
of lambda, which will be thrown away in the end */
real dvdl[efptNR] = { 0 };
- calcBondedForces(idef, x, fr, pbc_null, g,
+ calcBondedForces(idef, x, fr, fr->bMolPBC ? pbc : nullptr,
as_rvec_array(forceWithShiftForces.shiftForces().data()), enerd, nrnb,
lambda, dvdl, md, fcd, stepWork, global_atom_index);
wallcycle_sub_stop(wcycle, ewcsLISTED);
}
}
-void calc_listed_lambda(const t_idef* idef,
- const rvec x[],
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_graph* g,
- gmx_grppairener_t* grpp,
- real* epot,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- t_fcdata* fcd,
- int* global_atom_index)
+/*! \brief As calc_listed(), but only determines the potential energy
+ * for the perturbed interactions.
+ *
+ * The shift forces in fr are not affected.
+ */
+void calc_listed_lambda(const InteractionDefinitions& idef,
+ const rvec x[],
+ const t_forcerec* fr,
+ const struct t_pbc* pbc,
+ gmx_grppairener_t* grpp,
+ real* epot,
+ gmx::ArrayRef<real> dvdl,
+ t_nrnb* nrnb,
+ const real* lambda,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
+ int* global_atom_index)
{
real v;
- real dvdl_dum[efptNR] = { 0 };
rvec4* f;
rvec* fshift;
const t_pbc* pbc_null;
- t_idef idef_fe;
WorkDivision& workDivision = fr->bondedThreading->foreignLambdaWorkDivision;
if (fr->bMolPBC)
pbc_null = nullptr;
}
- /* Copy the whole idef, so we can modify the contents locally */
- idef_fe = *idef;
-
/* We already have the forces, so we use temp buffers here */
// TODO: Get rid of these allocations by using permanent force buffers
snew(f, fr->natoms_force);
{
if (ftype_is_bonded_potential(ftype))
{
- const t_ilist& ilist = idef->il[ftype];
- /* Create a temporary t_ilist with only perturbed interactions */
- t_ilist& ilist_fe = idef_fe.il[ftype];
- ilist_fe.iatoms = ilist.iatoms + ilist.nr_nonperturbed;
- ilist_fe.nr_nonperturbed = 0;
- ilist_fe.nr = ilist.nr - ilist.nr_nonperturbed;
- /* Set the work range of thread 0 to the perturbed bondeds */
- workDivision.setBound(ftype, 0, 0);
- workDivision.setBound(ftype, 1, ilist_fe.nr);
-
- if (ilist_fe.nr > 0)
+ const InteractionList& ilist = idef.il[ftype];
+ /* Create a temporary iatom list with only perturbed interactions */
+ const int numNonperturbed = idef.numNonperturbedInteractions[ftype];
+ ArrayRef<const int> iatomsPerturbed = gmx::constArrayRefFromArray(
+ ilist.iatoms.data() + numNonperturbed, ilist.size() - numNonperturbed);
+ if (!iatomsPerturbed.empty())
{
+ /* Set the work range of thread 0 to the perturbed bondeds */
+ workDivision.setBound(ftype, 0, 0);
+ workDivision.setBound(ftype, 1, iatomsPerturbed.ssize());
+
gmx::StepWorkload tempFlags;
tempFlags.computeEnergy = true;
- v = calc_one_bond(0, ftype, &idef_fe, workDivision, x, f, fshift, fr, pbc_null, g,
- grpp, nrnb, lambda, dvdl_dum, md, fcd, tempFlags, global_atom_index);
+ v = calc_one_bond(0, ftype, idef, iatomsPerturbed, iatomsPerturbed.ssize(),
+ workDivision, x, f, fshift, fr, pbc_null, grpp, nrnb, lambda,
+ dvdl.data(), md, fcd, tempFlags, global_atom_index);
epot[ftype] += v;
}
}
sfree(f);
}
-void do_force_listed(struct gmx_wallcycle* wcycle,
- const matrix box,
- const t_lambda* fepvals,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- const t_idef* idef,
- const rvec x[],
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_graph* graph,
- gmx_enerdata_t* enerd,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- t_fcdata* fcd,
- int* global_atom_index,
- const gmx::StepWorkload& stepWork)
-{
- t_pbc pbc_full; /* Full PBC is needed for position restraints */
+} // namespace
+void do_force_listed(struct gmx_wallcycle* wcycle,
+ const matrix box,
+ const t_lambda* fepvals,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ const InteractionDefinitions& idef,
+ const rvec x[],
+ gmx::ArrayRef<const gmx::RVec> xWholeMolecules,
+ history_t* hist,
+ gmx::ForceOutputs* forceOutputs,
+ const t_forcerec* fr,
+ const struct t_pbc* pbc,
+ gmx_enerdata_t* enerd,
+ t_nrnb* nrnb,
+ const real* lambda,
+ const t_mdatoms* md,
+ t_fcdata* fcd,
+ int* global_atom_index,
+ const gmx::StepWorkload& stepWork)
+{
if (!stepWork.computeListedForces)
{
return;
}
- if ((idef->il[F_POSRES].nr > 0) || (idef->il[F_FBPOSRES].nr > 0))
+ t_pbc pbc_full; /* Full PBC is needed for position restraints */
+ if (haveRestraints(idef, *fcd))
{
- /* Not enough flops to bother counting */
- set_pbc(&pbc_full, fr->ePBC, box);
+ if (!idef.il[F_POSRES].empty() || !idef.il[F_FBPOSRES].empty())
+ {
+ /* Not enough flops to bother counting */
+ set_pbc(&pbc_full, fr->pbcType, box);
+ }
+
+ /* TODO Use of restraints triggers further function calls
+ inside the loop over calc_one_bond(), but those are too
+ awkward to account to this subtimer properly in the present
+ code. We don't test / care much about performance with
+ restraints, anyway. */
+ wallcycle_sub_start(wcycle, ewcsRESTRAINTS);
+
+ if (!idef.il[F_POSRES].empty())
+ {
+ posres_wrapper(nrnb, idef, &pbc_full, x, enerd, lambda, fr, &forceOutputs->forceWithVirial());
+ }
+
+ if (!idef.il[F_FBPOSRES].empty())
+ {
+ fbposres_wrapper(nrnb, idef, &pbc_full, x, enerd, fr, &forceOutputs->forceWithVirial());
+ }
+
+ /* Do pre force calculation stuff which might require communication */
+ if (fcd->orires.nr > 0)
+ {
+ GMX_ASSERT(!xWholeMolecules.empty(), "Need whole molecules for orienation restraints");
+ enerd->term[F_ORIRESDEV] = calc_orires_dev(
+ ms, idef.il[F_ORIRES].size(), idef.il[F_ORIRES].iatoms.data(), idef.iparams.data(),
+ md, xWholeMolecules, x, fr->bMolPBC ? pbc : nullptr, fcd, hist);
+ }
+ if (fcd->disres.nres > 0)
+ {
+ calc_disres_R_6(cr, ms, idef.il[F_DISRES].size(), idef.il[F_DISRES].iatoms.data(), x,
+ fr->bMolPBC ? pbc : nullptr, fcd, hist);
+ }
+
+ wallcycle_sub_stop(wcycle, ewcsRESTRAINTS);
}
- calc_listed(cr, ms, wcycle, idef, x, hist, forceOutputs, fr, pbc, &pbc_full, graph, enerd, nrnb,
- lambda, md, fcd, global_atom_index, stepWork);
+
+ calc_listed(wcycle, idef, x, forceOutputs, fr, pbc, enerd, nrnb, lambda, md, fcd,
+ global_atom_index, stepWork);
/* Check if we have to determine energy differences
* at foreign lambda's.
*/
if (fepvals->n_lambda > 0 && stepWork.computeDhdl)
{
- posres_wrapper_lambda(wcycle, fepvals, idef, &pbc_full, x, enerd, lambda, fr);
-
- if (idef->ilsort != ilsortNO_FE)
+ real dvdl[efptNR] = { 0 };
+ if (!idef.il[F_POSRES].empty())
+ {
+ posres_wrapper_lambda(wcycle, fepvals, idef, &pbc_full, x, enerd, lambda, fr);
+ }
+ if (idef.ilsort != ilsortNO_FE)
{
wallcycle_sub_start(wcycle, ewcsLISTED_FEP);
- if (idef->ilsort != ilsortFE_SORTED)
+ if (idef.ilsort != ilsortFE_SORTED)
{
gmx_incons("The bonded interactions are not sorted for free energy");
}
{
lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i - 1]);
}
- calc_listed_lambda(idef, x, fr, pbc, graph, &(enerd->foreign_grpp),
- enerd->foreign_term, nrnb, lam_i, md, fcd, global_atom_index);
+ calc_listed_lambda(idef, x, fr, pbc, &(enerd->foreign_grpp), enerd->foreign_term,
+ dvdl, nrnb, lam_i, md, fcd, global_atom_index);
sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
+ for (int j = 0; j < efptNR; j++)
+ {
+ enerd->dhdlLambda[i] += dvdl[j];
+ dvdl[j] = 0;
+ }
}
wallcycle_sub_stop(wcycle, ewcsLISTED_FEP);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_grppairener_t;
struct gmx_multisim_t;
class history_t;
+class InteractionDefinitions;
struct t_commrec;
struct t_fcdata;
struct t_forcerec;
-struct t_idef;
-struct t_graph;
struct t_lambda;
struct t_mdatoms;
struct t_nrnb;
{
class ForceOutputs;
class StepWorkload;
+template<typename>
+class ArrayRef;
} // namespace gmx
//! Type of CPU function to compute a bonded interaction.
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
//! Getter for finding a callable CPU function to compute an \c ftype interaction.
BondedFunction bondedFunction(int ftype);
-/*! \brief Calculates all listed force interactions.
- *
- * Note that pbc_full is used only for position restraints, and is
- * not initialized if there are none. */
-void calc_listed(const t_commrec* cr,
- const gmx_multisim_t* ms,
- struct gmx_wallcycle* wcycle,
- const t_idef* idef,
- const rvec x[],
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_pbc* pbc_full,
- const struct t_graph* g,
- gmx_enerdata_t* enerd,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- struct t_fcdata* fcd,
- int* ddgatindex,
- const gmx::StepWorkload& stepWork);
-
-/*! \brief As calc_listed(), but only determines the potential energy
- * for the perturbed interactions.
- *
- * The shift forces in fr are not affected. */
-void calc_listed_lambda(const t_idef* idef,
- const rvec x[],
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_graph* g,
- gmx_grppairener_t* grpp,
- real* epot,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- struct t_fcdata* fcd,
- int* global_atom_index);
-
/*! \brief Do all aspects of energy and force calculations for mdrun
- * on the set of listed interactions */
-void do_force_listed(struct gmx_wallcycle* wcycle,
- const matrix box,
- const t_lambda* fepvals,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- const t_idef* idef,
- const rvec x[],
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- const t_forcerec* fr,
- const struct t_pbc* pbc,
- const struct t_graph* graph,
- gmx_enerdata_t* enerd,
- t_nrnb* nrnb,
- const real* lambda,
- const t_mdatoms* md,
- struct t_fcdata* fcd,
- int* global_atom_index,
- const gmx::StepWorkload& stepWork);
+ * on the set of listed interactions
+ *
+ * xWholeMolecules only needs to contain whole molecules when orientation
+ * restraints need to be computed and can be empty otherwise.
+ */
+void do_force_listed(struct gmx_wallcycle* wcycle,
+ const matrix box,
+ const t_lambda* fepvals,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ const InteractionDefinitions& idef,
+ const rvec x[],
+ gmx::ArrayRef<const gmx::RVec> xWholeMolecules,
+ history_t* hist,
+ gmx::ForceOutputs* forceOutputs,
+ const t_forcerec* fr,
+ const struct t_pbc* pbc,
+ gmx_enerdata_t* enerd,
+ t_nrnb* nrnb,
+ const real* lambda,
+ const t_mdatoms* md,
+ struct t_fcdata* fcd,
+ int* global_atom_index,
+ const gmx::StepWorkload& stepWork);
/*! \brief Returns true if there are position, distance or orientation restraints. */
-bool haveRestraints(const t_idef& idef, const t_fcdata& fcd);
+bool haveRestraints(const InteractionDefinitions& idef, const t_fcdata& fcd);
/*! \brief Returns true if there are CPU (i.e. not GPU-offloaded) bonded interactions to compute. */
bool haveCpuBondeds(const t_forcerec& fr);
* NOTE: the current implementation returns true if there are position restraints
* or any bonded interactions computed on the CPU.
*/
-bool haveCpuListedForces(const t_forcerec& fr, const t_idef& idef, const t_fcdata& fcd);
+bool haveCpuListedForces(const t_forcerec& fr, const InteractionDefinitions& idef, const t_fcdata& fcd);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief struct for passing all data required for a function type */
typedef struct
{
- const t_ilist* il; /**< pointer to t_ilist entry corresponding to ftype */
- int ftype; /**< the function type index */
- int nat; /**< nr of atoms involved in a single ftype interaction */
+ const InteractionList* il; /**< pointer to t_ilist entry corresponding to ftype */
+ int ftype; /**< the function type index */
+ int nat; /**< nr of atoms involved in a single ftype interaction */
} ilist_data_t;
/*! \brief Divides listed interactions over threads
for (f = 0; f < numType; f++)
{
/* Sum #bondeds*#atoms_per_bond over all bonded types */
- nat_tot += ild[f].il->nr / (ild[f].nat + 1) * ild[f].nat;
+ nat_tot += ild[f].il->size() / (ild[f].nat + 1) * ild[f].nat;
/* The start bound for thread 0 is 0 for all interactions */
ind[f] = 0;
/* Initialize the next atom index array */
- assert(ild[f].il->nr > 0);
+ assert(!ild[f].il->empty());
at_ind[f] = ild[f].il->iatoms[1];
}
nat_sum += ild[f_min].nat;
/* Update the first unassigned atom index for this type */
- if (ind[f_min] < ild[f_min].il->nr)
+ if (ind[f_min] < ild[f_min].il->size())
{
at_ind[f_min] = ild[f_min].il->iatoms[ind[f_min] + 1];
}
for (f = 0; f < numType; f++)
{
- assert(ind[f] == ild[f].il->nr);
+ assert(ind[f] == ild[f].il->size());
}
}
//! Return whether function type \p ftype in \p idef has perturbed interactions
-static bool ftypeHasPerturbedEntries(const t_idef& idef, int ftype)
+static bool ftypeHasPerturbedEntries(const InteractionDefinitions& idef, int ftype)
{
GMX_ASSERT(idef.ilsort == ilsortNO_FE || idef.ilsort == ilsortFE_SORTED,
"Perturbed interations should be sorted here");
- const t_ilist& ilist = idef.il[ftype];
+ const InteractionList& ilist = idef.il[ftype];
- return (idef.ilsort != ilsortNO_FE && ilist.nr_nonperturbed != ilist.nr);
+ return (idef.ilsort != ilsortNO_FE && idef.numNonperturbedInteractions[ftype] != ilist.size());
}
//! Divides bonded interactions over threads and GPU
-static void divide_bondeds_over_threads(bonded_threading_t* bt, bool useGpuForBondeds, const t_idef& idef)
+static void divide_bondeds_over_threads(bonded_threading_t* bt,
+ bool useGpuForBondeds,
+ const InteractionDefinitions& idef)
{
ilist_data_t ild[F_NRE];
GMX_ASSERT(bt->nthreads > 0, "Must have positive number of threads");
const int numThreads = bt->nthreads;
+ gmx::ArrayRef<const t_iparams> iparams = idef.iparams;
+
bt->haveBondeds = false;
int numType = 0;
size_t fTypeGpuIndex = 0;
continue;
}
- const t_ilist& il = idef.il[fType];
- int nrToAssignToCpuThreads = il.nr;
+ const InteractionList& il = idef.il[fType];
+ int nrToAssignToCpuThreads = il.size();
if (useGpuForBondeds && fTypeGpuIndex < gmx::fTypesOnGpu.size()
&& gmx::fTypesOnGpu[fTypeGpuIndex] == fType)
* end up on the same thread.
*/
while (nr_t > 0 && nr_t < nrToAssignToCpuThreads
- && idef.iparams[il.iatoms[nr_t]].disres.label
- == idef.iparams[il.iatoms[nr_t - stride]].disres.label)
+ && iparams[il.iatoms[nr_t]].disres.label
+ == iparams[il.iatoms[nr_t - stride]].disres.label)
{
nr_t += stride;
}
fprintf(debug, "Division of bondeds over threads:\n");
for (f = 0; f < F_NRE; f++)
{
- if (ftype_is_bonded_potential(f) && idef.il[f].nr > 0)
+ if (ftype_is_bonded_potential(f) && !idef.il[f].empty())
{
int t;
}
//! Construct a reduction mask for which parts (blocks) of the force array are touched on which thread task
-static void calc_bonded_reduction_mask(int natoms,
- f_thread_t* f_thread,
- const t_idef& idef,
- int thread,
- const bonded_threading_t& bondedThreading)
+static void calc_bonded_reduction_mask(int natoms,
+ f_thread_t* f_thread,
+ const InteractionDefinitions& idef,
+ int thread,
+ const bonded_threading_t& bondedThreading)
{
static_assert(BITMASK_SIZE == GMX_OPENMP_MAX_THREADS,
"For the error message below we assume these two are equal.");
if (bondedThreading.nthreads > BITMASK_SIZE)
{
-#pragma omp master
gmx_fatal(FARGS,
"You are using %d OpenMP threads, which is larger than GMX_OPENMP_MAX_THREADS "
"(%d). Decrease the number of OpenMP threads or rebuild GROMACS with a larger "
"value for GMX_OPENMP_MAX_THREADS passed to CMake.",
bondedThreading.nthreads, GMX_OPENMP_MAX_THREADS);
-#pragma omp barrier
}
GMX_ASSERT(bondedThreading.nthreads <= BITMASK_SIZE,
"We need at least nthreads bits in the mask");
{
if (ftype_is_bonded_potential(ftype))
{
- int nb = idef.il[ftype].nr;
+ int nb = idef.il[ftype].size();
if (nb > 0)
{
int nat1 = interaction_function[ftype].nratoms + 1;
}
}
-void setup_bonded_threading(bonded_threading_t* bt, int numAtoms, bool useGpuForBondeds, const t_idef& idef)
+void setup_bonded_threading(bonded_threading_t* bt,
+ int numAtoms,
+ bool useGpuForBondeds,
+ const InteractionDefinitions& idef)
{
int ctot = 0;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdio>
struct bonded_threading_t;
-struct t_idef;
+class InteractionDefinitions;
/*! \brief Divide the listed interactions over the threads and GPU
*
* This should be called each time the bonded setup changes;
* i.e. at start-up without domain decomposition and at DD.
*/
-void setup_bonded_threading(bonded_threading_t* bt, int numAtoms, bool useGpuForBondes, const t_idef& idef);
+void setup_bonded_threading(bonded_threading_t* bt,
+ int numAtoms,
+ bool useGpuForBondes,
+ const InteractionDefinitions& idef);
//! Destructor.
void tear_down_bonded_threading(bonded_threading_t* bt);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/pleasecite.h"
#include "gromacs/utility/smalloc.h"
+using gmx::ArrayRef;
+using gmx::RVec;
+
// TODO This implementation of ensemble orientation restraints is nasty because
// a user can't just do multi-sim with single-sim orientation restraints.
int nmol;
while (const InteractionLists* il = gmx_mtop_ilistloop_next(iloop, &nmol))
{
- if (nmol > 1 && (*il)[F_ORIRES].size() > 0)
+ const int numOrires = (*il)[F_ORIRES].size();
+ if (nmol > 1 && numOrires > 0)
{
gmx_fatal(FARGS,
"Found %d copies of a molecule with orientation restrains while the current "
nmol);
}
- for (int i = 0; i < (*il)[F_ORIRES].size(); i += 3)
+ for (int i = 0; i < numOrires; i += 3)
{
int type = (*il)[F_ORIRES].iatoms[i];
int ex = mtop->ffparams.iparams[type].orires.ex;
const t_iatom forceatoms[],
const t_iparams ip[],
const t_mdatoms* md,
+ ArrayRef<const RVec> xWholeMolecules,
const rvec x[],
const t_pbc* pbc,
t_fcdata* fcd,
{
if (md->cORF[i] == 0)
{
- copy_rvec(x[i], xtmp[j]);
+ copy_rvec(xWholeMolecules[i], xtmp[j]);
mref[j] = md->massT[i];
for (int d = 0; d < DIM; d++)
{
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real gmx_unused lambda,
real gmx_unused* dvdlambda,
const t_mdatoms gmx_unused* md,
int gmx_unused* global_atom_index)
{
int ex, power, ki = CENTRAL;
- ivec dt;
real r2, invr, invr2, fc, smooth_fc, dev, devins, pfac;
rvec r, Sr, fij;
real vtot;
fij[i] = -pfac * dev * (4 * Sr[i] - 2 * (2 + power) * invr2 * iprod(Sr, r) * r[i]);
}
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
- ki = IVEC2IS(dt);
- }
-
for (int i = 0; i < DIM; i++)
{
f[ai][i] += fij[i];
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_oriresdata;
class t_state;
+namespace gmx
+{
+template<typename>
+class ArrayRef;
+} // namespace gmx
+
/*! \brief
* Decides whether orientation restraints can work, and initializes
* all the orientation restraint stuff in *od (and assumes *od is
*
* Returns the weighted RMS deviation of the orientation restraints.
*/
-real calc_orires_dev(const gmx_multisim_t* ms,
- int nfa,
- const t_iatom fa[],
- const t_iparams ip[],
- const t_mdatoms* md,
- const rvec x[],
- const t_pbc* pbc,
- t_fcdata* fcd,
- history_t* hist);
+real calc_orires_dev(const gmx_multisim_t* ms,
+ int nfa,
+ const t_iatom fa[],
+ const t_iparams ip[],
+ const t_mdatoms* md,
+ gmx::ArrayRef<const gmx::RVec> xWholeMolecules,
+ const rvec x[],
+ const t_pbc* pbc,
+ t_fcdata* fcd,
+ history_t* hist);
/*! \brief
* Diagonalizes the order tensor(s) of the orienation restraints.
rvec4 f[],
rvec fshift[],
const t_pbc* pbc,
- const t_graph* g,
real lambda,
real* dvdlambda,
const t_mdatoms* md,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/listed_forces/bonded.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/vec.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/group.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/nblist.h"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/pbc_simd.h"
#include "gromacs/simd/simd.h"
real fscal_vdw[2], fscal_elec[2];
real velec[2], vvdw[2];
int i, ntab;
- const real half = 0.5;
- const real minusOne = -1.0;
- const real one = 1.0;
- const real two = 2.0;
- const real six = 6.0;
- const real fourtyeight = 48.0;
+ const real half = 0.5;
+ const real minusOne = -1.0;
+ const real one = 1.0;
+ const real two = 2.0;
+ const real six = 6.0;
qq[0] = qqA;
qq[1] = qqB;
rpm2 = r2 * r2; /* r4 */
rp = rpm2 * r2; /* r6 */
}
- else if (sc_r_power == fourtyeight)
- {
- rp = r2 * r2 * r2; /* r6 */
- rp = rp * rp; /* r12 */
- rp = rp * rp; /* r24 */
- rp = rp * rp; /* r48 */
- rpm2 = rp / r2; /* r46 */
- }
else
{
rp = std::pow(r2, half * sc_r_power); /* not currently supported as input, but can handle it */
{
sigma_pow[i] = sigma6[i];
}
- else if (sc_r_power == fourtyeight)
- {
- sigma_pow[i] = sigma6[i] * sigma6[i]; /* sigma^12 */
- sigma_pow[i] = sigma_pow[i] * sigma_pow[i]; /* sigma^24 */
- sigma_pow[i] = sigma_pow[i] * sigma_pow[i]; /* sigma^48 */
- }
else
{ /* not really supported as input, but in here for testing the general case*/
sigma_pow[i] = std::pow(sigma2[i], sc_r_power / 2);
/*! \brief Calculate pair interactions, supports all types and conditions. */
template<BondedKernelFlavor flavor>
-static real do_pairs_general(int ftype,
- int nbonds,
- const t_iatom iatoms[],
- const t_iparams iparams[],
- const rvec x[],
- rvec4 f[],
- rvec fshift[],
- const struct t_pbc* pbc,
- const struct t_graph* g,
- const real* lambda,
- real* dvdl,
- const t_mdatoms* md,
- const t_forcerec* fr,
- gmx_grppairener_t* grppener,
- int* global_atom_index)
+static real do_pairs_general(int ftype,
+ int nbonds,
+ const t_iatom iatoms[],
+ const t_iparams iparams[],
+ const rvec x[],
+ rvec4 f[],
+ rvec fshift[],
+ const struct t_pbc* pbc,
+ const real* lambda,
+ real* dvdl,
+ const t_mdatoms* md,
+ const t_forcerec* fr,
+ gmx_grppairener_t* grppener,
+ int* global_atom_index)
{
real qq, c6, c12;
rvec dx;
- ivec dt;
int i, itype, ai, aj, gid;
int fshift_index;
real r2;
if (computeVirial(flavor))
{
- if (g)
- {
- /* Correct the shift forces using the graph */
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
- fshift_index = IVEC2IS(dt);
- }
if (fshift_index != CENTRAL)
{
rvec_inc(fshift[fshift_index], dx);
rvec4 f[],
rvec fshift[],
const struct t_pbc* pbc,
- const struct t_graph* g,
const real* lambda,
real* dvdl,
const t_mdatoms* md,
}
else
{
- set_pbc(&pbc_no, epbcNONE, nullptr);
+ set_pbc(&pbc_no, PbcType::No, nullptr);
pbc_nonnull = &pbc_no;
}
else if (stepWork.computeVirial)
{
do_pairs_general<BondedKernelFlavor::ForcesAndVirialAndEnergy>(
- ftype, nbonds, iatoms, iparams, x, f, fshift, pbc, g, lambda, dvdl, md, fr,
- grppener, global_atom_index);
+ ftype, nbonds, iatoms, iparams, x, f, fshift, pbc, lambda, dvdl, md, fr, grppener,
+ global_atom_index);
}
else
{
do_pairs_general<BondedKernelFlavor::ForcesAndEnergy>(ftype, nbonds, iatoms, iparams, x, f,
- fshift, pbc, g, lambda, dvdl, md, fr,
+ fshift, pbc, lambda, dvdl, md, fr,
grppener, global_atom_index);
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_LISTED_FORCES_PAIRS_H
#include "gromacs/math/vec.h"
-#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
struct gmx_grppairener_t;
struct t_forcerec;
-struct t_graph;
struct t_pbc;
namespace gmx
rvec4 f[],
rvec fshift[],
const struct t_pbc* pbc,
- const struct t_graph* g,
const real* lambda,
real* dvdl,
const t_mdatoms* md,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::ForceWithVirial* forceWithVirial,
const t_pbc* pbc,
int refcoord_scaling,
- int ePBC,
+ PbcType pbcType,
const rvec com)
/* compute flat-bottomed positions restraints */
{
rvec com_sc, rdist, dx, dpdl, fm;
gmx_bool bInvert;
- npbcdim = ePBC2npbcdim(ePBC);
- GMX_ASSERT((ePBC == epbcNONE) == (npbcdim == 0), "");
+ npbcdim = numPbcDimensions(pbcType);
+ GMX_ASSERT((pbcType == PbcType::No) == (npbcdim == 0), "");
if (refcoord_scaling == erscCOM)
{
clear_rvec(com_sc);
real lambda,
real* dvdlambda,
int refcoord_scaling,
- int ePBC,
+ PbcType pbcType,
const rvec comA,
const rvec comB)
{
real kk, fm;
rvec comA_sc, comB_sc, rdist, dpdl, dx;
- npbcdim = ePBC2npbcdim(ePBC);
- GMX_ASSERT((ePBC == epbcNONE) == (npbcdim == 0), "");
+ npbcdim = numPbcDimensions(pbcType);
+ GMX_ASSERT((pbcType == PbcType::No) == (npbcdim == 0), "");
if (refcoord_scaling == erscCOM)
{
clear_rvec(comA_sc);
} // namespace
-void posres_wrapper(t_nrnb* nrnb,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec* x,
- gmx_enerdata_t* enerd,
- const real* lambda,
- const t_forcerec* fr,
- gmx::ForceWithVirial* forceWithVirial)
+void posres_wrapper(t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec* x,
+ gmx_enerdata_t* enerd,
+ const real* lambda,
+ const t_forcerec* fr,
+ gmx::ForceWithVirial* forceWithVirial)
{
real v, dvdl;
dvdl = 0;
- v = posres<true>(idef->il[F_POSRES].nr, idef->il[F_POSRES].iatoms, idef->iparams_posres, x,
- forceWithVirial, fr->ePBC == epbcNONE ? nullptr : pbc, lambda[efptRESTRAINT],
- &dvdl, fr->rc_scaling, fr->ePBC, fr->posres_com, fr->posres_comB);
+ v = posres<true>(idef.il[F_POSRES].size(), idef.il[F_POSRES].iatoms.data(),
+ idef.iparams_posres.data(), x, forceWithVirial,
+ fr->pbcType == PbcType::No ? nullptr : pbc, lambda[efptRESTRAINT], &dvdl,
+ fr->rc_scaling, fr->pbcType, fr->posres_com, fr->posres_comB);
enerd->term[F_POSRES] += v;
/* If just the force constant changes, the FEP term is linear,
* but if k changes, it is not.
*/
enerd->dvdl_nonlin[efptRESTRAINT] += dvdl;
- inc_nrnb(nrnb, eNR_POSRES, gmx::exactDiv(idef->il[F_POSRES].nr, 2));
+ inc_nrnb(nrnb, eNR_POSRES, gmx::exactDiv(idef.il[F_POSRES].size(), 2));
}
-void posres_wrapper_lambda(struct gmx_wallcycle* wcycle,
- const t_lambda* fepvals,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec x[],
- gmx_enerdata_t* enerd,
- const real* lambda,
- const t_forcerec* fr)
+void posres_wrapper_lambda(struct gmx_wallcycle* wcycle,
+ const t_lambda* fepvals,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec x[],
+ gmx_enerdata_t* enerd,
+ const real* lambda,
+ const t_forcerec* fr)
{
real v;
- if (0 == idef->il[F_POSRES].nr)
- {
- return;
- }
-
wallcycle_sub_start_nocount(wcycle, ewcsRESTRAINTS);
for (size_t i = 0; i < enerd->enerpart_lambda.size(); i++)
{
- real dvdl_dum = 0, lambda_dum;
-
- lambda_dum = (i == 0 ? lambda[efptRESTRAINT] : fepvals->all_lambda[efptRESTRAINT][i - 1]);
- v = posres<false>(idef->il[F_POSRES].nr, idef->il[F_POSRES].iatoms, idef->iparams_posres, x,
- nullptr, fr->ePBC == epbcNONE ? nullptr : pbc, lambda_dum, &dvdl_dum,
- fr->rc_scaling, fr->ePBC, fr->posres_com, fr->posres_comB);
+ real dvdl = 0;
+
+ const real lambda_dum =
+ (i == 0 ? lambda[efptRESTRAINT] : fepvals->all_lambda[efptRESTRAINT][i - 1]);
+ v = posres<false>(idef.il[F_POSRES].size(), idef.il[F_POSRES].iatoms.data(),
+ idef.iparams_posres.data(), x, nullptr,
+ fr->pbcType == PbcType::No ? nullptr : pbc, lambda_dum, &dvdl,
+ fr->rc_scaling, fr->pbcType, fr->posres_com, fr->posres_comB);
enerd->enerpart_lambda[i] += v;
+ enerd->dhdlLambda[i] += dvdl;
}
wallcycle_sub_stop(wcycle, ewcsRESTRAINTS);
}
/*! \brief Helper function that wraps calls to fbposres for
free-energy perturbation */
-void fbposres_wrapper(t_nrnb* nrnb,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec* x,
- gmx_enerdata_t* enerd,
- const t_forcerec* fr,
- gmx::ForceWithVirial* forceWithVirial)
+void fbposres_wrapper(t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec* x,
+ gmx_enerdata_t* enerd,
+ const t_forcerec* fr,
+ gmx::ForceWithVirial* forceWithVirial)
{
real v;
- v = fbposres(idef->il[F_FBPOSRES].nr, idef->il[F_FBPOSRES].iatoms, idef->iparams_fbposres, x,
- forceWithVirial, fr->ePBC == epbcNONE ? nullptr : pbc, fr->rc_scaling, fr->ePBC,
- fr->posres_com);
+ v = fbposres(idef.il[F_FBPOSRES].size(), idef.il[F_FBPOSRES].iatoms.data(),
+ idef.iparams_fbposres.data(), x, forceWithVirial,
+ fr->pbcType == PbcType::No ? nullptr : pbc, fr->rc_scaling, fr->pbcType, fr->posres_com);
enerd->term[F_FBPOSRES] += v;
- inc_nrnb(nrnb, eNR_FBPOSRES, gmx::exactDiv(idef->il[F_FBPOSRES].nr, 2));
+ inc_nrnb(nrnb, eNR_FBPOSRES, gmx::exactDiv(idef.il[F_FBPOSRES].size(), 2));
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_enerdata_t;
struct gmx_wallcycle;
struct t_forcerec;
-struct t_idef;
+class InteractionDefinitions;
struct t_lambda;
struct t_nrnb;
struct t_pbc;
}
/*! \brief Helper function that wraps calls to posres */
-void posres_wrapper(t_nrnb* nrnb,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec* x,
- gmx_enerdata_t* enerd,
- const real* lambda,
- const t_forcerec* fr,
- gmx::ForceWithVirial* forceWithVirial);
+void posres_wrapper(t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec* x,
+ gmx_enerdata_t* enerd,
+ const real* lambda,
+ const t_forcerec* fr,
+ gmx::ForceWithVirial* forceWithVirial);
/*! \brief Helper function that wraps calls to posres for free-energy
pertubation */
-void posres_wrapper_lambda(struct gmx_wallcycle* wcycle,
- const t_lambda* fepvals,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec x[],
- gmx_enerdata_t* enerd,
- const real* lambda,
- const t_forcerec* fr);
+void posres_wrapper_lambda(struct gmx_wallcycle* wcycle,
+ const t_lambda* fepvals,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec x[],
+ gmx_enerdata_t* enerd,
+ const real* lambda,
+ const t_forcerec* fr);
/*! \brief Helper function that wraps calls to fbposres for
free-energy perturbation */
-void fbposres_wrapper(t_nrnb* nrnb,
- const t_idef* idef,
- const struct t_pbc* pbc,
- const rvec* x,
- gmx_enerdata_t* enerd,
- const t_forcerec* fr,
- gmx::ForceWithVirial* forceWithVirial);
+void fbposres_wrapper(t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ const struct t_pbc* pbc,
+ const rvec* x,
+ gmx_enerdata_t* enerd,
+ const t_forcerec* fr,
+ gmx::ForceWithVirial* forceWithVirial);
#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2016,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(ListedForcesTest listed_forces-test
- bonded.cpp)
+ CPP_SOURCE_FILES
+ bonded.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
class ListedForcesTest :
- public ::testing::TestWithParam<std::tuple<iListInput, std::vector<gmx::RVec>, int>>
+ public ::testing::TestWithParam<std::tuple<iListInput, std::vector<gmx::RVec>, PbcType>>
{
protected:
matrix box_;
t_pbc pbc_;
std::vector<gmx::RVec> x_;
- int epbc_;
+ PbcType pbcType_;
iListInput input_;
test::TestReferenceData refData_;
test::TestReferenceChecker checker_;
ListedForcesTest() : checker_(refData_.rootChecker())
{
- input_ = std::get<0>(GetParam());
- x_ = std::get<1>(GetParam());
- epbc_ = std::get<2>(GetParam());
+ input_ = std::get<0>(GetParam());
+ x_ = std::get<1>(GetParam());
+ pbcType_ = std::get<2>(GetParam());
clear_mat(box_);
box_[0][0] = box_[1][1] = box_[2][2] = 1.5;
- set_pbc(&pbc_, epbc_, box_);
+ set_pbc(&pbc_, pbcType_, box_);
// We need quite specific tolerances here since angle functions
// etc. are not very precise and reproducible.
test::FloatingPointTolerance tolerance(test::FloatingPointTolerance(
}
void testOneIfunc(test::TestReferenceChecker* checker, const std::vector<t_iatom>& iatoms, const real lambda)
{
- SCOPED_TRACE(std::string("Testing PBC ") + epbc_names[epbc_]);
+ SCOPED_TRACE(std::string("Testing PBC ") + c_pbcTypeNames[pbcType_]);
std::vector<int> ddgatindex = { 0, 1, 2, 3 };
std::vector<real> chargeA = { 1.5, -2.0, 1.5, -1.0 };
t_mdatoms mdatoms = { 0 };
mdatoms.chargeA = chargeA.data();
OutputQuantities output;
- output.energy = calculateSimpleBond(
- input_.ftype, iatoms.size(), iatoms.data(), &input_.iparams,
- as_rvec_array(x_.data()), output.f, output.fshift, &pbc_,
- /* const struct t_graph *g */ nullptr, lambda, &output.dvdlambda, &mdatoms,
- /* struct t_fcdata * */ nullptr, ddgatindex.data(),
- BondedKernelFlavor::ForcesAndVirialAndEnergy);
+ output.energy = calculateSimpleBond(input_.ftype, iatoms.size(), iatoms.data(),
+ &input_.iparams, as_rvec_array(x_.data()), output.f,
+ output.fshift, &pbc_, lambda, &output.dvdlambda, &mdatoms,
+ /* struct t_fcdata * */ nullptr, ddgatindex.data(),
+ BondedKernelFlavor::ForcesAndVirialAndEnergy);
// Internal consistency test of both test input
// and bonded functions.
EXPECT_TRUE((input_.fep || (output.dvdlambda == 0.0))) << "dvdlambda was " << output.dvdlambda;
};
//! PBC values for testing
-std::vector<int> c_pbcForTests = { epbcNONE, epbcXY, epbcXYZ };
+std::vector<PbcType> c_pbcForTests = { PbcType::No, PbcType::XY, PbcType::Xyz };
// Those tests give errors with the intel compiler and nothing else, so we disable them only there.
#ifndef __INTEL_COMPILER
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
file(GLOB MATH_SOURCES *.cpp)
set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${MATH_SOURCES} PARENT_SCOPE)
-# TODO: (https://redmine.gromacs.org/issues/988) Find a new convention for defining public API.
+# TODO: (https://gitlab.com/gromacs/gromacs/-/issues/988) Find a new convention for defining public API.
install(FILES
vectypes.h
DESTINATION include/gromacs/math)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
private:
- real evaluatePrefactor(real comparisonSquaredSum, real referenceSquaredSum)
+ static real evaluatePrefactor(real comparisonSquaredSum, real referenceSquaredSum)
{
GMX_ASSERT(comparisonSquaredSum > 0,
"Squared sum of comparison values needs to be larger than zero.");
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdspan/extensions.h"
#include "gromacs/utility/classhelpers.h"
-#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/real.h"
namespace gmx
/*! \brief
* The methods that determine how two densities are compared to one another.
*/
-enum class DensitySimilarityMeasureMethod
+enum class DensitySimilarityMeasureMethod : int
{
/*! \brief Measure similarity between densities as normalized inner product of their
* voxel values.
Count,
};
-//! Name the methods that may be used to evaluate similarity between densities
-const EnumerationArray<DensitySimilarityMeasureMethod, const char* const> c_densitySimilarityMeasureMethodNames = {
- { "inner-product", "relative-entropy", "cross-correlation" }
-};
-
/* Forward declaration of implementation class outside class to allow
* choose implementation class during construction of the DensitySimilarityMeasure*/
class DensitySimilarityMeasureImpl;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
DensityFittingForce::Impl::Impl(const GaussianSpreadKernelParameters::Shape& kernelShapeParameters) :
sigma_{ kernelShapeParameters.sigma_ },
- latticeSpreadRange_{ kernelShapeParameters.latticeSpreadRange() },
+ latticeSpreadRange_{ kernelShapeParameters.latticeSpreadRange()[XX],
+ kernelShapeParameters.latticeSpreadRange()[YY],
+ kernelShapeParameters.latticeSpreadRange()[ZZ] },
gauss1d_({ GaussianOn1DLattice(latticeSpreadRange_[XX], sigma_[XX]),
GaussianOn1DLattice(latticeSpreadRange_[YY], sigma_[YY]),
GaussianOn1DLattice(latticeSpreadRange_[ZZ], sigma_[ZZ]) })
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Type has a resize member function callable with size_t argument
template<typename T>
+// NOLINTNEXTLINE misc-definitions-in-headers
constexpr bool is_resizable_v = is_resizable<T>::value;
} // namespace detail
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(MathUnitTests math-test
- arrayrefwithpadding.cpp
- coordinatetransformation.cpp
- densityfit.cpp
- dofit.cpp
- exponentialmovingaverage.cpp
- functions.cpp
- gausstransform.cpp
- densityfittingforce.cpp
- invertmatrix.cpp
- matrix.cpp
- multidimarray.cpp
- paddedvector.cpp
- vectypes.cpp
- )
+ CPP_SOURCE_FILES
+ arrayrefwithpadding.cpp
+ coordinatetransformation.cpp
+ densityfit.cpp
+ dofit.cpp
+ exponentialmovingaverage.cpp
+ functions.cpp
+ gausstransform.cpp
+ densityfittingforce.cpp
+ invertmatrix.cpp
+ matrix.cpp
+ multidimarray.cpp
+ paddedvector.cpp
+ vectypes.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
EXPECT_LE(v.paddedSize(), vReserved.paddedSize());
}
+TYPED_TEST(PaddedVectorTest, ArrayRefConversionsAreIdentical)
+{
+ using VectorType = PaddedVector<typename TypeParam::value_type, TypeParam>;
+
+ VectorType v;
+ fillInput(&v, 1);
+
+ SCOPED_TRACE("Comparing different paths to create identical unpadded views");
+ compareViews(makeArrayRef(v), v.arrayRefWithPadding().unpaddedArrayRef());
+ compareViews(makeConstArrayRef(v), v.constArrayRefWithPadding().unpaddedConstArrayRef());
+ compareViews(makeConstArrayRef(v), v.constArrayRefWithPadding().unpaddedArrayRef());
+ compareViews(makeConstArrayRef(v), v.arrayRefWithPadding().unpaddedConstArrayRef());
+
+ SCOPED_TRACE("Comparing const to non-const unpadded views");
+ compareViewsIgnoreConst(makeArrayRef(v), makeConstArrayRef(v));
+}
+
TYPED_TEST(PaddedVectorTest, CanCopyAssign)
{
using VectorType = PaddedVector<typename TypeParam::value_type, TypeParam>;
w = v;
compareViews(v.arrayRefWithPadding().unpaddedArrayRef(), w.arrayRefWithPadding().unpaddedArrayRef());
- compareViews(makeArrayRef(v), makeArrayRef(v));
+ compareViews(makeArrayRef(v), makeArrayRef(w));
}
TYPED_TEST(PaddedVectorTest, CanMoveAssign)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
+//! Comparison for non-BasicVector ignoring const qualifiers
+template<typename T, typename U>
+typename std::enable_if<std::is_same<typename std::remove_const<T>::type, typename std::remove_const<U>::type>::value, void>::type
+compareViewsIgnoreConst(ArrayRef<T> input, ArrayRef<U> output)
+{
+ ASSERT_EQ(input.size(), output.size());
+ for (index i = 0; i != input.ssize(); ++i)
+ {
+ EXPECT_EQ(input[i], output[i]) << "for index " << i;
+ }
+}
+
//! Comparison overload for BasicVector<T>
template<typename T>
void compareViews(ArrayRef<BasicVector<T>> input, ArrayRef<BasicVector<T>> output)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
case eg2cNm: return x;
case eg2cBohr: return x * BOHR2NM;
case eg2cKcal_Mole: return x / CAL2JOULE;
- case eg2cHartree: return x * ONE_4PI_EPS0 / BOHR2NM;
+ case eg2cHartree: return x * ONE_4PI_EPS0 / BOHR2NM; // NOLINT bugprone-branch-clone
case eg2cHartree_e: return x * ONE_4PI_EPS0 / BOHR2NM;
case eg2cAngstrom3: return x * A2NM * A2NM * A2NM;
case eg2cCoulomb: return x / E_CHARGE;
case eg2cNm: return x;
case eg2cBohr: return x / BOHR2NM;
case eg2cKcal_Mole: return x * CAL2JOULE;
- case eg2cHartree: return x / (ONE_4PI_EPS0 / BOHR2NM);
+ case eg2cHartree: return x / (ONE_4PI_EPS0 / BOHR2NM); // NOLINT bugprone-branch-clone
case eg2cHartree_e: return x / (ONE_4PI_EPS0 / BOHR2NM);
case eg2cAngstrom3: return x / (A2NM * A2NM * A2NM);
case eg2cCoulomb: return x * E_CHARGE;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cmath>
#include <algorithm>
-
#include <cfenv>
//! Floating point exception set that we use and care about
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
endif()
if(GMX_USE_CUDA)
gmx_add_libgromacs_sources(
- lincs_cuda.cu
- settle_cuda.cu
- leapfrog_cuda.cu
- update_constrain_cuda_impl.cu
+ leapfrog_gpu.cu
+ lincs_gpu.cu
+ settle_gpu.cu
+ update_constrain_gpu_impl.cu
)
endif()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
std::unique_ptr<BoxDeformation> prepareBoxDeformation(const matrix& initialBox,
- t_commrec* cr,
+ DDRole ddRole,
+ NumRanks numRanks,
+ MPI_Comm communicator,
const t_inputrec& inputrec)
{
if (!inputrecDeform(&inputrec))
matrix box;
// Only the rank that read the tpr has the global state, and thus
// the initial box, so we pass that around.
- if (SIMMASTER(cr))
+ // (numRanks != NumRanks::Multiple helps clang static analyzer to
+ // understand that box is defined in all cases)
+ if (ddRole == DDRole::Master || numRanks != NumRanks::Multiple)
{
copy_mat(initialBox, box);
}
- if (PAR(cr))
+ if (numRanks == NumRanks::Multiple)
{
- gmx_bcast(sizeof(box), box, cr);
+ gmx_bcast(sizeof(box), box, communicator);
}
return std::make_unique<BoxDeformation>(inputrec.delta_t, inputrec.init_step, inputrec.deform, box);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/classhelpers.h"
+#include "gromacs/utility/gmxmpi.h"
-struct t_commrec;
struct t_inputrec;
+enum class DDRole;
+enum class NumRanks;
namespace gmx
{
* unsupported combination.
*/
std::unique_ptr<BoxDeformation> prepareBoxDeformation(const matrix& initialBox,
- t_commrec* cr,
+ DDRole ddRole,
+ NumRanks numRanks,
+ MPI_Comm communicator,
const t_inputrec& inputrec);
} // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "broadcaststructs.h"
#include "gromacs/fileio/tpxio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/state.h"
template<typename AllocatorType>
-static void bcastPaddedRVecVector(const t_commrec* cr, gmx::PaddedVector<gmx::RVec, AllocatorType>* v, int numAtoms)
+static void bcastPaddedRVecVector(MPI_Comm communicator,
+ gmx::PaddedVector<gmx::RVec, AllocatorType>* v,
+ int numAtoms)
{
v->resizeWithPadding(numAtoms);
- nblock_bc(cr, makeArrayRef(*v));
+ nblock_bc(communicator, makeArrayRef(*v));
}
-void broadcastStateWithoutDynamics(const t_commrec* cr, t_state* state)
+void broadcastStateWithoutDynamics(MPI_Comm communicator,
+ bool useDomainDecomposition,
+ bool isParallelRun,
+ t_state* state)
{
- GMX_RELEASE_ASSERT(!DOMAINDECOMP(cr),
+ GMX_RELEASE_ASSERT(!useDomainDecomposition,
"broadcastStateWithoutDynamics should only be used for special cases "
"without domain decomposition");
- if (!PAR(cr))
+ if (!isParallelRun)
{
return;
}
/* Broadcasts the state sizes and flags from the master to all ranks
* in cr->mpi_comm_mygroup.
*/
- block_bc(cr, state->natoms);
- block_bc(cr, state->flags);
+ block_bc(communicator, state->natoms);
+ block_bc(communicator, state->flags);
for (int i = 0; i < estNR; i++)
{
{
switch (i)
{
- case estLAMBDA: nblock_bc(cr, efptNR, state->lambda.data()); break;
- case estFEPSTATE: block_bc(cr, state->fep_state); break;
- case estBOX: block_bc(cr, state->box); break;
- case estX: bcastPaddedRVecVector(cr, &state->x, state->natoms); break;
+ case estLAMBDA: nblock_bc(communicator, efptNR, state->lambda.data()); break;
+ case estFEPSTATE: block_bc(communicator, state->fep_state); break;
+ case estBOX: block_bc(communicator, state->box); break;
+ case estX: bcastPaddedRVecVector(communicator, &state->x, state->natoms); break;
default:
GMX_RELEASE_ASSERT(false,
"The state has a dynamic entry, while no dynamic entries "
}
}
-static void bc_tpxheader(const t_commrec* cr, TpxFileHeader* tpx)
+static void bc_tpxheader(MPI_Comm communicator, TpxFileHeader* tpx)
{
- block_bc(cr, tpx->bIr);
- block_bc(cr, tpx->bBox);
- block_bc(cr, tpx->bTop);
- block_bc(cr, tpx->bX);
- block_bc(cr, tpx->bV);
- block_bc(cr, tpx->bF);
- block_bc(cr, tpx->natoms);
- block_bc(cr, tpx->ngtc);
- block_bc(cr, tpx->lambda);
- block_bc(cr, tpx->fep_state);
- block_bc(cr, tpx->sizeOfTprBody);
- block_bc(cr, tpx->fileVersion);
- block_bc(cr, tpx->fileGeneration);
- block_bc(cr, tpx->isDouble);
+ block_bc(communicator, tpx->bIr);
+ block_bc(communicator, tpx->bBox);
+ block_bc(communicator, tpx->bTop);
+ block_bc(communicator, tpx->bX);
+ block_bc(communicator, tpx->bV);
+ block_bc(communicator, tpx->bF);
+ block_bc(communicator, tpx->natoms);
+ block_bc(communicator, tpx->ngtc);
+ block_bc(communicator, tpx->lambda);
+ block_bc(communicator, tpx->fep_state);
+ block_bc(communicator, tpx->sizeOfTprBody);
+ block_bc(communicator, tpx->fileVersion);
+ block_bc(communicator, tpx->fileGeneration);
+ block_bc(communicator, tpx->isDouble);
}
-static void bc_tprCharBuffer(const t_commrec* cr, std::vector<char>* charBuffer)
+static void bc_tprCharBuffer(MPI_Comm communicator, bool isMasterRank, std::vector<char>* charBuffer)
{
int elements = charBuffer->size();
- block_bc(cr, elements);
+ block_bc(communicator, elements);
- nblock_abc(cr, elements, charBuffer);
+ nblock_abc(isMasterRank, communicator, elements, charBuffer);
}
-void init_parallel(t_commrec* cr, t_inputrec* inputrec, gmx_mtop_t* mtop, PartialDeserializedTprFile* partialDeserializedTpr)
+void init_parallel(MPI_Comm communicator,
+ bool isMasterRank,
+ t_inputrec* inputrec,
+ gmx_mtop_t* mtop,
+ PartialDeserializedTprFile* partialDeserializedTpr)
{
- bc_tpxheader(cr, &partialDeserializedTpr->header);
- bc_tprCharBuffer(cr, &partialDeserializedTpr->body);
- if (!MASTER(cr))
+ bc_tpxheader(communicator, &partialDeserializedTpr->header);
+ bc_tprCharBuffer(communicator, isMasterRank, &partialDeserializedTpr->body);
+ if (!isMasterRank)
{
completeTprDeserialization(partialDeserializedTpr, inputrec, mtop);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
#include "gromacs/gmxlib/network.h"
-#include "gromacs/mdtypes/commrec.h"
#include "gromacs/utility/arrayref.h"
-#include "gromacs/utility/smalloc.h"
struct gmx_mtop_t;
-struct t_commrec;
struct t_inputrec;
struct PartialDeserializedTprFile;
class t_state;
-//! Convenience wrapper for gmx_bcast of a single value.
+//! Convenience wrapper for gmx_bcast to communicator of a single value.
template<typename T>
-void block_bc(const t_commrec* cr, T& data)
+void block_bc(MPI_Comm communicator, T& data)
{
- gmx_bcast(sizeof(T), static_cast<void*>(&data), cr);
+ gmx_bcast(sizeof(T), static_cast<void*>(&data), communicator);
}
-//! Convenience wrapper for gmx_bcast of a C-style array.
+//! Convenience wrapper for gmx_bcast to communicator of a C-style array.
template<typename T>
-void nblock_bc(const t_commrec* cr, int numElements, T* data)
+void nblock_bc(MPI_Comm communicator, int numElements, T* data)
{
- gmx_bcast(numElements * sizeof(T), static_cast<void*>(data), cr);
+ gmx_bcast(numElements * sizeof(T), static_cast<void*>(data), communicator);
}
-//! Convenience wrapper for gmx_bcast of an ArrayRef<T>
+//! Convenience wrapper for gmx_bcast to communicator of an ArrayRef<T>
template<typename T>
-void nblock_bc(const t_commrec* cr, gmx::ArrayRef<T> data)
+void nblock_bc(MPI_Comm communicator, gmx::ArrayRef<T> data)
{
- gmx_bcast(data.size() * sizeof(T), static_cast<void*>(data.data()), cr);
+ gmx_bcast(data.size() * sizeof(T), static_cast<void*>(data.data()), communicator);
}
//! Convenience wrapper for allocation with snew of vectors that need allocation on non-master ranks.
template<typename T>
-void snew_bc(const t_commrec* cr, T*& data, int numElements)
+void snew_bc(bool isMasterRank, T*& data, int numElements)
{
- if (!MASTER(cr))
+ if (!isMasterRank)
{
snew(data, numElements);
}
}
//! Convenience wrapper for gmx_bcast of a C-style array which needs allocation on non-master ranks.
template<typename T>
-void nblock_abc(const t_commrec* cr, int numElements, T** v)
+void nblock_abc(bool isMasterRank, MPI_Comm communicator, int numElements, T** v)
{
- snew_bc(cr, v, numElements);
- nblock_bc(cr, numElements, *v);
+ snew_bc(isMasterRank, v, numElements);
+ nblock_bc(communicator, numElements, *v);
}
//! Convenience wrapper for gmx_bcast of a std::vector which needs resizing on non-master ranks.
template<typename T>
-void nblock_abc(const t_commrec* cr, int numElements, std::vector<T>* v)
+void nblock_abc(bool isMasterRank, MPI_Comm communicator, int numElements, std::vector<T>* v)
{
- if (!MASTER(cr))
+ if (!isMasterRank)
{
v->resize(numElements);
}
- gmx_bcast(numElements * sizeof(T), v->data(), cr);
+ gmx_bcast(numElements * sizeof(T), v->data(), communicator);
}
//! \brief Broadcasts the, non-dynamic, state from the master to all ranks in cr->mpi_comm_mygroup
//
// This is intended to be used with MPI parallelization without
// domain decompostion (currently with NM and TPI).
-void broadcastStateWithoutDynamics(const t_commrec* cr, t_state* state);
+void broadcastStateWithoutDynamics(MPI_Comm communicator,
+ bool useDomainDecomposition,
+ bool isParallelRun,
+ t_state* state);
//! \brief Broadcast inputrec and mtop and allocate node-specific settings
-void init_parallel(t_commrec* cr,
+void init_parallel(MPI_Comm communicator,
+ bool isMasterRank,
t_inputrec* inputrec,
gmx_mtop_t* mtop,
PartialDeserializedTprFile* partialDeserializedTpr);
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
for (const int atom : block)
{
const auto& ilist = moltype.ilist[F_SETTLE];
- GMX_RELEASE_ASSERT(ilist.size() > 0,
+ GMX_RELEASE_ASSERT(!ilist.empty(),
"There should be at least one settle in this moltype");
for (int i = 0; i < ilist.size(); i += 1 + NRAL(F_SETTLE))
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
-void calc_mu(int start,
- int homenr,
- gmx::ArrayRef<gmx::RVec> x,
- const real q[],
- const real qB[],
- int nChargePerturbed,
- dvec mu,
- dvec mu_B)
+void calc_mu(int start,
+ int homenr,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const real q[],
+ const real qB[],
+ int nChargePerturbed,
+ dvec mu,
+ dvec mu_B)
{
int end, m;
double mu_x, mu_y, mu_z;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
-void calc_mu(int start,
- int homenr,
- gmx::ArrayRef<gmx::RVec> x,
- const real q[],
- const real qB[],
- int nChargePerturbed,
- dvec mu,
- dvec mu_B);
+void calc_mu(int start,
+ int homenr,
+ gmx::ArrayRef<const gmx::RVec> x,
+ const real q[],
+ const real qB[],
+ int nChargePerturbed,
+ dvec mu,
+ dvec mu_B);
gmx_bool read_mu(FILE* fp, rvec mu, real* vol);
/* Return true on succes */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vectypes.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/utility/gmxassert.h"
}
}
-
-static void
-lo_fcv(int i0, int i1, const real x[], const real f[], tensor vir, const int is[], const real box[], gmx_bool bTriclinic)
-{
- int i, i3, tx, ty, tz;
- real xx, yy, zz;
- real dvxx = 0, dvxy = 0, dvxz = 0, dvyx = 0, dvyy = 0, dvyz = 0, dvzx = 0, dvzy = 0, dvzz = 0;
-
- if (bTriclinic)
- {
- for (i = i0; (i < i1); i++)
- {
- i3 = DIM * i;
- tx = is[i3 + XX];
- ty = is[i3 + YY];
- tz = is[i3 + ZZ];
-
- xx = x[i3 + XX] - tx * box[XXXX] - ty * box[YYXX] - tz * box[ZZXX];
- dvxx += xx * f[i3 + XX];
- dvxy += xx * f[i3 + YY];
- dvxz += xx * f[i3 + ZZ];
-
- yy = x[i3 + YY] - ty * box[YYYY] - tz * box[ZZYY];
- dvyx += yy * f[i3 + XX];
- dvyy += yy * f[i3 + YY];
- dvyz += yy * f[i3 + ZZ];
-
- zz = x[i3 + ZZ] - tz * box[ZZZZ];
- dvzx += zz * f[i3 + XX];
- dvzy += zz * f[i3 + YY];
- dvzz += zz * f[i3 + ZZ];
- }
- }
- else
- {
- for (i = i0; (i < i1); i++)
- {
- i3 = DIM * i;
- tx = is[i3 + XX];
- ty = is[i3 + YY];
- tz = is[i3 + ZZ];
-
- xx = x[i3 + XX] - tx * box[XXXX];
- dvxx += xx * f[i3 + XX];
- dvxy += xx * f[i3 + YY];
- dvxz += xx * f[i3 + ZZ];
-
- yy = x[i3 + YY] - ty * box[YYYY];
- dvyx += yy * f[i3 + XX];
- dvyy += yy * f[i3 + YY];
- dvyz += yy * f[i3 + ZZ];
-
- zz = x[i3 + ZZ] - tz * box[ZZZZ];
- dvzx += zz * f[i3 + XX];
- dvzy += zz * f[i3 + YY];
- dvzz += zz * f[i3 + ZZ];
- }
- }
-
- upd_vir(vir[XX], dvxx, dvxy, dvxz);
- upd_vir(vir[YY], dvyx, dvyy, dvyz);
- upd_vir(vir[ZZ], dvzx, dvzy, dvzz);
-}
-
-void f_calc_vir(int i0, int i1, const rvec x[], const rvec f[], tensor vir, const t_graph* g, const matrix box)
+void f_calc_vir(int i0, int i1, const rvec x[], const rvec f[], tensor vir, const matrix box)
{
- int start, end;
-
- if (g && (g->nnodes > 0))
- {
- /* Calculate virial for bonded forces only when they belong to
- * this node.
- */
- start = std::max(i0, g->at_start);
- end = std::min(i1, g->at_end);
- lo_fcv(start, end, x[0], f[0], vir, g->ishift[0], box[0], TRICLINIC(box));
-
- /* If not all atoms are bonded, calculate their virial contribution
- * anyway, without shifting back their coordinates.
- * Note the nifty pointer arithmetic...
- */
- if (start > i0)
- {
- calc_vir(start - i0, x + i0, f + i0, vir, FALSE, box);
- }
- if (end < i1)
- {
- calc_vir(i1 - end, x + end, f + end, vir, FALSE, box);
- }
- }
- else
- {
- calc_vir(i1 - i0, x + i0, f + i0, vir, FALSE, box);
- }
+ calc_vir(i1 - i0, x + i0, f + i0, vir, FALSE, box);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vectypes.h"
-struct t_graph;
struct t_pbc;
void calc_vir(int nxf, const rvec x[], const rvec f[], tensor vir, bool bScrewPBC, const matrix box);
/* Calculate virial for nxf atoms, and add it to vir */
-void f_calc_vir(int i0, int i1, const rvec x[], const rvec f[], tensor vir, const t_graph* g, const rvec shift_vec[]);
+void f_calc_vir(int i0, int i1, const rvec x[], const rvec f[], tensor vir, const rvec shift_vec[]);
/* Calculate virial taking periodicity into account */
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/timing/wallcycle.h"
-#include "gromacs/topology/block.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/mtop_lookup.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/pleasecite.h"
-#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/txtdump.h"
namespace gmx
int numConstraints,
int numSettles);
~Impl();
- void setConstraints(const gmx_localtop_t& top, const t_mdatoms& md);
- bool apply(bool bLog,
- bool bEner,
- int64_t step,
- int delta_step,
- real step_scaling,
- rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- real lambda,
- real* dvdlambda,
- rvec* v,
- tensor* vir,
- ConstraintVariable econq);
+ void setConstraints(gmx_localtop_t* top, const t_mdatoms& md);
+ bool apply(bool bLog,
+ bool bEner,
+ int64_t step,
+ int delta_step,
+ real step_scaling,
+ ArrayRefWithPadding<RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ real lambda,
+ real* dvdlambda,
+ ArrayRefWithPadding<RVec> v,
+ tensor* vir,
+ ConstraintVariable econq);
//! The total number of constraints.
int ncon_tot = 0;
//! The number of flexible constraints.
int nflexcon = 0;
//! A list of atoms to constraints for each moleculetype.
- std::vector<t_blocka> at2con_mt;
+ std::vector<ListOfLists<int>> at2con_mt;
//! A list of atoms to settles for each moleculetype
std::vector<std::vector<int>> at2settle_mt;
//! LINCS data.
Lincs* lincsd = nullptr; // TODO this should become a unique_ptr
//! SHAKE data.
- shakedata* shaked = nullptr;
+ std::unique_ptr<shakedata> shaked;
//! SETTLE data.
settledata* settled = nullptr;
//! The maximum number of warnings.
//! Pointer to the global topology - only used for printing warnings.
const gmx_mtop_t& mtop;
//! Parameters for the interactions in this domain.
- const t_idef* idef = nullptr;
+ const InteractionDefinitions* idef = nullptr;
//! Data about atoms in this domain.
const t_mdatoms& md;
//! Whether we need to do pbc for handling bonds.
}
//! Clears constraint quantities for atoms in nonlocal region.
-static void clear_constraint_quantity_nonlocal(gmx_domdec_t* dd, rvec* q)
+static void clear_constraint_quantity_nonlocal(gmx_domdec_t* dd, ArrayRef<RVec> q)
{
int nonlocal_at_start, nonlocal_at_end, at;
}
//! Writes out coordinates.
-static void write_constr_pdb(const char* fn,
- const char* title,
- const gmx_mtop_t& mtop,
- int start,
- int homenr,
- const t_commrec* cr,
- const rvec x[],
- const matrix box)
+static void write_constr_pdb(const char* fn,
+ const char* title,
+ const gmx_mtop_t& mtop,
+ int start,
+ int homenr,
+ const t_commrec* cr,
+ ArrayRef<const RVec> x,
+ const matrix box)
{
char fname[STRLEN];
FILE* out;
out = gmx_fio_fopen(fname, "w");
fprintf(out, "TITLE %s\n", title);
- gmx_write_pdb_box(out, -1, box);
+ gmx_write_pdb_box(out, PbcType::Unset, box);
int molb = 0;
for (i = start; i < start + homenr; i++)
{
}
//! Writes out domain contents to help diagnose crashes.
-static void dump_confs(FILE* log,
- int64_t step,
- const gmx_mtop_t& mtop,
- int start,
- int homenr,
- const t_commrec* cr,
- const rvec x[],
- rvec xprime[],
- const matrix box)
+static void dump_confs(FILE* log,
+ int64_t step,
+ const gmx_mtop_t& mtop,
+ int start,
+ int homenr,
+ const t_commrec* cr,
+ ArrayRef<const RVec> x,
+ ArrayRef<const RVec> xprime,
+ const matrix box)
{
char buf[STRLEN], buf2[22];
fprintf(stderr, "Wrote pdb files with previous and current coordinates\n");
}
-bool Constraints::apply(bool bLog,
- bool bEner,
- int64_t step,
- int delta_step,
- real step_scaling,
- rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- real lambda,
- real* dvdlambda,
- rvec* v,
- tensor* vir,
- ConstraintVariable econq)
+bool Constraints::apply(bool bLog,
+ bool bEner,
+ int64_t step,
+ int delta_step,
+ real step_scaling,
+ ArrayRefWithPadding<RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ real lambda,
+ real* dvdlambda,
+ ArrayRefWithPadding<RVec> v,
+ tensor* vir,
+ ConstraintVariable econq)
{
- return impl_->apply(bLog, bEner, step, delta_step, step_scaling, x, xprime, min_proj, box,
- lambda, dvdlambda, v, vir, econq);
+ return impl_->apply(bLog, bEner, step, delta_step, step_scaling, std::move(x), std::move(xprime),
+ min_proj, box, lambda, dvdlambda, std::move(v), vir, econq);
}
-bool Constraints::Impl::apply(bool bLog,
- bool bEner,
- int64_t step,
- int delta_step,
- real step_scaling,
- rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- real lambda,
- real* dvdlambda,
- rvec* v,
- tensor* vir,
- ConstraintVariable econq)
+bool Constraints::Impl::apply(bool bLog,
+ bool bEner,
+ int64_t step,
+ int delta_step,
+ real step_scaling,
+ ArrayRefWithPadding<RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ real lambda,
+ real* dvdlambda,
+ ArrayRefWithPadding<RVec> v,
+ tensor* vir,
+ ConstraintVariable econq)
{
bool bOK, bDump;
int start, homenr;
{
clear_mat(vir_r_m_dr);
}
- const t_ilist* settle = &idef->il[F_SETTLE];
- nsettle = settle->nr / (1 + NRAL(F_SETTLE));
+ const InteractionList& settle = idef->il[F_SETTLE];
+ nsettle = settle.size() / (1 + NRAL(F_SETTLE));
if (nsettle > 0)
{
* Note that PBC for constraints is different from PBC for bondeds.
* For constraints there is both forward and backward communication.
*/
- if (ir.ePBC != epbcNONE && (cr->dd || pbcHandlingRequired_)
+ if (ir.pbcType != PbcType::No && (cr->dd || pbcHandlingRequired_)
&& !(cr->dd && cr->dd->constraint_comm == nullptr))
{
/* With pbc=screw the screw has been changed to a shift
* by the constraint coordinate communication routine,
* so that here we can use normal pbc.
*/
- pbc_null = set_pbc_dd(&pbc, ir.ePBC, DOMAINDECOMP(cr) ? cr->dd->nc : nullptr, FALSE, box);
+ pbc_null = set_pbc_dd(&pbc, ir.pbcType, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, FALSE, box);
}
else
{
*/
if (cr->dd)
{
- dd_move_x_constraints(cr->dd, box, x, xprime, econq == ConstraintVariable::Positions);
+ dd_move_x_constraints(cr->dd, box, x.unpaddedArrayRef(), xprime.unpaddedArrayRef(),
+ econq == ConstraintVariable::Positions);
- if (v != nullptr)
+ if (!v.empty())
{
/* We need to initialize the non-local components of v.
* We never actually use these values, but we do increment them,
* so we should avoid uninitialized variables and overflows.
*/
- clear_constraint_quantity_nonlocal(cr->dd, v);
+ clear_constraint_quantity_nonlocal(cr->dd, v.unpaddedArrayRef());
}
}
if (lincsd != nullptr)
{
bOK = constrain_lincs(bLog || bEner, ir, step, lincsd, md, cr, ms, x, xprime, min_proj, box,
- pbc_null, lambda, dvdlambda, invdt, v, vir != nullptr, vir_r_m_dr,
- econq, nrnb, maxwarn, &warncount_lincs);
+ pbc_null, lambda, dvdlambda, invdt, v.unpaddedArrayRef(),
+ vir != nullptr, vir_r_m_dr, econq, nrnb, maxwarn, &warncount_lincs);
if (!bOK && maxwarn < INT_MAX)
{
if (log != nullptr)
if (shaked != nullptr)
{
- bOK = constrain_shake(log, shaked, md.invmass, *idef, ir, x, xprime, min_proj, nrnb, lambda,
- dvdlambda, invdt, v, vir != nullptr, vir_r_m_dr, maxwarn < INT_MAX, econq);
+ bOK = constrain_shake(log, shaked.get(), md.invmass, *idef, ir, x.unpaddedArrayRef(),
+ xprime.unpaddedArrayRef(), min_proj, pbc_null, nrnb, lambda,
+ dvdlambda, invdt, v.unpaddedArrayRef(), vir != nullptr, vir_r_m_dr,
+ maxwarn < INT_MAX, econq);
if (!bOK && maxwarn < INT_MAX)
{
clear_mat(vir_r_m_dr_th[th]);
}
- csettle(settled, nth, th, pbc_null, x[0], xprime[0], invdt, v ? v[0] : nullptr,
- vir != nullptr, th == 0 ? vir_r_m_dr : vir_r_m_dr_th[th],
+ csettle(settled, nth, th, pbc_null, x, xprime, invdt, v, vir != nullptr,
+ th == 0 ? vir_r_m_dr : vir_r_m_dr_th[th],
th == 0 ? &bSettleErrorHasOccurred0 : &bSettleErrorHasOccurred[th]);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
inc_nrnb(nrnb, eNR_SETTLE, nsettle);
- if (v != nullptr)
+ if (!v.empty())
{
inc_nrnb(nrnb, eNR_CONSTR_V, nsettle * 3);
}
if (start_th >= 0 && end_th - start_th > 0)
{
settle_proj(settled, econq, end_th - start_th,
- settle->iatoms + start_th * (1 + NRAL(F_SETTLE)), pbc_null,
- x, xprime, min_proj, calcvir_atom_end,
- th == 0 ? vir_r_m_dr : vir_r_m_dr_th[th]);
+ settle.iatoms.data() + start_th * (1 + NRAL(F_SETTLE)), pbc_null,
+ x.unpaddedArrayRef(), xprime.unpaddedArrayRef(), min_proj,
+ calcvir_atom_end, th == 0 ? vir_r_m_dr : vir_r_m_dr_th[th]);
}
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
if (bDump)
{
- dump_confs(log, step, mtop, start, homenr, cr, x, xprime, box);
+ dump_confs(log, step, mtop, start, homenr, cr, x.unpaddedArrayRef(),
+ xprime.unpaddedArrayRef(), box);
}
if (econq == ConstraintVariable::Positions)
{
t = ir.init_t;
}
- set_pbc(&pbc, ir.ePBC, box);
- pull_constraint(pull_work, &md, &pbc, cr, ir.delta_t, t, x, xprime, v, *vir);
+ set_pbc(&pbc, ir.pbcType, box);
+ pull_constraint(pull_work, &md, &pbc, cr, ir.delta_t, t,
+ as_rvec_array(x.unpaddedArrayRef().data()),
+ as_rvec_array(xprime.unpaddedArrayRef().data()),
+ as_rvec_array(v.unpaddedArrayRef().data()), *vir);
}
if (ed && delta_step > 0)
{
/* apply the essential dynamics constraints here */
- do_edsam(&ir, step, cr, xprime, v, box, ed);
+ do_edsam(&ir, step, cr, as_rvec_array(xprime.unpaddedArrayRef().data()),
+ as_rvec_array(v.unpaddedArrayRef().data()), box, ed);
}
}
wallcycle_stop(wcycle, ewcCONSTR);
- if (v != nullptr && md.cFREEZE)
+ if (!v.empty() && md.cFREEZE)
{
/* Set the velocities of frozen dimensions to zero */
+ ArrayRef<RVec> vRef = v.unpaddedArrayRef();
int gmx_unused numThreads = gmx_omp_nthreads_get(emntUpdate);
{
if (ir.opts.nFreeze[freezeGroup][d])
{
- v[i][d] = 0;
+ vRef[i][d] = 0;
}
}
}
* \param[in] numAtoms The number of atoms to construct the list for
* \param[in] ilists The interaction lists, size F_NRE
* \param[in] iparams Interaction parameters, can be null when
- * flexibleConstraintTreatment=Include \param[in] flexibleConstraintTreatment The flexible
- * constraint treatment, see enum above \returns a block struct with all constraints for each atom
+ * \p flexibleConstraintTreatment==Include
+ * \param[in] flexibleConstraintTreatment The flexible constraint treatment,
+ * see enum above
+ *
+ * \returns a block struct with all constraints for each atom
*/
-template<typename T>
-static t_blocka makeAtomsToConstraintsList(int numAtoms,
- const T* ilists,
- const t_iparams* iparams,
- FlexibleConstraintTreatment flexibleConstraintTreatment)
+static ListOfLists<int> makeAtomsToConstraintsList(int numAtoms,
+ ArrayRef<const InteractionList> ilists,
+ ArrayRef<const t_iparams> iparams,
+ FlexibleConstraintTreatment flexibleConstraintTreatment)
{
- GMX_ASSERT(flexibleConstraintTreatment == FlexibleConstraintTreatment::Include || iparams != nullptr,
+ GMX_ASSERT(flexibleConstraintTreatment == FlexibleConstraintTreatment::Include || !iparams.empty(),
"With flexible constraint detection we need valid iparams");
std::vector<int> count(numAtoms);
for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
{
- const T& ilist = ilists[ftype];
- const int stride = 1 + NRAL(ftype);
+ const InteractionList& ilist = ilists[ftype];
+ const int stride = 1 + NRAL(ftype);
for (int i = 0; i < ilist.size(); i += stride)
{
if (flexibleConstraintTreatment == FlexibleConstraintTreatment::Include
}
}
- t_blocka at2con;
- at2con.nr = numAtoms;
- at2con.nalloc_index = at2con.nr + 1;
- snew(at2con.index, at2con.nalloc_index);
- at2con.index[0] = 0;
+ std::vector<int> listRanges(numAtoms + 1);
for (int a = 0; a < numAtoms; a++)
{
- at2con.index[a + 1] = at2con.index[a] + count[a];
- count[a] = 0;
+ listRanges[a + 1] = listRanges[a] + count[a];
+ count[a] = 0;
}
- at2con.nra = at2con.index[at2con.nr];
- at2con.nalloc_a = at2con.nra;
- snew(at2con.a, at2con.nalloc_a);
+ std::vector<int> elements(listRanges[numAtoms]);
/* The F_CONSTRNC constraints have constraint numbers
* that continue after the last F_CONSTR constraint.
int numConstraints = 0;
for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
{
- const T& ilist = ilists[ftype];
- const int stride = 1 + NRAL(ftype);
+ const InteractionList& ilist = ilists[ftype];
+ const int stride = 1 + NRAL(ftype);
for (int i = 0; i < ilist.size(); i += stride)
{
if (flexibleConstraintTreatment == FlexibleConstraintTreatment::Include
{
for (int j = 1; j < 3; j++)
{
- int a = ilist.iatoms[i + j];
- at2con.a[at2con.index[a] + count[a]++] = numConstraints;
+ const int a = ilist.iatoms[i + j];
+ elements[listRanges[a] + count[a]++] = numConstraints;
}
}
numConstraints++;
}
}
- return at2con;
+ return ListOfLists<int>(std::move(listRanges), std::move(elements));
}
-t_blocka make_at2con(int numAtoms,
- const t_ilist* ilist,
- const t_iparams* iparams,
- FlexibleConstraintTreatment flexibleConstraintTreatment)
+ListOfLists<int> make_at2con(int numAtoms,
+ ArrayRef<const InteractionList> ilist,
+ ArrayRef<const t_iparams> iparams,
+ FlexibleConstraintTreatment flexibleConstraintTreatment)
{
return makeAtomsToConstraintsList(numAtoms, ilist, iparams, flexibleConstraintTreatment);
}
-t_blocka make_at2con(const gmx_moltype_t& moltype,
- gmx::ArrayRef<const t_iparams> iparams,
- FlexibleConstraintTreatment flexibleConstraintTreatment)
+ListOfLists<int> make_at2con(const gmx_moltype_t& moltype,
+ gmx::ArrayRef<const t_iparams> iparams,
+ FlexibleConstraintTreatment flexibleConstraintTreatment)
{
- return makeAtomsToConstraintsList(moltype.atoms.nr, moltype.ilist.data(), iparams.data(),
+ return makeAtomsToConstraintsList(moltype.atoms.nr, makeConstArrayRef(moltype.ilist), iparams,
flexibleConstraintTreatment);
}
//! Return the number of flexible constraints in the \c ilist and \c iparams.
-template<typename T>
-static int countFlexibleConstraintsTemplate(const T* ilist, const t_iparams* iparams)
+int countFlexibleConstraints(ArrayRef<const InteractionList> ilist, ArrayRef<const t_iparams> iparams)
{
int nflexcon = 0;
for (int ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
return nflexcon;
}
-int countFlexibleConstraints(const t_ilist* ilist, const t_iparams* iparams)
-{
- return countFlexibleConstraintsTemplate(ilist, iparams);
-}
-
//! Returns the index of the settle to which each atom belongs.
static std::vector<int> make_at2settle(int natoms, const InteractionList& ilist)
{
return at2s;
}
-void Constraints::Impl::setConstraints(const gmx_localtop_t& top, const t_mdatoms& md)
+void Constraints::Impl::setConstraints(gmx_localtop_t* top, const t_mdatoms& md)
{
- idef = &top.idef;
+ idef = &top->idef;
if (ncon_tot > 0)
{
*/
if (ir.eConstrAlg == econtLINCS)
{
- set_lincs(top.idef, md, EI_DYNAMICS(ir.eI), cr, lincsd);
+ set_lincs(*idef, md, EI_DYNAMICS(ir.eI), cr, lincsd);
}
if (ir.eConstrAlg == econtSHAKE)
{
{
// We are using the local topology, so there are only
// F_CONSTR constraints.
- make_shake_sblock_dd(shaked, &idef->il[F_CONSTR], cr->dd);
+ make_shake_sblock_dd(shaked.get(), idef->il[F_CONSTR]);
}
else
{
- make_shake_sblock_serial(shaked, idef, md);
+ make_shake_sblock_serial(shaked.get(), &top->idef, md);
}
}
}
if (settled)
{
- settle_set_constraints(settled, &idef->il[F_SETTLE], md);
+ settle_set_constraints(settled, idef->il[F_SETTLE], md);
}
/* Make a selection of the local atoms for essential dynamics */
}
}
-void Constraints::setConstraints(const gmx_localtop_t& top, const t_mdatoms& md)
+void Constraints::setConstraints(gmx_localtop_t* top, const t_mdatoms& md)
{
impl_->setConstraints(top, md);
}
* indices to constraint indices.
*
* Note that flexible constraints are only enabled with a dynamical integrator. */
-static std::vector<t_blocka> makeAtomToConstraintMappings(const gmx_mtop_t& mtop,
- FlexibleConstraintTreatment flexibleConstraintTreatment)
+static std::vector<ListOfLists<int>> makeAtomToConstraintMappings(const gmx_mtop_t& mtop,
+ FlexibleConstraintTreatment flexibleConstraintTreatment)
{
- std::vector<t_blocka> mapping;
+ std::vector<ListOfLists<int>> mapping;
mapping.reserve(mtop.moltype.size());
for (const gmx_moltype_t& moltype : mtop.moltype)
{
for (const gmx_molblock_t& molblock : mtop.molblock)
{
- int count = countFlexibleConstraintsTemplate(mtop.moltype[molblock.type].ilist.data(),
- mtop.ffparams.iparams.data());
+ int count = countFlexibleConstraints(mtop.moltype[molblock.type].ilist, mtop.ffparams.iparams);
nflexcon += molblock.nmol * count;
}
please_cite(log, "Barth95a");
}
- shaked = shake_init();
+ shaked = std::make_unique<shakedata>();
}
}
Constraints::Impl::~Impl()
{
- for (auto blocka : at2con_mt)
- {
- done_blocka(&blocka);
- }
if (bSettleErrorHasOccurred != nullptr)
{
sfree(bSettleErrorHasOccurred);
impl_->ed = ed;
}
-ArrayRef<const t_blocka> Constraints::atom2constraints_moltype() const
+ArrayRef<const ListOfLists<int>> Constraints::atom2constraints_moltype() const
{
return impl_->at2con_mt;
}
int64_t step;
real dt = ir->delta_t;
real dvdl_dum;
- rvec* savex;
- auto xRvec = as_rvec_array(x.paddedArrayRef().data());
- auto vRvec = as_rvec_array(v.paddedArrayRef().data());
-
- /* We need to allocate one element extra, since we might use
- * (unaligned) 4-wide SIMD loads to access rvec entries.
- */
- snew(savex, natoms + 1);
+ PaddedVector<RVec> savex(natoms);
start = 0;
end = md->homenr;
dvdl_dum = 0;
/* constrain the current position */
- constr->apply(TRUE, FALSE, step, 0, 1.0, xRvec, xRvec, nullptr, box, lambda, &dvdl_dum, nullptr,
- nullptr, gmx::ConstraintVariable::Positions);
+ constr->apply(TRUE, FALSE, step, 0, 1.0, x, x, {}, box, lambda, &dvdl_dum, {}, nullptr,
+ gmx::ConstraintVariable::Positions);
if (EI_VV(ir->eI))
{
/* constrain the inital velocity, and save it */
/* also may be useful if we need the ekin from the halfstep for velocity verlet */
- constr->apply(TRUE, FALSE, step, 0, 1.0, xRvec, vRvec, vRvec, box, lambda, &dvdl_dum,
- nullptr, nullptr, gmx::ConstraintVariable::Velocities);
+ constr->apply(TRUE, FALSE, step, 0, 1.0, x, v, v.unpaddedArrayRef(), box, lambda, &dvdl_dum,
+ {}, nullptr, gmx::ConstraintVariable::Velocities);
}
/* constrain the inital velocities at t-dt/2 */
if (EI_STATE_VELOCITY(ir->eI) && ir->eI != eiVV)
fprintf(fplog, "\nConstraining the coordinates at t0-dt (step %s)\n", gmx_step_str(step, buf));
}
dvdl_dum = 0;
- constr->apply(TRUE, FALSE, step, -1, 1.0, xRvec, savex, nullptr, box, lambda, &dvdl_dum,
- vRvec, nullptr, gmx::ConstraintVariable::Positions);
+ constr->apply(TRUE, FALSE, step, -1, 1.0, x, savex.arrayRefWithPadding(), {}, box, lambda,
+ &dvdl_dum, v, nullptr, gmx::ConstraintVariable::Positions);
for (i = start; i < end; i++)
{
}
}
}
- sfree(savex);
}
} // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_multisim_t;
struct gmx_wallcycle;
struct pull_t;
-struct t_blocka;
struct t_commrec;
struct t_ilist;
struct t_inputrec;
{
template<typename T>
class ArrayRefWithPadding;
+template<typename>
+class ListOfLists;
//! Describes supported flavours of constrained updates.
enum class ConstraintVariable : int
*
* \todo Make this a callback that is called automatically
* once a new domain has been made. */
- void setConstraints(const gmx_localtop_t& top, const t_mdatoms& md);
+ void setConstraints(gmx_localtop_t* top, const t_mdatoms& md);
/*! \brief Applies constraints to coordinates.
*
* When econq=ConstraintVariable::Positions constrains
- * coordinates xprime using th directions in x, min_proj is
+ * coordinates xprime using the directions in x, min_proj is
* not used.
*
* When econq=ConstraintVariable::Derivative, calculates the
* If vir!=NULL calculate the constraint virial.
*
* Return whether the application of constraints succeeded without error.
+ *
+ * /note x is non-const, because non-local atoms need to be communicated.
*/
- bool apply(bool bLog,
- bool bEner,
- int64_t step,
- int delta_step,
- real step_scaling,
- rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- real lambda,
- real* dvdlambda,
- rvec* v,
- tensor* vir,
- ConstraintVariable econq);
+ bool apply(bool bLog,
+ bool bEner,
+ int64_t step,
+ int delta_step,
+ real step_scaling,
+ ArrayRefWithPadding<RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ real lambda,
+ real* dvdlambda,
+ ArrayRefWithPadding<RVec> v,
+ tensor* vir,
+ ConstraintVariable econq);
//! Links the essentialdynamics and constraint code.
void saveEdsamPointer(gmx_edsam* ed);
//! Getter for use by domain decomposition.
- ArrayRef<const t_blocka> atom2constraints_moltype() const;
+ ArrayRef<const ListOfLists<int>> atom2constraints_moltype() const;
//! Getter for use by domain decomposition.
ArrayRef<const std::vector<int>> atom2settle_moltype() const;
[[noreturn]] void too_many_constraint_warnings(int eConstrAlg, int warncount);
/*! \brief Returns whether constraint with parameter \p iparamsIndex is a flexible constraint */
-static inline bool isConstraintFlexible(const t_iparams* iparams, int iparamsIndex)
+static inline bool isConstraintFlexible(ArrayRef<const t_iparams> iparams, int iparamsIndex)
{
- GMX_ASSERT(iparams != nullptr, "Need a valid iparams array");
-
return (iparams[iparamsIndex].constr.dA == 0 && iparams[iparamsIndex].constr.dB == 0);
};
/*! \brief Returns the flexible constraint treatment depending on whether the integrator is dynamic */
FlexibleConstraintTreatment flexibleConstraintTreatment(bool haveDynamicsIntegrator);
-/*! \brief Returns a block struct to go from atoms to constraints
+/*! \brief Returns a ListOfLists object to go from atoms to constraints
*
- * The block struct will contain constraint indices with lower indices
+ * The object will contain constraint indices with lower indices
* directly matching the order in F_CONSTR and higher indices matching
* the order in F_CONSTRNC offset by the number of constraints in F_CONSTR.
*
* \param[in] moltype The molecule data
* \param[in] iparams Interaction parameters, can be null when
- * flexibleConstraintTreatment=Include \param[in] flexibleConstraintTreatment The flexible
- * constraint treatment, see enum above \returns a block struct with all constraints for each atom
+ * \p flexibleConstraintTreatment==Include
+ * \param[in] flexibleConstraintTreatment The flexible constraint treatment,
+ * see enum above
+ *
+ * \returns a ListOfLists object with all constraints for each atom
*/
-t_blocka make_at2con(const gmx_moltype_t& moltype,
- gmx::ArrayRef<const t_iparams> iparams,
- FlexibleConstraintTreatment flexibleConstraintTreatment);
+ListOfLists<int> make_at2con(const gmx_moltype_t& moltype,
+ gmx::ArrayRef<const t_iparams> iparams,
+ FlexibleConstraintTreatment flexibleConstraintTreatment);
-/*! \brief Returns a block struct to go from atoms to constraints
+/*! \brief Returns a ListOfLists object to go from atoms to constraints
*
- * The block struct will contain constraint indices with lower indices
+ * The object will contain constraint indices with lower indices
* directly matching the order in F_CONSTR and higher indices matching
* the order in F_CONSTRNC offset by the number of constraints in F_CONSTR.
*
* \param[in] numAtoms The number of atoms to construct the list for
* \param[in] ilist Interaction list, size F_NRE
* \param[in] iparams Interaction parameters, can be null when
- * flexibleConstraintTreatment=Include \param[in] flexibleConstraintTreatment The flexible
- * constraint treatment, see enum above \returns a block struct with all constraints for each atom
+ * \p flexibleConstraintTreatment==Include
+ * \param[in] flexibleConstraintTreatment The flexible constraint treatment,
+ * see enum above
+ *
+ * \returns a ListOfLists object with all constraints for each atom
*/
-t_blocka make_at2con(int numAtoms,
- const t_ilist* ilist,
- const t_iparams* iparams,
- FlexibleConstraintTreatment flexibleConstraintTreatment);
-
-/*! \brief Returns an array of atom to constraints lists for the moltypes */
-const t_blocka* atom2constraints_moltype(const Constraints* constr);
+ListOfLists<int> make_at2con(int numAtoms,
+ ArrayRef<const InteractionList> ilist,
+ ArrayRef<const t_iparams> iparams,
+ FlexibleConstraintTreatment flexibleConstraintTreatment);
//! Return the number of flexible constraints in the \c ilist and \c iparams.
-int countFlexibleConstraints(const t_ilist* ilist, const t_iparams* iparams);
+int countFlexibleConstraints(ArrayRef<const InteractionList> ilist, ArrayRef<const t_iparams> iparams);
/*! \brief Returns the constraint iatoms for a constraint number con
* which comes from a list where F_CONSTR and F_CONSTRNC constraints
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/topology/block.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/logger.h"
#include "gromacs/utility/real.h"
-#include "gromacs/utility/smalloc.h"
namespace gmx
{
//! Recursing function to help find all adjacent constraints.
-static void constr_recur(const t_blocka* at2con,
+static void constr_recur(const ListOfLists<int>& at2con,
const InteractionLists& ilist,
gmx::ArrayRef<const t_iparams> iparams,
gmx_bool bTopB,
int at,
int depth,
int nc,
- int* path,
+ ArrayRef<int> path,
real r0,
real r1,
real* r2max,
int* count)
{
- int c, con, a1;
gmx_bool bUse;
real len, rn0, rn1;
gmx::ArrayRef<const int> ia2 = ilist[F_CONSTRNC].iatoms;
/* Loop over all constraints connected to this atom */
- for (c = at2con->index[at]; c < at2con->index[at + 1]; c++)
+ for (const int con : at2con[at])
{
- con = at2con->a[c];
/* Do not walk over already used constraints */
bUse = TRUE;
- for (a1 = 0; a1 < depth; a1++)
+ for (int a1 = 0; a1 < depth; a1++)
{
if (con == path[a1])
{
fprintf(debug,
"Found longer constraint distance: r0 %5.3f r1 %5.3f rmax %5.3f\n", rn0,
rn1, sqrt(*r2max));
- for (a1 = 0; a1 < depth; a1++)
+ for (int a1 = 0; a1 < depth; a1++)
{
fprintf(debug, " %d %5.3f", path[a1],
iparams[constr_iatomptr(ia1, ia2, con)[0]].constr.dA);
*/
if (depth + 1 < nc && *count < 1000 * nc)
{
+ int a1;
if (ia[1] == at)
{
a1 = ia[2];
gmx::ArrayRef<const t_iparams> iparams,
const t_inputrec* ir)
{
- int natoms, *path, at, count;
+ int natoms, at, count;
- t_blocka at2con;
- real r0, r1, r2maxA, r2maxB, rmax, lam0, lam1;
+ real r0, r1, r2maxA, r2maxB, rmax, lam0, lam1;
- if (molt->ilist[F_CONSTR].size() == 0 && molt->ilist[F_CONSTRNC].size() == 0)
+ if (molt->ilist[F_CONSTR].empty() && molt->ilist[F_CONSTRNC].empty())
{
return 0;
}
natoms = molt->atoms.nr;
- at2con = make_at2con(*molt, iparams, flexibleConstraintTreatment(EI_DYNAMICS(ir->eI)));
- snew(path, 1 + ir->nProjOrder);
+ const ListOfLists<int> at2con =
+ make_at2con(*molt, iparams, flexibleConstraintTreatment(EI_DYNAMICS(ir->eI)));
+ std::vector<int> path(1 + ir->nProjOrder);
for (at = 0; at < 1 + ir->nProjOrder; at++)
{
path[at] = -1;
r1 = 0;
count = 0;
- constr_recur(&at2con, molt->ilist, iparams, FALSE, at, 0, 1 + ir->nProjOrder, path, r0, r1,
+ constr_recur(at2con, molt->ilist, iparams, FALSE, at, 0, 1 + ir->nProjOrder, path, r0, r1,
&r2maxA, &count);
}
if (ir->efep == efepNO)
r0 = 0;
r1 = 0;
count = 0;
- constr_recur(&at2con, molt->ilist, iparams, TRUE, at, 0, 1 + ir->nProjOrder, path, r0,
+ constr_recur(at2con, molt->ilist, iparams, TRUE, at, 0, 1 + ir->nProjOrder, path, r0,
r1, &r2maxB, &count);
}
lam0 = ir->fepvals->init_lambda;
}
}
- done_blocka(&at2con);
- sfree(path);
-
return rmax;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* for now, we use Elr = 0, because if you want to get it right, you
really should be using PME. Maybe print a warning? */
- pscal = calc_pres(ir->ePBC, nwall, box, ekinmod, vir, localpres) + pcorr;
+ pscal = calc_pres(ir->pbcType, nwall, box, ekinmod, vir, localpres) + pcorr;
vol = det(box);
GW = (vol * (MassQ->Winv / PRESFAC)) * (DIM * pscal - trace(ir->ref_p)); /* W is in ps^2 * bar * nm^3 */
*
*/
-real calc_pres(int ePBC, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres)
+real calc_pres(PbcType pbcType, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres)
{
int n, m;
real fac;
- if (ePBC == epbcNONE || (ePBC == epbcXY && nwall != 2))
+ if (pbcType == PbcType::No || (pbcType == PbcType::XY && nwall != 2))
{
clear_mat(pres);
}
#include "gromacs/math/vec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/nblist.h"
#include "gromacs/tables/forcetable.h"
*/
for (const gmx_molblock_t& molb : mtop.molblock)
{
- const int nmol = molb.nmol;
- const t_atoms* atoms = &mtop.moltype[molb.type].atoms;
- const t_blocka* excl = &mtop.moltype[molb.type].excls;
+ const int nmol = molb.nmol;
+ const t_atoms* atoms = &mtop.moltype[molb.type].atoms;
+ const auto& excl = mtop.moltype[molb.type].excls;
for (int i = 0; (i < atoms->nr); i++)
{
const int tpi = atomtypeAOrB(atoms->atom[i], q);
- const int j1 = excl->index[i];
- const int j2 = excl->index[i + 1];
- for (int j = j1; j < j2; j++)
+ for (const int k : excl[i])
{
- const int k = excl->a[j];
if (k > i)
{
const int tpj = atomtypeAOrB(atoms->atom[k], q);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_enerdata_t::gmx_enerdata_t(int numEnergyGroups, int numFepLambdas) :
grpp(numEnergyGroups),
enerpart_lambda(numFepLambdas == 0 ? 0 : numFepLambdas + 1),
+ dhdlLambda(numFepLambdas == 0 ? 0 : numFepLambdas + 1),
foreign_grpp(numEnergyGroups)
{
}
int index;
enerd->dvdl_lin[efptVDW] += enerd->term[F_DVDL_VDW]; /* include dispersion correction */
+
+ for (size_t i = 0; i < enerd->enerpart_lambda.size(); i++)
+ {
+ enerd->dhdlLambda[i] += enerd->term[F_DVDL_VDW];
+ }
+
enerd->term[F_DVDL] = 0.0;
for (int i = 0; i < efptNR; i++)
{
}
}
+void reset_dvdl_enerdata(gmx_enerdata_t* enerd)
+{
+ for (int i = 0; i < efptNR; i++)
+ {
+ enerd->dvdl_lin[i] = 0.0;
+ enerd->dvdl_nonlin[i] = 0.0;
+ }
+}
+
void reset_enerdata(gmx_enerdata_t* enerd)
{
int i, j;
enerd->grpp.ener[i][j] = 0.0;
}
}
- for (i = 0; i < efptNR; i++)
- {
- enerd->dvdl_lin[i] = 0.0;
- enerd->dvdl_nonlin[i] = 0.0;
- }
/* Normal potential energy components */
for (i = 0; (i <= F_EPOT); i++)
enerd->term[F_DVDL_RESTRAINT] = 0.0;
enerd->term[F_DKDL] = 0.0;
std::fill(enerd->enerpart_lambda.begin(), enerd->enerpart_lambda.end(), 0);
- /* reset foreign energy data - separate function since we also call it elsewhere */
+ std::fill(enerd->dhdlLambda.begin(), enerd->dhdlLambda.end(), 0);
+ /* reset foreign energy data and dvdl - separate functions since they are also called elsewhere */
reset_foreign_enerdata(enerd);
+ reset_dvdl_enerdata(enerd);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void reset_foreign_enerdata(gmx_enerdata_t* enerd);
/* Resets only the foreign energy data */
+void reset_dvdl_enerdata(gmx_enerdata_t* enerd);
+/* Resets only the dvdl energy data */
+
void reset_enerdata(gmx_enerdata_t* enerd);
/* Resets the energy data */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
bEner_[F_COM_PULL] = ((ir->bPull && pull_have_potential(pull_work)) || ir->bRot);
MdModulesEnergyOutputToDensityFittingRequestChecker mdModulesAddOutputToDensityFittingFieldRequest;
- mdModulesNotifier.notifier_.notify(&mdModulesAddOutputToDensityFittingFieldRequest);
+ mdModulesNotifier.simulationSetupNotifications_.notify(&mdModulesAddOutputToDensityFittingFieldRequest);
bEner_[F_DENSITYFITTING] = mdModulesAddOutputToDensityFittingFieldRequest.energyOutputToDensityFitting_;
}
}
-void EnergyOutput::printAnnealingTemperatures(FILE* log, SimulationGroups* groups, t_grpopts* opts)
+void EnergyOutput::printAnnealingTemperatures(FILE* log, const SimulationGroups* groups, t_grpopts* opts)
{
if (log)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] opts Atom temperature coupling groups options
* (annealing is done by groups).
*/
- void printAnnealingTemperatures(FILE* log, SimulationGroups* groups, t_grpopts* opts);
+ static void printAnnealingTemperatures(FILE* log, const SimulationGroups* groups, t_grpopts* opts);
/*! \brief Prints average values to log file.
*
void restoreFromEnergyHistory(const energyhistory_t& enerhist);
//! Print an output header to the log file.
- void printHeader(FILE* log, int64_t steps, double time);
+ static void printHeader(FILE* log, int64_t steps, double time);
private:
//! Timestep
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vec.h"
#include "gromacs/math/vecdump.h"
#include "gromacs/mdlib/forcerec_threading.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/rf_util.h"
#include "gromacs/mdlib/wall.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
+using gmx::ArrayRef;
+using gmx::RVec;
+
static void clearEwaldThreadOutput(ewald_corr_thread_t* ewc_t)
{
ewc_t->Vcorr_q = 0;
}
}
-void do_force_lowlevel(t_forcerec* fr,
- const t_inputrec* ir,
- const t_idef* idef,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- t_nrnb* nrnb,
- gmx_wallcycle_t wcycle,
- const t_mdatoms* md,
- gmx::ArrayRefWithPadding<gmx::RVec> coordinates,
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- gmx_enerdata_t* enerd,
- t_fcdata* fcd,
- const matrix box,
- const real* lambda,
- const t_graph* graph,
- const rvec* mu_tot,
- const gmx::StepWorkload& stepWork,
- const DDBalanceRegionHandler& ddBalanceRegionHandler)
+void do_force_lowlevel(t_forcerec* fr,
+ const t_inputrec* ir,
+ const InteractionDefinitions& idef,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ t_nrnb* nrnb,
+ gmx_wallcycle_t wcycle,
+ const t_mdatoms* md,
+ gmx::ArrayRefWithPadding<const RVec> coordinates,
+ ArrayRef<const RVec> xWholeMolecules,
+ history_t* hist,
+ gmx::ForceOutputs* forceOutputs,
+ gmx_enerdata_t* enerd,
+ t_fcdata* fcd,
+ const matrix box,
+ const real* lambda,
+ const rvec* mu_tot,
+ const gmx::StepWorkload& stepWork,
+ const DDBalanceRegionHandler& ddBalanceRegionHandler)
{
// TODO: Replace all uses of x by const coordinates
- rvec* x = as_rvec_array(coordinates.paddedArrayRef().data());
+ const rvec* x = as_rvec_array(coordinates.paddedArrayRef().data());
auto& forceWithVirial = forceOutputs->forceWithVirial();
- /* do QMMM first if requested */
- if (fr->bQMMM)
- {
- enerd->term[F_EQM] = calculate_QMMM(cr, &forceOutputs->forceWithShiftForces(), fr);
- }
-
/* Call the short range functions all in one go. */
if (ir->nwall)
real dvdl_walls = do_walls(*ir, *fr, box, *md, x, &forceWithVirial, lambda[efptVDW],
enerd->grpp.ener[egLJSR].data(), nrnb);
enerd->dvdl_lin[efptVDW] += dvdl_walls;
- }
-
- /* Shift the coordinates. Must be done before listed forces and PPPM,
- * but is also necessary for SHAKE and update, therefore it can NOT
- * go when no listed forces have to be evaluated.
- *
- * The shifting and PBC code is deliberately not timed, since with
- * the Verlet scheme it only takes non-zero time with triclinic
- * boxes, and even then the time is around a factor of 100 less
- * than the next smallest counter.
- */
-
- /* Here sometimes we would not need to shift with NBFonly,
- * but we do so anyhow for consistency of the returned coordinates.
- */
- if (graph)
- {
- shift_self(graph, box, x);
- if (TRICLINIC(box))
- {
- inc_nrnb(nrnb, eNR_SHIFTX, 2 * graph->nnodes);
- }
- else
+ for (auto& dhdl : enerd->dhdlLambda)
{
- inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
+ dhdl += dvdl_walls;
}
}
/* Check whether we need to take into account PBC in listed interactions. */
const auto needPbcForListedForces =
- fr->bMolPBC && stepWork.computeListedForces && haveCpuListedForces(*fr, *idef, *fcd);
+ fr->bMolPBC && stepWork.computeListedForces && haveCpuListedForces(*fr, idef, *fcd);
if (needPbcForListedForces)
{
/* Since all atoms are in the rectangular or triclinic unit-cell,
* only single box vector shifts (2 in x) are required.
*/
- set_pbc_dd(&pbc, fr->ePBC, DOMAINDECOMP(cr) ? cr->dd->nc : nullptr, TRUE, box);
+ set_pbc_dd(&pbc, fr->pbcType, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, TRUE, box);
}
- do_force_listed(wcycle, box, ir->fepvals, cr, ms, idef, x, hist, forceOutputs, fr, &pbc,
- graph, enerd, nrnb, lambda, md, fcd,
+ do_force_listed(wcycle, box, ir->fepvals, cr, ms, idef, x, xWholeMolecules, hist,
+ forceOutputs, fr, &pbc, enerd, nrnb, lambda, md, fcd,
DOMAINDECOMP(cr) ? cr->dd->globalAtomIndices.data() : nullptr, stepWork);
}
{
wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION);
- if (fr->n_tpi > 0)
- {
- gmx_fatal(FARGS,
- "TPI with PME currently only works in a 3D geometry with tin-foil "
- "boundary conditions");
- }
-
int nthreads = fr->nthread_ewc;
#pragma omp parallel for num_threads(nthreads) schedule(static)
for (int t = 0; t < nthreads; t++)
assert(fr->n_tpi >= 0);
if (fr->n_tpi == 0 || stepWork.stateChanged)
{
- int pme_flags = GMX_PME_SPREAD | GMX_PME_SOLVE;
-
- if (stepWork.computeForces)
- {
- pme_flags |= GMX_PME_CALC_F;
- }
- if (stepWork.computeVirial)
- {
- pme_flags |= GMX_PME_CALC_ENER_VIR;
- }
- if (fr->n_tpi > 0)
- {
- /* We don't calculate f, but we do want the potential */
- pme_flags |= GMX_PME_CALC_POT;
- }
-
/* With domain decomposition we close the CPU side load
* balancing region here, because PME does global
* communication that acts as a global barrier.
DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0, nrnb, wcycle,
ewaldOutput.vir_q, ewaldOutput.vir_lj, &Vlr_q, &Vlr_lj,
lambda[efptCOUL], lambda[efptVDW], &ewaldOutput.dvdl[efptCOUL],
- &ewaldOutput.dvdl[efptVDW], pme_flags);
+ &ewaldOutput.dvdl[efptVDW], stepWork);
wallcycle_stop(wcycle, ewcPMEMESH);
if (status != 0)
{
}
if (fr->n_tpi > 0)
{
- if (EVDW_PME(ir->vdwtype))
- {
-
- gmx_fatal(FARGS, "Test particle insertion not implemented with LJ-PME");
- }
/* Determine the PME grid energy of the test molecule
* with the PME grid potential of the other charges.
*/
enerd->term[F_COUL_RECIP] = Vlr_q + ewaldOutput.Vcorr_q;
enerd->term[F_LJ_RECIP] = Vlr_lj + ewaldOutput.Vcorr_lj;
+ for (auto& dhdl : enerd->dhdlLambda)
+ {
+ dhdl += ewaldOutput.dvdl[efptVDW] + ewaldOutput.dvdl[efptCOUL];
+ }
+
if (debug)
{
fprintf(debug, "Vlr_q = %g, Vcorr_q = %g, Vlr_corr_q = %g\n", Vlr_q,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/arrayrefwithpadding.h"
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/utility/arrayref.h"
class DDBalanceRegionHandler;
struct gmx_vsite_t;
struct gmx_wallcycle;
class history_t;
+class InteractionDefinitions;
struct pull_t;
struct t_commrec;
struct t_fcdata;
struct t_forcerec;
-struct t_graph;
-struct t_idef;
struct t_inputrec;
struct t_lambda;
struct t_mdatoms;
namespace gmx
{
class Awh;
+class ForceOutputs;
class ForceWithVirial;
class ImdSession;
class MdrunScheduleWorkload;
gmx_enerdata_t* enerd,
t_fcdata* fcd,
gmx::ArrayRef<real> lambda,
- t_graph* graph,
t_forcerec* fr,
gmx::MdrunScheduleWorkload* runScheduleWork,
const gmx_vsite_t* vsite,
*/
-void do_force_lowlevel(t_forcerec* fr,
- const t_inputrec* ir,
- const t_idef* idef,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- t_nrnb* nrnb,
- gmx_wallcycle* wcycle,
- const t_mdatoms* md,
- gmx::ArrayRefWithPadding<gmx::RVec> coordinates,
- history_t* hist,
- gmx::ForceOutputs* forceOutputs,
- gmx_enerdata_t* enerd,
- t_fcdata* fcd,
- const matrix box,
- const real* lambda,
- const t_graph* graph,
- const rvec* mu_tot,
- const gmx::StepWorkload& stepWork,
- const DDBalanceRegionHandler& ddBalanceRegionHandler);
+/* Compute listed forces, Ewald, PME corrections add when (when used).
+ *
+ * xWholeMolecules only needs to contain whole molecules when orientation
+ * restraints need to be computed and can be empty otherwise.
+ */
+void do_force_lowlevel(t_forcerec* fr,
+ const t_inputrec* ir,
+ const InteractionDefinitions& idef,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ t_nrnb* nrnb,
+ gmx_wallcycle* wcycle,
+ const t_mdatoms* md,
+ gmx::ArrayRefWithPadding<const gmx::RVec> coordinates,
+ gmx::ArrayRef<const gmx::RVec> xWholeMolecules,
+ history_t* hist,
+ gmx::ForceOutputs* forceOutputs,
+ gmx_enerdata_t* enerd,
+ t_fcdata* fcd,
+ const matrix box,
+ const real* lambda,
+ const rvec* mu_tot,
+ const gmx::StepWorkload& stepWork,
+ const DDBalanceRegionHandler& ddBalanceRegionHandler);
/* Call all the force routines */
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-2020, by the GROMACS development team, led by
+ * Copyright (c) 2013-2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/forcerec_threading.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/md_support.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/rf_util.h"
#include "gromacs/mdlib/wall.h"
+#include "gromacs/mdlib/wholemoleculetransform.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/fcdata.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/iforceprovider.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/nbnxm/nbnxm.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strconvert.h"
-/*! \brief environment variable to enable GPU P2P communication */
-static const bool c_enableGpuPmePpComms =
- (getenv("GMX_GPU_PME_PP_COMMS") != nullptr) && GMX_THREAD_MPI && (GMX_GPU == GMX_GPU_CUDA);
-
-static real* mk_nbfp(const gmx_ffparams_t* idef, gmx_bool bBHAM)
+static std::vector<real> mk_nbfp(const gmx_ffparams_t* idef, gmx_bool bBHAM)
{
- real* nbfp;
- int i, j, k, atnr;
+ std::vector<real> nbfp;
+ int atnr;
atnr = idef->atnr;
if (bBHAM)
{
- snew(nbfp, 3 * atnr * atnr);
- for (i = k = 0; (i < atnr); i++)
+ nbfp.resize(3 * atnr * atnr);
+ int k = 0;
+ for (int i = 0; (i < atnr); i++)
{
- for (j = 0; (j < atnr); j++, k++)
+ for (int j = 0; (j < atnr); j++, k++)
{
BHAMA(nbfp, atnr, i, j) = idef->iparams[k].bham.a;
BHAMB(nbfp, atnr, i, j) = idef->iparams[k].bham.b;
}
else
{
- snew(nbfp, 2 * atnr * atnr);
- for (i = k = 0; (i < atnr); i++)
+ nbfp.resize(2 * atnr * atnr);
+ int k = 0;
+ for (int i = 0; (i < atnr); i++)
{
- for (j = 0; (j < atnr); j++, k++)
+ for (int j = 0; (j < atnr); j++, k++)
{
/* nbfp now includes the 6.0/12.0 derivative prefactors */
C6(nbfp, atnr, i, j) = idef->iparams[k].lj.c6 * 6.0;
acSETTLE
};
-static cginfo_mb_t* init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr, gmx_bool* bFEP_NonBonded)
+static std::vector<cginfo_mb_t> init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr)
{
- cginfo_mb_t* cginfo_mb;
- gmx_bool* type_VDW;
- int* cginfo;
- int* a_con;
-
- snew(cginfo_mb, mtop->molblock.size());
+ gmx_bool* type_VDW;
+ int* a_con;
snew(type_VDW, fr->ntype);
for (int ai = 0; ai < fr->ntype; ai++)
}
}
- *bFEP_NonBonded = FALSE;
-
- int a_offset = 0;
+ std::vector<cginfo_mb_t> cginfoPerMolblock;
+ int a_offset = 0;
for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
{
const gmx_molblock_t& molb = mtop->molblock[mb];
const gmx_moltype_t& molt = mtop->moltype[molb.type];
- const t_blocka& excl = molt.excls;
+ const auto& excl = molt.excls;
/* Check if the cginfo is identical for all molecules in this block.
* If so, we only need an array of the size of one molecule.
}
}
- cginfo_mb[mb].cg_start = a_offset;
- cginfo_mb[mb].cg_end = a_offset + molb.nmol * molt.atoms.nr;
- cginfo_mb[mb].cg_mod = (bId ? 1 : molb.nmol) * molt.atoms.nr;
- snew(cginfo_mb[mb].cginfo, cginfo_mb[mb].cg_mod);
- cginfo = cginfo_mb[mb].cginfo;
+ cginfo_mb_t cginfo_mb;
+ cginfo_mb.cg_start = a_offset;
+ cginfo_mb.cg_end = a_offset + molb.nmol * molt.atoms.nr;
+ cginfo_mb.cg_mod = (bId ? 1 : molb.nmol) * molt.atoms.nr;
+ cginfo_mb.cginfo.resize(cginfo_mb.cg_mod);
+ gmx::ArrayRef<int> cginfo = cginfo_mb.cginfo;
/* Set constraints flags for constrained atoms */
snew(a_con, molt.atoms.nr);
bool haveExclusions = false;
/* Loop over all the exclusions of atom ai */
- for (int j = excl.index[a]; j < excl.index[a + 1]; j++)
+ for (const int j : excl[a])
{
- if (excl.a[j] != a)
+ if (j != a)
{
haveExclusions = true;
break;
if (fr->efep != efepNO && PERTURBED(atom))
{
SET_CGINFO_FEP(atomInfo);
- *bFEP_NonBonded = TRUE;
}
}
}
sfree(a_con);
+ cginfoPerMolblock.push_back(cginfo_mb);
+
a_offset += molb.nmol * molt.atoms.nr;
}
sfree(type_VDW);
- return cginfo_mb;
+ return cginfoPerMolblock;
}
-static std::vector<int> cginfo_expand(const int nmb, const cginfo_mb_t* cgi_mb)
+static std::vector<int> cginfo_expand(const int nmb, gmx::ArrayRef<const cginfo_mb_t> cgi_mb)
{
const int ncg = cgi_mb[nmb - 1].cg_end;
return cginfo;
}
-static void done_cginfo_mb(cginfo_mb_t* cginfo_mb, int numMolBlocks)
-{
- if (cginfo_mb == nullptr)
- {
- return;
- }
- for (int mb = 0; mb < numMolBlocks; ++mb)
- {
- sfree(cginfo_mb[mb].cginfo);
- }
- sfree(cginfo_mb);
-}
-
/* Sets the sum of charges (squared) and C6 in the system in fr.
* Returns whether the system has a net charge.
*/
fr->natoms_force = natoms_force;
fr->natoms_force_constr = natoms_force_constr;
- if (fr->natoms_force_constr > fr->nalloc_force)
- {
- fr->nalloc_force = over_alloc_dd(fr->natoms_force_constr);
- }
-
if (fr->haveDirectVirialContributions)
{
fr->forceBufferForDirectVirialContributions.resize(natoms_f_novirsum);
* both accuracy requirements, when relevant.
*/
static void init_ewald_f_table(const interaction_const_t& ic,
+ const real tableExtensionLength,
EwaldCorrectionTables* coulombTables,
EwaldCorrectionTables* vdwTables)
{
*/
const real tableScale = ewald_spline3_table_scale(ic, useCoulombTable, useVdwTable);
- const int tableSize = static_cast<int>(ic.rcoulomb * tableScale) + 2;
+ real tableLen = ic.rcoulomb;
+ if (useCoulombTable && tableExtensionLength > 0.0)
+ {
+ /* TODO: Ideally this should also check if couple-intramol == no, but that isn't
+ * stored in ir. Grompp puts that info into an opts structure that doesn't make it into the tpr.
+ * The alternative is to look through all the exclusions and check if they come from
+ * couple-intramol == no. Meanwhile, always having larger tables should only affect
+ * memory consumption, not speed (barring cache issues).
+ */
+ tableLen = ic.rcoulomb + tableExtensionLength;
+ }
+ const int tableSize = static_cast<int>(tableLen * tableScale) + 2;
if (useCoulombTable)
{
}
}
-void init_interaction_const_tables(FILE* fp, interaction_const_t* ic)
+void init_interaction_const_tables(FILE* fp, interaction_const_t* ic, const real tableExtensionLength)
{
if (EEL_PME_EWALD(ic->eeltype) || EVDW_PME(ic->vdwtype))
{
- init_ewald_f_table(*ic, ic->coulombEwaldTables.get(), ic->vdwEwaldTables.get());
+ init_ewald_f_table(*ic, tableExtensionLength, ic->coulombEwaldTables.get(),
+ ic->vdwEwaldTables.get());
if (fp != nullptr)
{
fprintf(fp, "Initialized non-bonded Ewald tables, spacing: %.2e size: %zu\n\n",
*interaction_const = ic;
}
-bool areMoleculesDistributedOverPbc(const t_inputrec& ir, const gmx_mtop_t& mtop, const gmx::MDLogger& mdlog)
-{
- bool areMoleculesDistributedOverPbc = false;
- const bool useEwaldSurfaceCorrection = (EEL_PME_EWALD(ir.coulombtype) && ir.epsilon_surface != 0);
-
- const bool bSHAKE =
- (ir.eConstrAlg == econtSHAKE
- && (gmx_mtop_ftype_count(mtop, F_CONSTR) > 0 || gmx_mtop_ftype_count(mtop, F_CONSTRNC) > 0));
-
- /* The group cut-off scheme and SHAKE assume charge groups
- * are whole, but not using molpbc is faster in most cases.
- * With intermolecular interactions we need PBC for calculating
- * distances between atoms in different molecules.
- */
- if (bSHAKE && !mtop.bIntermolecularInteractions)
- {
- areMoleculesDistributedOverPbc = ir.bPeriodicMols;
-
- if (areMoleculesDistributedOverPbc)
- {
- gmx_fatal(FARGS, "SHAKE is not supported with periodic molecules");
- }
- }
- else
- {
- /* Not making molecules whole is faster in most cases,
- * but with orientation restraints or non-tinfoil boundary
- * conditions we need whole molecules.
- */
- areMoleculesDistributedOverPbc =
- (gmx_mtop_ftype_count(mtop, F_ORIRES) == 0 && !useEwaldSurfaceCorrection);
-
- if (getenv("GMX_USE_GRAPH") != nullptr)
- {
- areMoleculesDistributedOverPbc = false;
-
- GMX_LOG(mdlog.warning)
- .asParagraph()
- .appendText(
- "GMX_USE_GRAPH is set, using the graph for bonded "
- "interactions");
-
- if (mtop.bIntermolecularInteractions)
- {
- GMX_LOG(mdlog.warning)
- .asParagraph()
- .appendText(
- "WARNING: Molecules linked by intermolecular interactions "
- "have to reside in the same periodic image, otherwise "
- "artifacts will occur!");
- }
- }
-
- GMX_RELEASE_ASSERT(areMoleculesDistributedOverPbc || !mtop.bIntermolecularInteractions,
- "We need to use PBC within molecules with inter-molecular interactions");
-
- if (bSHAKE && areMoleculesDistributedOverPbc)
- {
- gmx_fatal(FARGS,
- "SHAKE is not properly supported with intermolecular interactions. "
- "For short simulations where linked molecules remain in the same "
- "periodic image, the environment variable GMX_USE_GRAPH can be used "
- "to override this check.\n");
- }
- }
-
- return areMoleculesDistributedOverPbc;
-}
-
void init_forcerec(FILE* fp,
const gmx::MDLogger& mdlog,
t_forcerec* fr,
const char* tabfn,
const char* tabpfn,
gmx::ArrayRef<const std::string> tabbfnm,
- const gmx_hw_info_t& hardwareInfo,
- const gmx_device_info_t* deviceInfo,
- const bool useGpuForBonded,
- const bool pmeOnlyRankUsesGpu,
- real print_force,
- gmx_wallcycle* wcycle)
+ real print_force)
{
- real rtab;
- char* env;
- double dbl;
- gmx_bool bFEP_NonBonded;
+ /* The CMake default turns SIMD kernels on, but it might be turned off further down... */
+ fr->use_simd_kernels = GMX_USE_SIMD_KERNELS;
- /* By default we turn SIMD kernels on, but it might be turned off further down... */
- fr->use_simd_kernels = TRUE;
-
- if (check_box(ir->ePBC, box))
+ if (check_box(ir->pbcType, box))
{
- gmx_fatal(FARGS, "%s", check_box(ir->ePBC, box));
+ gmx_fatal(FARGS, "%s", check_box(ir->pbcType, box));
}
/* Test particle insertion ? */
fr->sc_r_power = ir->fepvals->sc_r_power;
fr->sc_sigma6_def = gmx::power6(ir->fepvals->sc_sigma);
- env = getenv("GMX_SCSIGMA_MIN");
+ char* env = getenv("GMX_SCSIGMA_MIN");
if (env != nullptr)
{
- dbl = 0;
+ double dbl = 0;
sscanf(env, "%20lf", &dbl);
fr->sc_sigma6_min = gmx::power6(dbl);
if (fp)
/* Neighbour searching stuff */
fr->cutoff_scheme = ir->cutoff_scheme;
- fr->ePBC = ir->ePBC;
+ fr->pbcType = ir->pbcType;
/* Determine if we will do PBC for distances in bonded interactions */
- if (fr->ePBC == epbcNONE)
+ if (fr->pbcType == PbcType::No)
{
fr->bMolPBC = FALSE;
}
{
const bool useEwaldSurfaceCorrection =
(EEL_PME_EWALD(ir->coulombtype) && ir->epsilon_surface != 0);
+ const bool haveOrientationRestraints = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0);
if (!DOMAINDECOMP(cr))
{
- fr->bMolPBC = areMoleculesDistributedOverPbc(*ir, *mtop, mdlog);
- // The assert below is equivalent to fcd->orires.nr != gmx_mtop_ftype_count(mtop, F_ORIRES)
- GMX_RELEASE_ASSERT(!fr->bMolPBC || fcd->orires.nr == 0,
- "Molecules broken over PBC exist in a simulation including "
- "orientation restraints. "
- "This likely means that the global topology and the force constant "
- "data have gotten out of sync.");
- if (useEwaldSurfaceCorrection)
+ fr->bMolPBC = true;
+
+ if (useEwaldSurfaceCorrection || haveOrientationRestraints)
{
- gmx_fatal(FARGS,
- "In GROMACS 2020, Ewald dipole correction is disabled when not "
- "using domain decomposition. With domain decomposition, it only works "
- "when each molecule consists of a single update group (e.g. water). "
- "This will be fixed in GROMACS 2021.");
+ fr->wholeMoleculeTransform =
+ std::make_unique<gmx::WholeMoleculeTransform>(*mtop, ir->pbcType);
}
}
else
{
- fr->bMolPBC = dd_bonded_molpbc(cr->dd, fr->ePBC);
+ fr->bMolPBC = dd_bonded_molpbc(cr->dd, fr->pbcType);
- if (useEwaldSurfaceCorrection && !dd_moleculesAreAlwaysWhole(*cr->dd))
+ /* With Ewald surface correction it is useful to support e.g. running water
+ * in parallel with update groups.
+ * With orientation restraints there is no sensible use case supported with DD.
+ */
+ if ((useEwaldSurfaceCorrection && !dd_moleculesAreAlwaysWhole(*cr->dd)) || haveOrientationRestraints)
{
gmx_fatal(FARGS,
- "You requested dipole correction (epsilon_surface > 0), but molecules "
- "are broken "
+ "You requested Ewald surface correction or orientation restraints, "
+ "but molecules are broken "
"over periodic boundary conditions by the domain decomposition. "
"Run without domain decomposition instead.");
}
if (useEwaldSurfaceCorrection)
{
- GMX_RELEASE_ASSERT((!DOMAINDECOMP(cr) && !fr->bMolPBC)
- || (DOMAINDECOMP(cr) && dd_moleculesAreAlwaysWhole(*cr->dd)),
+ GMX_RELEASE_ASSERT(!DOMAINDECOMP(cr) || dd_moleculesAreAlwaysWhole(*cr->dd),
"Molecules can not be broken by PBC with epsilon_surface > 0");
}
}
/* fr->ic is used both by verlet and group kernels (to some extent) now */
init_interaction_const(fp, &fr->ic, ir, mtop, systemHasNetCharge);
- init_interaction_const_tables(fp, fr->ic);
+ init_interaction_const_tables(fp, fr->ic, ir->tabext);
const interaction_const_t* ic = fr->ic;
case eelSWITCH:
case eelSHIFT:
case eelUSER:
- case eelENCADSHIFT:
case eelPMESWITCH:
case eelPMEUSER:
case eelPMEUSERSWITCH:
case evdwSWITCH:
case evdwSHIFT:
- case evdwUSER:
- case evdwENCADSHIFT:
- fr->nbkernel_vdw_interaction = GMX_NBKERNEL_VDW_CUBICSPLINETABLE;
- break;
+ case evdwUSER: fr->nbkernel_vdw_interaction = GMX_NBKERNEL_VDW_CUBICSPLINETABLE; break;
default: gmx_fatal(FARGS, "Unsupported vdw interaction: %s", evdw_names[ic->vdwtype]);
}
fr->shiftForces.resize(SHIFTS);
- if (fr->nbfp == nullptr)
+ if (fr->nbfp.empty())
{
fr->ntype = mtop->ffparams.atnr;
fr->nbfp = mk_nbfp(&mtop->ffparams, fr->bBHAM);
* in that case grompp should already have checked that we do not need
* normal tables and we only generate tables for 1-4 interactions.
*/
- rtab = ir->rlist + ir->tabext;
+ real rtab = ir->rlist + ir->tabext;
/* We want to use unmodified tables for 1-4 coulombic
* interactions, so we must in general have an extra set of
}
// QM/MM initialization if requested
- fr->bQMMM = ir->bQMMM;
- if (fr->bQMMM)
+ if (ir->bQMMM)
{
- // Initialize QM/MM if supported
- if (GMX_QMMM)
- {
- GMX_LOG(mdlog.info)
- .asParagraph()
- .appendText(
- "Large parts of the QM/MM support is deprecated, and may be removed in "
- "a future "
- "version. Please get in touch with the developers if you find the "
- "support useful, "
- "as help is needed if the functionality is to continue to be "
- "available.");
- fr->qr = mk_QMMMrec();
- init_QMMMrec(cr, mtop, ir, fr);
- }
- else
- {
- gmx_incons(
- "QM/MM was requested, but is only available when GROMACS "
- "is configured with QM/MM support");
- }
+ gmx_incons("QM/MM was requested, but is no longer available in GROMACS");
}
/* Set all the static charge group info */
- fr->cginfo_mb = init_cginfo_mb(mtop, fr, &bFEP_NonBonded);
+ fr->cginfo_mb = init_cginfo_mb(mtop, fr);
if (!DOMAINDECOMP(cr))
{
fr->cginfo = cginfo_expand(mtop->molblock.size(), fr->cginfo_mb);
fr->nthread_ewc = gmx_omp_nthreads_get(emntBonded);
snew(fr->ewc_t, fr->nthread_ewc);
- if (fr->cutoff_scheme == ecutsVERLET)
- {
- // We checked the cut-offs in grompp, but double-check here.
- // We have PME+LJcutoff kernels for rcoulomb>rvdw.
- if (EEL_PME_EWALD(ir->coulombtype) && ir->vdwtype == eelCUT)
- {
- GMX_RELEASE_ASSERT(ir->rcoulomb >= ir->rvdw,
- "With Verlet lists and PME we should have rcoulomb>=rvdw");
- }
- else
- {
- GMX_RELEASE_ASSERT(
- ir->rcoulomb == ir->rvdw,
- "With Verlet lists and no PME rcoulomb and rvdw should be identical");
- }
-
- fr->nbv = Nbnxm::init_nb_verlet(mdlog, bFEP_NonBonded, ir, fr, cr, hardwareInfo, deviceInfo,
- mtop, box, wcycle);
-
- if (useGpuForBonded)
- {
- auto stream = havePPDomainDecomposition(cr)
- ? Nbnxm::gpu_get_command_stream(
- fr->nbv->gpu_nbv, gmx::InteractionLocality::NonLocal)
- : Nbnxm::gpu_get_command_stream(fr->nbv->gpu_nbv,
- gmx::InteractionLocality::Local);
- // TODO the heap allocation is only needed while
- // t_forcerec lacks a constructor.
- fr->gpuBonded = new gmx::GpuBonded(mtop->ffparams, stream, wcycle);
- }
- }
-
if (ir->eDispCorr != edispcNO)
{
fr->dispersionCorrection = std::make_unique<DispersionCorrection>(
- *mtop, *ir, fr->bBHAM, fr->ntype,
- gmx::arrayRefFromArray(fr->nbfp, fr->ntype * fr->ntype * 2), *fr->ic, tabfn);
+ *mtop, *ir, fr->bBHAM, fr->ntype, fr->nbfp, *fr->ic, tabfn);
fr->dispersionCorrection->print(mdlog);
}
*/
fprintf(fp, "\n");
}
-
- if (pmeOnlyRankUsesGpu && c_enableGpuPmePpComms)
- {
- fr->pmePpCommGpu = std::make_unique<gmx::PmePpCommGpu>(cr->mpi_comm_mysim, cr->dd->pme_nodeid);
- }
}
t_forcerec::t_forcerec() = default;
-t_forcerec::~t_forcerec() = default;
-
-/* Frees GPU memory and sets a tMPI node barrier.
- *
- * Note that this function needs to be called even if GPUs are not used
- * in this run because the PME ranks have no knowledge of whether GPUs
- * are used or not, but all ranks need to enter the barrier below.
- * \todo Remove physical node barrier from this function after making sure
- * that it's not needed anymore (with a shared GPU run).
- */
-void free_gpu_resources(t_forcerec* fr,
- const gmx::PhysicalNodeCommunicator& physicalNodeCommunicator,
- const gmx_gpu_info_t& gpu_info)
-{
- bool isPPrankUsingGPU = (fr != nullptr) && (fr->nbv != nullptr) && fr->nbv->useGpu();
-
- /* stop the GPU profiler (only CUDA) */
- if (gpu_info.n_dev > 0)
- {
- stopGpuProfiler();
- }
-
- if (isPPrankUsingGPU)
- {
- /* Free data in GPU memory and pinned memory before destroying the GPU context */
- fr->nbv.reset();
-
- delete fr->gpuBonded;
- fr->gpuBonded = nullptr;
- }
-
- /* With tMPI we need to wait for all ranks to finish deallocation before
- * destroying the CUDA context in free_gpu() as some tMPI ranks may be sharing
- * GPU and context.
- *
- * This is not a concern in OpenCL where we use one context per rank which
- * is freed in nbnxn_gpu_free().
- *
- * Note: it is safe to not call the barrier on the ranks which do not use GPU,
- * but it is easier and more futureproof to call it on the whole node.
- */
- if (GMX_THREAD_MPI)
- {
- physicalNodeCommunicator.barrier();
- }
-}
-
-void done_forcerec(t_forcerec* fr, int numMolBlocks)
+t_forcerec::~t_forcerec()
{
- if (fr == nullptr)
- {
- // PME-only ranks don't have a forcerec
- return;
- }
- done_cginfo_mb(fr->cginfo_mb, numMolBlocks);
- sfree(fr->nbfp);
- delete fr->ic;
- sfree(fr->shift_vec);
- sfree(fr->ewc_t);
- tear_down_bonded_threading(fr->bondedThreading);
- GMX_RELEASE_ASSERT(fr->gpuBonded == nullptr, "Should have been deleted earlier, when used");
- fr->bondedThreading = nullptr;
- delete fr;
+ /* Note: This code will disappear when types are converted to C++ */
+ sfree(shift_vec);
+ sfree(ewc_t);
+ tear_down_bonded_threading(bondedThreading);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_MDLIB_FORCEREC_H
#define GMX_MDLIB_FORCEREC_H
-#include "gromacs/mdlib/force_flags.h"
-#include "gromacs/mdlib/tgroup.h"
-#include "gromacs/mdlib/vsite.h"
-#include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/math/vec.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/utility/arrayref.h"
-struct gmx_device_info_t;
struct gmx_hw_info_t;
struct t_commrec;
struct t_fcdata;
+struct t_forcerec;
struct t_filenm;
struct t_inputrec;
struct gmx_gpu_info_t;
+struct gmx_localtop_t;
+struct gmx_mtop_t;
struct gmx_wallcycle;
+struct interaction_const_t;
namespace gmx
{
class PhysicalNodeCommunicator;
} // namespace gmx
-//! Destroy a forcerec.
-void done_forcerec(t_forcerec* fr, int numMolBlocks);
-
/*! \brief Print the contents of the forcerec to a file
*
* \param[in] fplog The log file to print to
/*! \brief Initiate table constants
*
* Initializes the tables in the interaction constant data structure.
- * \param[in] fp File for debugging output
- * \param[in] ic Structure holding the table constant
+ * \param[in] fp File for debugging output
+ * \param[in] ic Structure holding the table constant
+ * \param[in] tableExtensionLength Length by which to extend the tables. Taken from the input record.
*/
-void init_interaction_const_tables(FILE* fp, interaction_const_t* ic);
+void init_interaction_const_tables(FILE* fp, interaction_const_t* ic, real tableExtensionLength);
/*! \brief Initialize forcerec structure.
*
* \param[in] tabfn Table potential file for non-bonded interactions
* \param[in] tabpfn Table potential file for pair interactions
* \param[in] tabbfnm Table potential files for bonded interactions
- * \param[in] hardwareInfo Information about hardware
- * \param[in] deviceInfo Info about GPU device to use for short-ranged work
- * \param[in] useGpuForBonded Whether bonded interactions will run on a GPU
- * \param[in] pmeOnlyRankUsesGpu Whether there is a PME task on a GPU on a PME-only rank
* \param[in] print_force Print forces for atoms with force >= print_force
- * \param[out] wcycle Pointer to cycle counter object
*/
void init_forcerec(FILE* fplog,
const gmx::MDLogger& mdlog,
const char* tabfn,
const char* tabpfn,
gmx::ArrayRef<const std::string> tabbfnm,
- const gmx_hw_info_t& hardwareInfo,
- const gmx_device_info_t* deviceInfo,
- bool useGpuForBonded,
- bool pmeOnlyRankUsesGpu,
- real print_force,
- gmx_wallcycle* wcycle);
+ real print_force);
/*! \brief Check whether molecules are ever distributed over PBC boundaries
*
*/
void forcerec_set_excl_load(t_forcerec* fr, const gmx_localtop_t* top);
-void free_gpu_resources(t_forcerec* fr,
- const gmx::PhysicalNodeCommunicator& physicalNodeCommunicator,
- const gmx_gpu_info_t& gpu_info);
-
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* using CUDA, including class initialization, data-structures management
* and GPU kernel.
*
- * \todo Reconsider naming towards using "gpu" suffix instead of "cuda".
- *
* \author Artem Zhmurov <zhmurov@gmail.com>
*
* \ingroup module_mdlib
*/
#include "gmxpre.h"
-#include "leapfrog_cuda.cuh"
+#include "leapfrog_gpu.cuh"
#include <assert.h>
#include <stdio.h>
return kernelPtr;
}
-void LeapFrogCuda::integrate(const float3* d_x,
- float3* d_xp,
- float3* d_v,
- const float3* d_f,
- const real dt,
- const bool doTemperatureScaling,
- gmx::ArrayRef<const t_grp_tcstat> tcstat,
- const bool doParrinelloRahman,
- const float dtPressureCouple,
- const matrix prVelocityScalingMatrix)
+void LeapFrogGpu::integrate(const float3* d_x,
+ float3* d_xp,
+ float3* d_v,
+ const float3* d_f,
+ const real dt,
+ const bool doTemperatureScaling,
+ gmx::ArrayRef<const t_grp_tcstat> tcstat,
+ const bool doParrinelloRahman,
+ const float dtPressureCouple,
+ const matrix prVelocityScalingMatrix)
{
ensureNoPendingCudaError("In CUDA version of Leap-Frog integrator");
h_lambdas_[i] = tcstat[i].lambda;
}
copyToDeviceBuffer(&d_lambdas_, h_lambdas_.data(), 0, numTempScaleValues_,
- commandStream_, GpuApiCallBehavior::Async, nullptr);
+ deviceStream_, GpuApiCallBehavior::Async, nullptr);
}
VelocityScalingType prVelocityScalingType = VelocityScalingType::None;
if (doParrinelloRahman)
const auto kernelArgs = prepareGpuKernelArguments(
kernelPtr, kernelLaunchConfig_, &numAtoms_, &d_x, &d_xp, &d_v, &d_f, &d_inverseMasses_,
&dt, &d_lambdas_, &d_tempScaleGroups_, &prVelocityScalingMatrixDiagonal_);
- launchGpuKernel(kernelPtr, kernelLaunchConfig_, nullptr, "leapfrog_kernel", kernelArgs);
+ launchGpuKernel(kernelPtr, kernelLaunchConfig_, deviceStream_, nullptr, "leapfrog_kernel", kernelArgs);
return;
}
-LeapFrogCuda::LeapFrogCuda(CommandStream commandStream) : commandStream_(commandStream)
+LeapFrogGpu::LeapFrogGpu(const DeviceContext& deviceContext, const DeviceStream& deviceStream) :
+ deviceContext_(deviceContext),
+ deviceStream_(deviceStream)
{
numAtoms_ = 0;
kernelLaunchConfig_.blockSize[1] = 1;
kernelLaunchConfig_.blockSize[2] = 1;
kernelLaunchConfig_.sharedMemorySize = 0;
- kernelLaunchConfig_.stream = commandStream_;
}
-LeapFrogCuda::~LeapFrogCuda()
+LeapFrogGpu::~LeapFrogGpu()
{
freeDeviceBuffer(&d_inverseMasses_);
}
-void LeapFrogCuda::setPbc(const t_pbc* pbc)
-{
- setPbcAiuc(pbc->ndim_ePBC, pbc->box, &pbcAiuc_);
-}
-
-void LeapFrogCuda::set(const t_mdatoms& md, const int numTempScaleValues, const unsigned short* tempScaleGroups)
+void LeapFrogGpu::set(const t_mdatoms& md, const int numTempScaleValues, const unsigned short* tempScaleGroups)
{
numAtoms_ = md.nr;
kernelLaunchConfig_.gridSize[0] = (numAtoms_ + c_threadsPerBlock - 1) / c_threadsPerBlock;
numTempScaleValues_ = numTempScaleValues;
reallocateDeviceBuffer(&d_inverseMasses_, numAtoms_, &numInverseMasses_,
- &numInverseMassesAlloc_, nullptr);
- copyToDeviceBuffer(&d_inverseMasses_, (float*)md.invmass, 0, numAtoms_, commandStream_,
+ &numInverseMassesAlloc_, deviceContext_);
+ copyToDeviceBuffer(&d_inverseMasses_, (float*)md.invmass, 0, numAtoms_, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
// Temperature scale group map only used if there are more then one group
if (numTempScaleValues > 1)
{
reallocateDeviceBuffer(&d_tempScaleGroups_, numAtoms_, &numTempScaleGroups_,
- &numTempScaleGroupsAlloc_, nullptr);
- copyToDeviceBuffer(&d_tempScaleGroups_, tempScaleGroups, 0, numAtoms_, commandStream_,
+ &numTempScaleGroupsAlloc_, deviceContext_);
+ copyToDeviceBuffer(&d_tempScaleGroups_, tempScaleGroups, 0, numAtoms_, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
}
if (numTempScaleValues_ > 0)
{
h_lambdas_.resize(numTempScaleValues);
- reallocateDeviceBuffer(&d_lambdas_, numTempScaleValues_, &numLambdas_, &numLambdasAlloc_, nullptr);
+ reallocateDeviceBuffer(&d_lambdas_, numTempScaleValues_, &numLambdas_, &numLambdasAlloc_,
+ deviceContext_);
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \libinternal \file
*
- * \brief Declarations for CUDA implementation of Leap-Frog.
- *
- * \todo Reconsider naming towards using "gpu" suffix instead of "cuda".
+ * \brief Declarations for GPU implementation of Leap-Frog.
*
* \author Artem Zhmurov <zhmurov@gmail.com>
*
* \ingroup module_mdlib
* \inlibraryapi
*/
-#ifndef GMX_MDLIB_LEAPFROG_CUDA_CUH
-#define GMX_MDLIB_LEAPFROG_CUDA_CUH
+#ifndef GMX_MDLIB_LEAPFROG_GPU_CUH
+#define GMX_MDLIB_LEAPFROG_GPU_CUH
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/mdtypes/group.h"
namespace gmx
{
-class LeapFrogCuda
+class LeapFrogGpu
{
public:
/*! \brief Constructor.
*
- * \param[in] commandStream Device command stream to use.
- */
- LeapFrogCuda(CommandStream commandStream);
- ~LeapFrogCuda();
-
- /*! \brief
- * Update PBC data.
- *
- * Converts PBC data from t_pbc into the PbcAiuc format and stores the latter.
- *
- * \param[in] pbc The PBC data in t_pbc format.
+ * \param[in] deviceContext Device context (dummy in CUDA).
+ * \param[in] deviceStream Device stream to use.
*/
- void setPbc(const t_pbc* pbc);
+ LeapFrogGpu(const DeviceContext& deviceContext, const DeviceStream& deviceStream);
+ ~LeapFrogGpu();
/*! \brief Integrate
*
class Impl;
private:
- //! CUDA stream
- CommandStream commandStream_;
- //! CUDA kernel launch config
+ //! GPU context object
+ const DeviceContext& deviceContext_;
+ //! GPU stream
+ const DeviceStream& deviceStream_;
+ //! GPU kernel launch config
KernelLaunchConfig kernelLaunchConfig_;
- //! Periodic boundary data
- PbcAiuc pbcAiuc_;
//! Number of atoms
int numAtoms_;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/simd/simd.h"
#include "gromacs/simd/simd_math.h"
#include "gromacs/simd/vector_operations.h"
-#include "gromacs/topology/block.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/utility/alignedallocator.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/pleasecite.h"
using namespace gmx; // TODO: Remove when this file is moved into gmx namespace
#endif // GMX_SIMD_HAVE_REAL
/*! \brief LINCS projection, works on derivatives of the coordinates. */
-static void do_lincsp(const rvec* x,
- rvec* f,
- rvec* fp,
- t_pbc* pbc,
- Lincs* lincsd,
- int th,
- real* invmass,
- ConstraintVariable econq,
- bool bCalcDHDL,
- bool bCalcVir,
- tensor rmdf)
+static void do_lincsp(ArrayRefWithPadding<const RVec> xPadded,
+ ArrayRefWithPadding<RVec> fPadded,
+ ArrayRef<RVec> fp,
+ t_pbc* pbc,
+ Lincs* lincsd,
+ int th,
+ real* invmass,
+ ConstraintVariable econq,
+ bool bCalcDHDL,
+ bool bCalcVir,
+ tensor rmdf)
{
const int b0 = lincsd->task[th].b0;
const int b1 = lincsd->task[th].b1;
gmx::ArrayRef<real> rhs2 = lincsd->tmp2;
gmx::ArrayRef<real> sol = lincsd->tmp3;
+ const rvec* x = as_rvec_array(xPadded.paddedArrayRef().data());
+ rvec* f = as_rvec_array(fPadded.paddedArrayRef().data());
+
#if GMX_SIMD_HAVE_REAL
/* This SIMD code does the same as the plain-C code after the #else.
* The only difference is that we always call pbc code, as with SIMD
/* When constraining forces, we should not use mass weighting,
* so we pass invmass=NULL, which results in the use of 1 for all atoms.
*/
- lincs_update_atoms(lincsd, th, 1.0, sol, r,
- (econq != ConstraintVariable::Force) ? invmass : nullptr, fp);
+ lincs_update_atoms(lincsd, th, 1.0, sol, r, (econq != ConstraintVariable::Force) ? invmass : nullptr,
+ as_rvec_array(fp.data()));
if (bCalcDHDL)
{
#endif // GMX_SIMD_HAVE_REAL
//! Implements LINCS constraining.
-static void do_lincs(const rvec* x,
- rvec* xp,
- const matrix box,
- t_pbc* pbc,
- Lincs* lincsd,
- int th,
- const real* invmass,
- const t_commrec* cr,
- bool bCalcDHDL,
- real wangle,
- bool* bWarn,
- real invdt,
- rvec* gmx_restrict v,
- bool bCalcVir,
- tensor vir_r_m_dr)
+static void do_lincs(ArrayRefWithPadding<const RVec> xPadded,
+ ArrayRefWithPadding<RVec> xpPadded,
+ const matrix box,
+ t_pbc* pbc,
+ Lincs* lincsd,
+ int th,
+ const real* invmass,
+ const t_commrec* cr,
+ bool bCalcDHDL,
+ real wangle,
+ bool* bWarn,
+ real invdt,
+ ArrayRef<RVec> vRef,
+ bool bCalcVir,
+ tensor vir_r_m_dr)
{
+ const rvec* x = as_rvec_array(xPadded.paddedArrayRef().data());
+ rvec* xp = as_rvec_array(xpPadded.paddedArrayRef().data());
+ rvec* gmx_restrict v = as_rvec_array(vRef.data());
+
const int b0 = lincsd->task[th].b0;
const int b1 = lincsd->task[th].b1;
/* Communicate the corrected non-local coordinates */
if (DOMAINDECOMP(cr))
{
- dd_move_x_constraints(cr->dd, box, xp, nullptr, FALSE);
+ dd_move_x_constraints(cr->dd, box, xpPadded.unpaddedArrayRef(), ArrayRef<RVec>(), FALSE);
}
}
#pragma omp barrier
}
//! Finds all triangles of atoms that share constraints to a central atom.
-static int count_triangle_constraints(const InteractionLists& ilist, const t_blocka& at2con)
+static int count_triangle_constraints(const InteractionLists& ilist, const ListOfLists<int>& at2con)
{
- int ncon1, ncon_tot;
- int c0, n1, c1, ac1, n2, c2;
- int ncon_triangle;
-
- ncon1 = ilist[F_CONSTR].size() / 3;
- ncon_tot = ncon1 + ilist[F_CONSTRNC].size() / 3;
+ const int ncon1 = ilist[F_CONSTR].size() / 3;
+ const int ncon_tot = ncon1 + ilist[F_CONSTRNC].size() / 3;
gmx::ArrayRef<const int> ia1 = ilist[F_CONSTR].iatoms;
gmx::ArrayRef<const int> ia2 = ilist[F_CONSTRNC].iatoms;
- ncon_triangle = 0;
- for (c0 = 0; c0 < ncon_tot; c0++)
+ int ncon_triangle = 0;
+ for (int c0 = 0; c0 < ncon_tot; c0++)
{
bool bTriangle = FALSE;
const int* iap = constr_iatomptr(ia1, ia2, c0);
const int a00 = iap[1];
const int a01 = iap[2];
- for (n1 = at2con.index[a01]; n1 < at2con.index[a01 + 1]; n1++)
+ for (const int c1 : at2con[a01])
{
- c1 = at2con.a[n1];
if (c1 != c0)
{
const int* iap = constr_iatomptr(ia1, ia2, c1);
const int a10 = iap[1];
const int a11 = iap[2];
+ int ac1;
if (a10 == a01)
{
ac1 = a11;
{
ac1 = a10;
}
- for (n2 = at2con.index[ac1]; n2 < at2con.index[ac1 + 1]; n2++)
+ for (const int c2 : at2con[ac1])
{
- c2 = at2con.a[n2];
if (c2 != c0 && c2 != c1)
{
const int* iap = constr_iatomptr(ia1, ia2, c2);
}
//! Finds sequences of sequential constraints.
-static bool more_than_two_sequential_constraints(const InteractionLists& ilist, const t_blocka& at2con)
+static bool more_than_two_sequential_constraints(const InteractionLists& ilist, const ListOfLists<int>& at2con)
{
- int ncon1, ncon_tot, c;
- bool bMoreThanTwoSequentialConstraints;
-
- ncon1 = ilist[F_CONSTR].size() / 3;
- ncon_tot = ncon1 + ilist[F_CONSTRNC].size() / 3;
+ const int ncon1 = ilist[F_CONSTR].size() / 3;
+ const int ncon_tot = ncon1 + ilist[F_CONSTRNC].size() / 3;
gmx::ArrayRef<const int> ia1 = ilist[F_CONSTR].iatoms;
gmx::ArrayRef<const int> ia2 = ilist[F_CONSTRNC].iatoms;
- bMoreThanTwoSequentialConstraints = FALSE;
- for (c = 0; c < ncon_tot && !bMoreThanTwoSequentialConstraints; c++)
+ for (int c = 0; c < ncon_tot; c++)
{
const int* iap = constr_iatomptr(ia1, ia2, c);
const int a1 = iap[1];
const int a2 = iap[2];
/* Check if this constraint has constraints connected at both atoms */
- if (at2con.index[a1 + 1] - at2con.index[a1] > 1 && at2con.index[a2 + 1] - at2con.index[a2] > 1)
+ if (at2con[a1].ssize() > 1 && at2con[a2].ssize() > 1)
{
- bMoreThanTwoSequentialConstraints = TRUE;
+ return true;
}
}
- return bMoreThanTwoSequentialConstraints;
+ return false;
}
-Lincs* init_lincs(FILE* fplog,
- const gmx_mtop_t& mtop,
- int nflexcon_global,
- ArrayRef<const t_blocka> at2con,
- bool bPLINCS,
- int nIter,
- int nProjOrder)
+Lincs* init_lincs(FILE* fplog,
+ const gmx_mtop_t& mtop,
+ int nflexcon_global,
+ ArrayRef<const ListOfLists<int>> atomToConstraintsPerMolType,
+ bool bPLINCS,
+ int nIter,
+ int nProjOrder)
{
// TODO this should become a unique_ptr
Lincs* li;
li->max_connect = 0;
for (size_t mt = 0; mt < mtop.moltype.size(); mt++)
{
+ const auto& at2con = atomToConstraintsPerMolType[mt];
for (int a = 0; a < mtop.moltype[mt].atoms.nr; a++)
{
- li->max_connect = std::max(li->max_connect, at2con[mt].index[a + 1] - at2con[mt].index[a]);
+ li->max_connect = std::max(li->max_connect, int(at2con[a].ssize()));
}
}
bMoreThanTwoSeq = FALSE;
for (const gmx_molblock_t& molb : mtop.molblock)
{
- const gmx_moltype_t& molt = mtop.moltype[molb.type];
+ const gmx_moltype_t& molt = mtop.moltype[molb.type];
+ const auto& at2con = atomToConstraintsPerMolType[molb.type];
- li->ncg_triangle += molb.nmol * count_triangle_constraints(molt.ilist, at2con[molb.type]);
+ li->ncg_triangle += molb.nmol * count_triangle_constraints(molt.ilist, at2con);
- if (!bMoreThanTwoSeq && more_than_two_sequential_constraints(molt.ilist, at2con[molb.type]))
+ if (!bMoreThanTwoSeq && more_than_two_sequential_constraints(molt.ilist, at2con))
{
bMoreThanTwoSeq = TRUE;
}
}
//! Assign a constraint.
-static void assign_constraint(Lincs* li, int constraint_index, int a1, int a2, real lenA, real lenB, const t_blocka* at2con)
+static void assign_constraint(Lincs* li,
+ int constraint_index,
+ int a1,
+ int a2,
+ real lenA,
+ real lenB,
+ const ListOfLists<int>& at2con)
{
int con;
/* Make space in the constraint connection matrix for constraints
* connected to both end of the current constraint.
*/
- li->ncc += at2con->index[a1 + 1] - at2con->index[a1] - 1 + at2con->index[a2 + 1]
- - at2con->index[a2] - 1;
+ li->ncc += at2con[a1].ssize() - 1 + at2con[a2].ssize() - 1;
li->blnr[con + 1] = li->ncc;
/*! \brief Check if constraint with topology index constraint_index is connected
* to other constraints, and if so add those connected constraints to our task. */
-static void check_assign_connected(Lincs* li,
- const t_iatom* iatom,
- const t_idef& idef,
- bool bDynamics,
- int a1,
- int a2,
- const t_blocka* at2con)
+static void check_assign_connected(Lincs* li,
+ gmx::ArrayRef<const int> iatom,
+ const InteractionDefinitions& idef,
+ bool bDynamics,
+ int a1,
+ int a2,
+ const ListOfLists<int>& at2con)
{
/* Currently this function only supports constraint groups
* in which all constraints share at least one atom
* connected constraints. We need to assign those
* to the same task.
*/
- int end;
-
- for (end = 0; end < 2; end++)
+ for (int end = 0; end < 2; end++)
{
- int a, k;
+ const int a = (end == 0 ? a1 : a2);
- a = (end == 0 ? a1 : a2);
-
- for (k = at2con->index[a]; k < at2con->index[a + 1]; k++)
+ for (const int cc : at2con[a])
{
- int cc;
-
- cc = at2con->a[k];
/* Check if constraint cc has not yet been assigned */
if (li->con_index[cc] == -1)
{
- int type;
- real lenA, lenB;
-
- type = iatom[cc * 3];
- lenA = idef.iparams[type].constr.dA;
- lenB = idef.iparams[type].constr.dB;
+ const int type = iatom[cc * 3];
+ const real lenA = idef.iparams[type].constr.dA;
+ const real lenB = idef.iparams[type].constr.dB;
if (bDynamics || lenA != 0 || lenB != 0)
{
/*! \brief Check if constraint with topology index constraint_index is involved
* in a constraint triangle, and if so add the other two constraints
* in the triangle to our task. */
-static void check_assign_triangle(Lincs* li,
- const t_iatom* iatom,
- const t_idef& idef,
- bool bDynamics,
- int constraint_index,
- int a1,
- int a2,
- const t_blocka* at2con)
+static void check_assign_triangle(Lincs* li,
+ gmx::ArrayRef<const int> iatom,
+ const InteractionDefinitions& idef,
+ bool bDynamics,
+ int constraint_index,
+ int a1,
+ int a2,
+ const ListOfLists<int>& at2con)
{
- int nca, cc[32], ca[32], k;
+ int nca, cc[32], ca[32];
int c_triangle[2] = { -1, -1 };
nca = 0;
- for (k = at2con->index[a1]; k < at2con->index[a1 + 1]; k++)
+ for (const int c : at2con[a1])
{
- int c;
-
- c = at2con->a[k];
if (c != constraint_index)
{
int aa1, aa2;
}
}
- for (k = at2con->index[a2]; k < at2con->index[a2 + 1]; k++)
+ for (const int c : at2con[a2])
{
- int c;
-
- c = at2con->a[k];
if (c != constraint_index)
{
int aa1, aa2, i;
}
//! Sets matrix indices.
-static void set_matrix_indices(Lincs* li, const Task& li_task, const t_blocka* at2con, bool bSortMatrix)
+static void set_matrix_indices(Lincs* li, const Task& li_task, const ListOfLists<int>& at2con, bool bSortMatrix)
{
for (int b = li_task.b0; b < li_task.b1; b++)
{
const int a2 = li->atoms[b].index2;
int i = li->blnr[b];
- for (int k = at2con->index[a1]; k < at2con->index[a1 + 1]; k++)
+ for (const int constraint : at2con[a1])
{
- int concon = li->con_index[at2con->a[k]];
+ const int concon = li->con_index[constraint];
if (concon != b)
{
li->blbnb[i++] = concon;
}
}
- for (int k = at2con->index[a2]; k < at2con->index[a2 + 1]; k++)
+ for (const int constraint : at2con[a2])
{
- int concon = li->con_index[at2con->a[k]];
+ const int concon = li->con_index[constraint];
if (concon != b)
{
li->blbnb[i++] = concon;
}
}
-void set_lincs(const t_idef& idef, const t_mdatoms& md, bool bDynamics, const t_commrec* cr, Lincs* li)
+void set_lincs(const InteractionDefinitions& idef, const t_mdatoms& md, bool bDynamics, const t_commrec* cr, Lincs* li)
{
- int natoms;
- t_blocka at2con;
- t_iatom* iatom;
-
li->nc_real = 0;
li->nc = 0;
li->ncc = 0;
}
/* This is the local topology, so there are only F_CONSTR constraints */
- if (idef.il[F_CONSTR].nr == 0)
+ if (idef.il[F_CONSTR].empty())
{
/* There are no constraints,
* we do not need to fill any data structures.
fprintf(debug, "Building the LINCS connectivity\n");
}
+ int natoms;
if (DOMAINDECOMP(cr))
{
if (cr->dd->constraints)
natoms = md.homenr;
}
- at2con = make_at2con(natoms, idef.il, idef.iparams, flexibleConstraintTreatment(bDynamics));
+ const ListOfLists<int> at2con =
+ make_at2con(natoms, idef.il, idef.iparams, flexibleConstraintTreatment(bDynamics));
- const int ncon_tot = idef.il[F_CONSTR].nr / 3;
+ const int ncon_tot = idef.il[F_CONSTR].size() / 3;
/* Ensure we have enough padding for aligned loads for each thread */
const int numEntries = ncon_tot + li->ntask * simd_width;
li->tmp4.resize(numEntries);
li->mlambda.resize(numEntries);
- iatom = idef.il[F_CONSTR].iatoms;
+ gmx::ArrayRef<const int> iatom = idef.il[F_CONSTR].iatoms;
li->blnr[0] = li->ncc;
*/
li_task->b0 = li->nc;
+ gmx::ArrayRef<const t_iparams> iparams = idef.iparams;
+
while (con < ncon_tot && li->nc - li_task->b0 < ncon_target)
{
if (li->con_index[con] == -1)
type = iatom[3 * con];
a1 = iatom[3 * con + 1];
a2 = iatom[3 * con + 2];
- lenA = idef.iparams[type].constr.dA;
- lenB = idef.iparams[type].constr.dB;
+ lenA = iparams[type].constr.dA;
+ lenB = iparams[type].constr.dB;
/* Skip the flexible constraints when not doing dynamics */
if (bDynamics || lenA != 0 || lenB != 0)
{
- assign_constraint(li, con, a1, a2, lenA, lenB, &at2con);
+ assign_constraint(li, con, a1, a2, lenA, lenB, at2con);
if (li->ntask > 1 && !li->bTaskDep)
{
/* We can generate independent tasks. Check if we
* need to assign connected constraints to our task.
*/
- check_assign_connected(li, iatom, idef, bDynamics, a1, a2, &at2con);
+ check_assign_connected(li, iatom, idef, bDynamics, a1, a2, at2con);
}
if (li->ntask > 1 && li->ncg_triangle > 0)
{
/* Ensure constraints in one triangle are assigned
* to the same task.
*/
- check_assign_triangle(li, iatom, idef, bDynamics, con, a1, a2, &at2con);
+ check_assign_triangle(li, iatom, idef, bDynamics, con, a1, a2, at2con);
}
}
}
li_task.tri_bits.resize(li_task.b1 - li_task.b0);
}
- set_matrix_indices(li, li_task, &at2con, bSortMatrix);
+ set_matrix_indices(li, li_task, at2con, bSortMatrix);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
- done_blocka(&at2con);
-
if (cr->dd == nullptr)
{
/* Since the matrix is static, we should free some memory */
//! Issues a warning when LINCS constraints cannot be satisfied.
static void lincs_warning(gmx_domdec_t* dd,
- const rvec* x,
- rvec* xprime,
+ ArrayRef<const RVec> x,
+ ArrayRef<const RVec> xprime,
t_pbc* pbc,
int ncons,
gmx::ArrayRef<const AtomPair> atoms,
};
//! Determine how well the constraints have been satisfied.
-static LincsDeviations makeLincsDeviations(const Lincs& lincsd, const rvec* x, const t_pbc* pbc)
+static LincsDeviations makeLincsDeviations(const Lincs& lincsd, ArrayRef<const RVec> x, const t_pbc* pbc)
{
LincsDeviations result;
const ArrayRef<const AtomPair> atoms = lincsd.atoms;
return result;
}
-bool constrain_lincs(bool computeRmsd,
- const t_inputrec& ir,
- int64_t step,
- Lincs* lincsd,
- const t_mdatoms& md,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- const rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- t_pbc* pbc,
- real lambda,
- real* dvdlambda,
- real invdt,
- rvec* v,
- bool bCalcVir,
- tensor vir_r_m_dr,
- ConstraintVariable econq,
- t_nrnb* nrnb,
- int maxwarn,
- int* warncount)
+bool constrain_lincs(bool computeRmsd,
+ const t_inputrec& ir,
+ int64_t step,
+ Lincs* lincsd,
+ const t_mdatoms& md,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ ArrayRefWithPadding<const RVec> xPadded,
+ ArrayRefWithPadding<RVec> xprimePadded,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ t_pbc* pbc,
+ real lambda,
+ real* dvdlambda,
+ real invdt,
+ ArrayRef<RVec> v,
+ bool bCalcVir,
+ tensor vir_r_m_dr,
+ ConstraintVariable econq,
+ t_nrnb* nrnb,
+ int maxwarn,
+ int* warncount)
{
bool bOK = TRUE;
return bOK;
}
+ ArrayRef<const RVec> x = xPadded.unpaddedArrayRef();
+ ArrayRef<RVec> xprime = xprimePadded.unpaddedArrayRef();
+
if (econq == ConstraintVariable::Positions)
{
/* We can't use bCalcDHDL here, since NULL can be passed for dvdlambda
clear_mat(lincsd->task[th].vir_r_m_dr);
- do_lincs(x, xprime, box, pbc, lincsd, th, md.invmass, cr, bCalcDHDL, ir.LincsWarnAngle,
- &bWarn, invdt, v, bCalcVir, th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
+ do_lincs(xPadded, xprimePadded, box, pbc, lincsd, th, md.invmass, cr, bCalcDHDL,
+ ir.LincsWarnAngle, &bWarn, invdt, v, bCalcVir,
+ th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
{
int th = gmx_omp_get_thread_num();
- do_lincsp(x, xprime, min_proj, pbc, lincsd, th, md.invmass, econq, bCalcDHDL,
- bCalcVir, th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
+ do_lincsp(xPadded, xprimePadded, min_proj, pbc, lincsd, th, md.invmass, econq,
+ bCalcDHDL, bCalcVir, th == 0 ? vir_r_m_dr : lincsd->task[th].vir_r_m_dr);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
{
inc_nrnb(nrnb, eNR_LINCSMAT, lincsd->nOrder * lincsd->ncc_triangle);
}
- if (v)
+ if (!v.empty())
{
inc_nrnb(nrnb, eNR_CONSTR_V, lincsd->nc_real * 2);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_mtop_t;
struct gmx_multisim_t;
-struct t_blocka;
+class InteractionDefinitions;
struct t_commrec;
-struct t_idef;
struct t_inputrec;
struct t_mdatoms;
struct t_nrnb;
namespace gmx
{
+template<typename>
+class ArrayRefWithPadding;
enum class ConstraintVariable : int;
-
-/* Abstract type for LINCS that is defined only in the file that uses it */
class Lincs;
+template<typename>
+class ListOfLists;
+
/*! \brief Return the data for determining constraint RMS relative deviations. */
ArrayRef<real> lincs_rmsdData(Lincs* lincsd);
real lincs_rmsd(const Lincs* lincsd);
/*! \brief Initializes and returns the lincs data struct. */
-Lincs* init_lincs(FILE* fplog,
- const gmx_mtop_t& mtop,
- int nflexcon_global,
- ArrayRef<const t_blocka> at2con,
- bool bPLINCS,
- int nIter,
- int nProjOrder);
+Lincs* init_lincs(FILE* fplog,
+ const gmx_mtop_t& mtop,
+ int nflexcon_global,
+ ArrayRef<const ListOfLists<int>> atomsToConstraintsPerMolType,
+ bool bPLINCS,
+ int nIter,
+ int nProjOrder);
/*! \brief Destructs the lincs object when it is not nullptr. */
void done_lincs(Lincs* li);
/*! \brief Initialize lincs stuff */
-void set_lincs(const t_idef& idef, const t_mdatoms& md, bool bDynamics, const t_commrec* cr, Lincs* li);
+void set_lincs(const InteractionDefinitions& idef,
+ const t_mdatoms& md,
+ bool bDynamics,
+ const t_commrec* cr,
+ Lincs* li);
/*! \brief Applies LINCS constraints.
*
* \returns true if the constraining succeeded. */
-bool constrain_lincs(bool computeRmsd,
- const t_inputrec& ir,
- int64_t step,
- Lincs* lincsd,
- const t_mdatoms& md,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- const rvec* x,
- rvec* xprime,
- rvec* min_proj,
- const matrix box,
- t_pbc* pbc,
- real lambda,
- real* dvdlambda,
- real invdt,
- rvec* v,
- bool bCalcVir,
- tensor vir_r_m_dr,
- ConstraintVariable econq,
- t_nrnb* nrnb,
- int maxwarn,
- int* warncount);
+bool constrain_lincs(bool computeRmsd,
+ const t_inputrec& ir,
+ int64_t step,
+ Lincs* lincsd,
+ const t_mdatoms& md,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ ArrayRefWithPadding<const RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ ArrayRef<RVec> min_proj,
+ const matrix box,
+ t_pbc* pbc,
+ real lambda,
+ real* dvdlambda,
+ real invdt,
+ ArrayRef<RVec> v,
+ bool bCalcVir,
+ tensor vir_r_m_dr,
+ ConstraintVariable econq,
+ t_nrnb* nrnb,
+ int maxwarn,
+ int* warncount);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* using CUDA, including class initialization, data-structures management
* and GPU kernel.
*
- * \note Management of periodic boundary should be unified with SETTLE and
- * removed from here.
- * \todo Reconsider naming, i.e. "cuda" suffics should be changed to "gpu".
- *
* \author Artem Zhmurov <zhmurov@gmail.com>
* \author Alan Gray <alang@nvidia.com>
*
*/
#include "gmxpre.h"
-#include "lincs_cuda.cuh"
+#include "lincs_gpu.cuh"
#include <assert.h>
#include <stdio.h>
#include "gromacs/mdlib/constr.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/pbc_aiuc_cuda.cuh"
+#include "gromacs/topology/forcefieldparameters.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/topology.h"
* 3. Use analytical solution for matrix A inversion.
* 4. Introduce mapping of thread id to both single constraint and single atom, thus designating
* Nth threads to deal with Nat <= Nth coupled atoms and Nc <= Nth coupled constraints.
- * See Redmine issue #2885 for details (https://redmine.gromacs.org/issues/2885)
+ * See Issue #2885 for details (https://gitlab.com/gromacs/gromacs/-/issues/2885)
* \todo The use of __restrict__ for gm_xp and gm_v causes failure, probably because of the atomic
operations. Investigate this issue further.
*
*/
template<bool updateVelocities, bool computeVirial>
__launch_bounds__(c_maxThreadsPerBlock) __global__
- void lincs_kernel(LincsCudaKernelParameters kernelParams,
+ void lincs_kernel(LincsGpuKernelParameters kernelParams,
const float3* __restrict__ gm_x,
float3* gm_xp,
float3* gm_v,
return kernelPtr;
}
-void LincsCuda::apply(const float3* d_x,
- float3* d_xp,
- const bool updateVelocities,
- float3* d_v,
- const real invdt,
- const bool computeVirial,
- tensor virialScaled)
+void LincsGpu::apply(const float3* d_x,
+ float3* d_xp,
+ const bool updateVelocities,
+ float3* d_v,
+ const real invdt,
+ const bool computeVirial,
+ tensor virialScaled,
+ const PbcAiuc pbcAiuc)
{
ensureNoPendingCudaError("In CUDA version of LINCS");
{
// Fill with zeros so the values can be reduced to it
// Only 6 values are needed because virial is symmetrical
- clearDeviceBufferAsync(&kernelParams_.d_virialScaled, 0, 6, commandStream_);
+ clearDeviceBufferAsync(&kernelParams_.d_virialScaled, 0, 6, deviceStream_);
}
auto kernelPtr = getLincsKernelPtr(updateVelocities, computeVirial);
{
config.sharedMemorySize = c_threadsPerBlock * 3 * sizeof(float);
}
- config.stream = commandStream_;
+
+ kernelParams_.pbcAiuc = pbcAiuc;
const auto kernelArgs =
prepareGpuKernelArguments(kernelPtr, config, &kernelParams_, &d_x, &d_xp, &d_v, &invdt);
- launchGpuKernel(kernelPtr, config, nullptr, "lincs_kernel<updateVelocities, computeVirial>", kernelArgs);
+ launchGpuKernel(kernelPtr, config, deviceStream_, nullptr,
+ "lincs_kernel<updateVelocities, computeVirial>", kernelArgs);
if (computeVirial)
{
// Copy LINCS virial data and add it to the common virial
copyFromDeviceBuffer(h_virialScaled_.data(), &kernelParams_.d_virialScaled, 0, 6,
- commandStream_, GpuApiCallBehavior::Sync, nullptr);
+ deviceStream_, GpuApiCallBehavior::Sync, nullptr);
// Mapping [XX, XY, XZ, YY, YZ, ZZ] internal format to a tensor object
virialScaled[XX][XX] += h_virialScaled_[0];
return;
}
-LincsCuda::LincsCuda(int numIterations, int expansionOrder, CommandStream commandStream) :
- commandStream_(commandStream)
+LincsGpu::LincsGpu(int numIterations,
+ int expansionOrder,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream) :
+ deviceContext_(deviceContext),
+ deviceStream_(deviceStream)
{
kernelParams_.numIterations = numIterations;
kernelParams_.expansionOrder = expansionOrder;
c_threadsPerBlock > 0 && ((c_threadsPerBlock & (c_threadsPerBlock - 1)) == 0),
"Number of threads per block should be a power of two in order for reduction to work.");
- allocateDeviceBuffer(&kernelParams_.d_virialScaled, 6, nullptr);
+ allocateDeviceBuffer(&kernelParams_.d_virialScaled, 6, deviceContext_);
h_virialScaled_.resize(6);
// The data arrays should be expanded/reallocated on first call of set() function.
numAtomsAlloc_ = 0;
}
-LincsCuda::~LincsCuda()
+LincsGpu::~LincsGpu()
{
freeDeviceBuffer(&kernelParams_.d_virialScaled);
return numCoupledConstraints;
}
-bool LincsCuda::isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop)
+bool LincsGpu::isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop)
{
for (const gmx_moltype_t& molType : mtop.moltype)
{
return true;
}
-void LincsCuda::set(const t_idef& idef, const t_mdatoms& md)
+void LincsGpu::set(const InteractionDefinitions& idef, const t_mdatoms& md)
{
int numAtoms = md.nr;
// List of constrained atoms (CPU memory)
std::vector<float> massFactorsHost;
// List of constrained atoms in local topology
- gmx::ArrayRef<const int> iatoms =
- constArrayRefFromArray(idef.il[F_CONSTR].iatoms, idef.il[F_CONSTR].nr);
- const int stride = NRAL(F_CONSTR) + 1;
- const int numConstraints = idef.il[F_CONSTR].nr / stride;
+ ArrayRef<const int> iatoms = idef.il[F_CONSTR].iatoms;
+ const int stride = NRAL(F_CONSTR) + 1;
+ const int numConstraints = idef.il[F_CONSTR].size() / stride;
// Early exit if no constraints
if (numConstraints == 0)
numConstraintsThreadsAlloc_ = kernelParams_.numConstraintsThreads;
- allocateDeviceBuffer(&kernelParams_.d_constraints, kernelParams_.numConstraintsThreads, nullptr);
+ allocateDeviceBuffer(&kernelParams_.d_constraints, kernelParams_.numConstraintsThreads,
+ deviceContext_);
allocateDeviceBuffer(&kernelParams_.d_constraintsTargetLengths,
- kernelParams_.numConstraintsThreads, nullptr);
+ kernelParams_.numConstraintsThreads, deviceContext_);
allocateDeviceBuffer(&kernelParams_.d_coupledConstraintsCounts,
- kernelParams_.numConstraintsThreads, nullptr);
+ kernelParams_.numConstraintsThreads, deviceContext_);
allocateDeviceBuffer(&kernelParams_.d_coupledConstraintsIndices,
- maxCoupledConstraints * kernelParams_.numConstraintsThreads, nullptr);
+ maxCoupledConstraints * kernelParams_.numConstraintsThreads, deviceContext_);
allocateDeviceBuffer(&kernelParams_.d_massFactors,
- maxCoupledConstraints * kernelParams_.numConstraintsThreads, nullptr);
+ maxCoupledConstraints * kernelParams_.numConstraintsThreads, deviceContext_);
allocateDeviceBuffer(&kernelParams_.d_matrixA,
- maxCoupledConstraints * kernelParams_.numConstraintsThreads, nullptr);
+ maxCoupledConstraints * kernelParams_.numConstraintsThreads, deviceContext_);
}
// (Re)allocate the memory, if the number of atoms has increased.
freeDeviceBuffer(&kernelParams_.d_inverseMasses);
}
numAtomsAlloc_ = numAtoms;
- allocateDeviceBuffer(&kernelParams_.d_inverseMasses, numAtoms, nullptr);
+ allocateDeviceBuffer(&kernelParams_.d_inverseMasses, numAtoms, deviceContext_);
}
// Copy data to GPU.
copyToDeviceBuffer(&kernelParams_.d_constraints, constraintsHost.data(), 0,
- kernelParams_.numConstraintsThreads, commandStream_,
- GpuApiCallBehavior::Sync, nullptr);
+ kernelParams_.numConstraintsThreads, deviceStream_, GpuApiCallBehavior::Sync,
+ nullptr);
copyToDeviceBuffer(&kernelParams_.d_constraintsTargetLengths,
constraintsTargetLengthsHost.data(), 0, kernelParams_.numConstraintsThreads,
- commandStream_, GpuApiCallBehavior::Sync, nullptr);
+ deviceStream_, GpuApiCallBehavior::Sync, nullptr);
copyToDeviceBuffer(&kernelParams_.d_coupledConstraintsCounts,
coupledConstraintsCountsHost.data(), 0, kernelParams_.numConstraintsThreads,
- commandStream_, GpuApiCallBehavior::Sync, nullptr);
+ deviceStream_, GpuApiCallBehavior::Sync, nullptr);
copyToDeviceBuffer(&kernelParams_.d_coupledConstraintsIndices, coupledConstraintsIndicesHost.data(),
0, maxCoupledConstraints * kernelParams_.numConstraintsThreads,
- commandStream_, GpuApiCallBehavior::Sync, nullptr);
+ deviceStream_, GpuApiCallBehavior::Sync, nullptr);
copyToDeviceBuffer(&kernelParams_.d_massFactors, massFactorsHost.data(), 0,
- maxCoupledConstraints * kernelParams_.numConstraintsThreads, commandStream_,
+ maxCoupledConstraints * kernelParams_.numConstraintsThreads, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
GMX_RELEASE_ASSERT(md.invmass != nullptr, "Masses of atoms should be specified.\n");
- copyToDeviceBuffer(&kernelParams_.d_inverseMasses, md.invmass, 0, numAtoms, commandStream_,
+ copyToDeviceBuffer(&kernelParams_.d_inverseMasses, md.invmass, 0, numAtoms, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
}
-void LincsCuda::setPbc(const t_pbc* pbc)
-{
- setPbcAiuc(pbc->ndim_ePBC, pbc->box, &kernelParams_.pbcAiuc);
-}
-
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \libinternal \file
*
- * \brief Declares the class for CUDA implementation of LINCS.
+ * \brief Declares the class for GPU implementation of LINCS.
*
* \author Artem Zhmurov <zhmurov@gmail.com>
*
* \ingroup module_mdlib
* \inlibraryapi
*/
-#ifndef GMX_MDLIB_LINCS_CUDA_CUH
-#define GMX_MDLIB_LINCS_CUDA_CUH
+#ifndef GMX_MDLIB_LINCS_GPU_CUH
+#define GMX_MDLIB_LINCS_GPU_CUH
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc_aiuc.h"
-#include "gromacs/topology/idef.h"
#include "gromacs/utility/classhelpers.h"
+class InteractionDefinitions;
+
namespace gmx
{
* to the GPU as a single structure.
*
*/
-struct LincsCudaKernelParameters
+struct LincsGpuKernelParameters
{
//! Periodic boundary data
PbcAiuc pbcAiuc;
float* d_massFactors;
};
-/*! \internal \brief Class with interfaces and data for CUDA version of LINCS. */
-class LincsCuda
+/*! \internal \brief Class with interfaces and data for GPU version of LINCS. */
+class LincsGpu
{
public:
*
* \param[in] numIterations Number of iteration for the correction of the projection.
* \param[in] expansionOrder Order of the matrix inversion algorithm.
- * \param[in] commandStream Device command stream.
+ * \param[in] deviceContext Device context (dummy in CUDA).
+ * \param[in] deviceStream Device command stream.
*/
- LincsCuda(int numIterations, int expansionOrder, CommandStream commandStream);
+ LincsGpu(int numIterations,
+ int expansionOrder,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream);
/*! \brief Destructor.*/
- ~LincsCuda();
+ ~LincsGpu();
/*! \brief Apply LINCS.
*
* Applies LINCS to coordinates and velocities, stored on GPU.
* The results are not automatically copied back to the CPU memory.
* Method uses this class data structures which should be updated
- * when needed using set() and setPbc() method.
+ * when needed using set() method.
*
* \param[in] d_x Coordinates before timestep (in GPU memory)
* \param[in,out] d_xp Coordinates after timestep (in GPU memory). The
* multipliers when velocities are updated)
* \param[in] computeVirial If virial should be updated.
* \param[in,out] virialScaled Scaled virial tensor to be updated.
+ * \param[in] pbcAiuc PBC data.
*/
void apply(const float3* d_x,
float3* d_xp,
float3* d_v,
const real invdt,
const bool computeVirial,
- tensor virialScaled);
+ tensor virialScaled,
+ const PbcAiuc pbcAiuc);
/*! \brief
* Update data-structures (e.g. after NB search step).
* \param[in] idef Local topology data to get information on constraints from.
* \param[in] md Atoms data to get atom masses from.
*/
- void set(const t_idef& idef, const t_mdatoms& md);
-
- /*! \brief
- * Update PBC data.
- *
- * Converts pbc data from t_pbc into the PbcAiuc format and stores the latter.
- *
- * \todo Remove this method. LINCS should not manage PBC.
- *
- * \param[in] pbc The PBC data in t_pbc format.
- */
- void setPbc(const t_pbc* pbc);
+ void set(const InteractionDefinitions& idef, const t_mdatoms& md);
/*! \brief
* Returns whether the maximum number of coupled constraints is supported
- * by the CUDA LINCS code.
+ * by the GPU LINCS code.
*
* \param[in] mtop The molecular topology
*/
static bool isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop);
private:
- //! CUDA stream
- CommandStream commandStream_;
+ //! GPU context object
+ const DeviceContext& deviceContext_;
+ //! GPU stream
+ const DeviceStream& deviceStream_;
- //! Parameters and pointers, passed to the CUDA kernel
- LincsCudaKernelParameters kernelParams_;
+ //! Parameters and pointers, passed to the GPU kernel
+ LincsGpuKernelParameters kernelParams_;
//! Scaled virial tensor (6 floats: [XX, XY, XZ, YY, YZ, ZZ])
std::vector<float> h_virialScaled_;
} // namespace gmx
-#endif // GMX_MDLIB_LINCS_CUDA_CUH
+#endif // GMX_MDLIB_LINCS_GPU_CUH
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
/* TODO Specialize this routine into init-time and loop-time versions?
e.g. bReadEkin is only true when restoring from checkpoint */
-void compute_globals(gmx_global_stat* gstat,
- t_commrec* cr,
- const t_inputrec* ir,
- t_forcerec* fr,
- gmx_ekindata_t* ekind,
- const rvec* x,
- const rvec* v,
- const matrix box,
- real vdwLambda,
- const t_mdatoms* mdatoms,
- t_nrnb* nrnb,
- t_vcm* vcm,
- gmx_wallcycle_t wcycle,
- gmx_enerdata_t* enerd,
- tensor force_vir,
- tensor shake_vir,
- tensor total_vir,
- tensor pres,
- rvec mu_tot,
- gmx::Constraints* constr,
- gmx::SimulationSignaller* signalCoordinator,
- const matrix lastbox,
- int* totalNumberOfBondedInteractions,
- gmx_bool* bSumEkinhOld,
- const int flags)
+void compute_globals(gmx_global_stat* gstat,
+ t_commrec* cr,
+ const t_inputrec* ir,
+ t_forcerec* fr,
+ gmx_ekindata_t* ekind,
+ gmx::ArrayRef<const gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> v,
+ const matrix box,
+ real vdwLambda,
+ const t_mdatoms* mdatoms,
+ t_nrnb* nrnb,
+ t_vcm* vcm,
+ gmx_wallcycle_t wcycle,
+ gmx_enerdata_t* enerd,
+ tensor force_vir,
+ tensor shake_vir,
+ tensor total_vir,
+ tensor pres,
+ gmx::Constraints* constr,
+ gmx::SimulationSignaller* signalCoordinator,
+ const matrix lastbox,
+ int* totalNumberOfBondedInteractions,
+ gmx_bool* bSumEkinhOld,
+ const int flags)
{
gmx_bool bEner, bPres, bTemp;
gmx_bool bStopCM, bGStat, bReadEkin, bEkinAveVel, bScaleEkin, bConstrain;
if (PAR(cr))
{
wallcycle_start(wcycle, ewcMoveE);
- global_stat(gstat, cr, enerd, force_vir, shake_vir, mu_tot, ir, ekind, constr,
+ global_stat(gstat, cr, enerd, force_vir, shake_vir, ir, ekind, constr,
bStopCM ? vcm : nullptr, signalBuffer.size(), signalBuffer.data(),
totalNumberOfBondedInteractions, *bSumEkinhOld, flags);
wallcycle_stop(wcycle, ewcMoveE);
enerd->dvdl_lin[efptMASS] = static_cast<double>(dvdl_ekin);
enerd->term[F_EKIN] = trace(ekind->ekin);
+
+ for (auto& dhdl : enerd->dhdlLambda)
+ {
+ dhdl += enerd->dvdl_lin[efptMASS];
+ }
}
/* ########## Now pressure ############## */
* Use the box from last timestep since we already called update().
*/
- enerd->term[F_PRES] = calc_pres(fr->ePBC, ir->nwall, lastbox, ekind->ekin, total_vir, pres);
+ enerd->term[F_PRES] = calc_pres(fr->pbcType, ir->nwall, lastbox, ekind->ekin, total_vir, pres);
}
/* ########## Long range energy information ###### */
}
xp = fr->x;
vp = fr->v;
- gmx_bcast(sizeof(*fr), fr, cr);
+ gmx_bcast(sizeof(*fr), fr, cr->mpi_comm_mygroup);
fr->x = xp;
fr->v = vp;
}
state->nnhpres = 0;
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
state->flags |= (1 << estBOX);
if (inputrecPreserveShape(ir))
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* and for COM removal with rotational and acceleration correction modes.
* Velocities v are needed for kinetic energy calculation and for COM removal.
*/
-void compute_globals(gmx_global_stat* gstat,
- t_commrec* cr,
- const t_inputrec* ir,
- t_forcerec* fr,
- gmx_ekindata_t* ekind,
- const rvec* x,
- const rvec* v,
- const matrix box,
- real vdwLambda,
- const t_mdatoms* mdatoms,
- t_nrnb* nrnb,
- t_vcm* vcm,
- gmx_wallcycle_t wcycle,
- gmx_enerdata_t* enerd,
- tensor force_vir,
- tensor shake_vir,
- tensor total_vir,
- tensor pres,
- rvec mu_tot,
- gmx::Constraints* constr,
- gmx::SimulationSignaller* signalCoordinator,
- const matrix lastbox,
- int* totalNumberOfBondedInteractions,
- gmx_bool* bSumEkinhOld,
- int flags);
+void compute_globals(gmx_global_stat* gstat,
+ t_commrec* cr,
+ const t_inputrec* ir,
+ t_forcerec* fr,
+ gmx_ekindata_t* ekind,
+ gmx::ArrayRef<const gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> v,
+ const matrix box,
+ real vdwLambda,
+ const t_mdatoms* mdatoms,
+ t_nrnb* nrnb,
+ t_vcm* vcm,
+ gmx_wallcycle_t wcycle,
+ gmx_enerdata_t* enerd,
+ tensor force_vir,
+ tensor shake_vir,
+ tensor total_vir,
+ tensor pres,
+ gmx::Constraints* constr,
+ gmx::SimulationSignaller* signalCoordinator,
+ const matrix lastbox,
+ int* totalNumberOfBondedInteractions,
+ gmx_bool* bSumEkinhOld,
+ int flags);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/hostallocator.h"
#include "gromacs/math/functions.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/topology/mtop_lookup.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
sfree(mdatoms_->bPerturbed);
sfree(mdatoms_->cU1);
sfree(mdatoms_->cU2);
- sfree(mdatoms_->bQM);
}
void MDAtoms::resize(int newSize)
{
srenew(md->cU2, md->nalloc);
}
-
- if (ir->bQMMM)
- {
- srenew(md->bQM, md->nalloc);
- }
}
int molb = 0;
{
md->cU2[i] = groups.groupNumbers[SimulationAtomGroupType::User2][ag];
}
-
- if (ir->bQMMM)
- {
- if (groups.groupNumbers[SimulationAtomGroupType::QuantumMechanics].empty()
- || groups.groupNumbers[SimulationAtomGroupType::QuantumMechanics][ag]
- < groups.groups[SimulationAtomGroupType::QuantumMechanics].size() - 1)
- {
- md->bQM[i] = TRUE;
- }
- else
- {
- md->bQM[i] = FALSE;
- }
- }
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
#include "gromacs/gpu_utils/hostallocator.h"
-#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
#include "gromacs/utility/unique_cptr.h"
struct gmx_mtop_t;
struct t_inputrec;
+struct t_mdatoms;
namespace gmx
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
dhc->start_lambda = deltaH->start_lambda;
}
- if (dhc->dh[0].ndh > 0)
- {
- dhc->start_time_set = TRUE;
- }
- else
- {
- dhc->start_time_set = FALSE;
- }
+ dhc->start_time_set = (dhc->dh[0].ndh > 0);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
FILE* fp_dhdl;
int natoms_global;
int natoms_x_compressed;
- SimulationGroups* groups; /* for compressed position writing */
+ const SimulationGroups* groups; /* for compressed position writing */
gmx_wallcycle_t wcycle;
rvec* f_global;
gmx::IMDOutputProvider* outputProvider;
gmx::IMDOutputProvider* outputProvider,
const gmx::MdModulesNotifier& mdModulesNotifier,
const t_inputrec* ir,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
const gmx_output_env_t* oenv,
gmx_wallcycle_t wcycle,
const gmx::StartingBehavior startingBehavior,
*/
ivec one_ivec = { 1, 1, 1 };
write_checkpoint(of->fn_cpt, of->bKeepAndNumCPT, fplog, cr,
- DOMAINDECOMP(cr) ? cr->dd->nc : one_ivec,
+ DOMAINDECOMP(cr) ? cr->dd->numCells : one_ivec,
DOMAINDECOMP(cr) ? cr->dd->nnodes : cr->nnodes, of->eIntegrator,
of->simulation_part, of->bExpanded, of->elamstats, step, t,
state_global, observablesHistory, *(of->mdModulesNotifier),
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::IMDOutputProvider* outputProvider,
const gmx::MdModulesNotifier& mdModulesNotifier,
const t_inputrec* ir,
- gmx_mtop_t* mtop,
+ const gmx_mtop_t* mtop,
const gmx_output_env_t* oenv,
gmx_wallcycle_t wcycle,
gmx::StartingBehavior startingBehavior,
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* remove overlapping lipids and water from the membrane box*/
/*mark molecules to be removed*/
snew(pbc, 1);
- set_pbc(pbc, inputrec->ePBC, state->box);
+ set_pbc(pbc, inputrec->pbcType, state->box);
snew(rm_p, 1);
lip_rm = gen_rm_list(rm_p, ins_at, rest_at, pbc, mtop, state->x.rvec_array(), mem_p,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
bdens0 = (*gr0)[d];
}
/* Check for a DD cell not at a higher edge */
- if (dd != nullptr && gr1 != nullptr && dd->ci[d] < dd->nc[d] - 1)
+ if (dd != nullptr && gr1 != nullptr && dd->ci[d] < dd->numCells[d] - 1)
{
grid_x1[d] = (*gr1)[d];
bdens1 = (*gr1)[d];
grid->cell_offset[i] = izones_x0[i];
size = izones_size[i];
- bDD = (dd != nullptr) && (dd->nc[i] > 1);
+ bDD = (dd != nullptr) && (dd->numCells[i] > 1);
if (!bDD)
{
bDDRect = FALSE;
snew(grid, 1);
- grid->npbcdim = ePBC2npbcdim(fr->ePBC);
+ grid->npbcdim = numPbcDimensions(fr->pbcType);
- if (fr->ePBC == epbcXY && fr->nwall == 2)
+ if (fr->pbcType == PbcType::XY && fr->nwall == 2)
{
grid->nboundeddim = 3;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
if (bExcl)
{
- ndtot_c += molb.nmol * (molt->excls.nra - molt->atoms.nr) / 2.;
+ ndtot_c += molb.nmol * (molt->excls.numElements() - molt->atoms.nr) / 2.;
}
}
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "qm_gamess.h"
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <cmath>
-
-#include "gromacs/fileio/confio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/gmxlib/nrnb.h"
-#include "gromacs/math/units.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/qmmm.h"
-#include "gromacs/mdtypes/commrec.h"
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-// When not built in a configuration with QMMM support, much of this
-// code is unreachable by design. Tell clang not to warn about it.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-/* QMMM sub routines */
-/* mopac interface routines */
-
-
-static void F77_FUNC(inigms, IMIGMS)();
-
-static void F77_FUNC(grads, GRADS)(const int* nrqmat,
- real* qmcrd,
- const int* nrmmat,
- const real* mmchrg,
- real* mmcrd,
- real* qmgrad,
- real* mmgrad,
- real* energy);
-
-#if !GMX_QMMM_GAMESS
-// Stub definitions to make compilation succeed when not configured
-// for GAMESS support. In that case, the module gives a fatal error
-// when the initialization function is called, so there is no need to
-// issue fatal errors here, because that introduces problems with
-// tools suggesting and prohibiting noreturn attributes.
-
-void F77_FUNC(inigms, IMIGMS)(){};
-// NOLINTNEXTLINE(readability-named-parameter)
-void F77_FUNC(grads, GRADS)(const int*, real*, const int*, const real*, real*, real*, real*, real*){};
-#endif
-
-void init_gamess(const t_commrec* cr, t_QMrec* qm, t_MMrec* mm)
-{
- /* it works hopelessly complicated :-)
- * first a file is written. Then the standard gamess input/output
- * routine is called (no system()!) to set up all fortran arrays.
- * this routine writes a punch file, like in a normal gamess run.
- * via this punch file the other games routines, needed for gradient
- * and energy evaluations are called. This setup works fine for
- * dynamics simulations. 7-6-2002 (London)
- */
- int i, j;
- FILE* out;
- char periodic_system[37][3] = { "XX", "H ", "He", "Li", "Be", "B ", "C ", "N ", "O ", "F ",
- "Ne", "Na", "Mg", "Al", "Si", "P ", "S ", "Cl", "Ar", "K ",
- "Ca", "Sc", "Ti", "V ", "Cr", "Mn", "Fe", "Co", "Ni", "Cu",
- "Zn", "Ga", "Ge", "As", "Se", "Br", "Kr" };
- if (!GMX_QMMM_GAMESS)
- {
- gmx_fatal(FARGS,
- "Cannot call GAMESS unless linked against it. Use cmake "
- "-DGMX_QMMM_PROGRAM=GAMESS, and ensure that linking will work correctly.");
- }
-
- if (PAR(cr))
- {
-
- if (MASTER(cr))
- {
- out = fopen("FOR009", "w");
- /* of these options I am not completely sure.... the overall
- * preformance on more than 4 cpu's is rather poor at the moment.
- */
- fprintf(out, "memory 48000000\nPARALLEL IOMODE SCREENED\n");
- fprintf(out, "ELEC %d\nMULT %d\nSUPER ON\nNOSYM\nGEOMETRY ANGSTROM\n", qm->nelectrons,
- qm->multiplicity);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
-#ifdef DOUBLE
- fprintf(out, "%10.7lf %10.7lf %10.7lf %5.3lf %2s\n", i / 2., i / 3., i / 4.,
- qm->atomicnumberQM[i] * 1.0, periodic_system[qm->atomicnumberQM[i]]);
-#else
- fprintf(out, "%10.7f %10.7f %10.7f %5.3f %2s\n", i / 2., i / 3., i / 4.,
- qm->atomicnumberQM[i] * 1.0, periodic_system[qm->atomicnumberQM[i]]);
-#endif
- }
- if (mm->nrMMatoms)
- {
- for (j = i; j < i + 2; j++)
- {
-#ifdef DOUBLE
- fprintf(out, "%10.7lf %10.7lf %10.7lf %5.3lf BQ\n", j / 5., j / 6., j / 7., 1.0);
-#else
- fprintf(out, "%10.7f %10.7f %10.7f %5.3f BQ\n", j / 5., j / 6., j / 7., 2.0);
-#endif
- }
- }
- fprintf(out, "END\nBASIS %s\nRUNTYPE GRADIENT\nSCFTYPE %s\n",
- eQMbasis_names[qm->QMbasis], eQMmethod_names[qm->QMmethod]); /* see enum.h */
- fclose(out);
- }
- gmx_barrier(cr);
- F77_FUNC(inigms, IMIGMS)();
- }
- else /* normal serial run */
-
- {
- out = fopen("FOR009", "w");
- /* of these options I am not completely sure.... the overall
- * preformance on more than 4 cpu's is rather poor at the moment.
- */
- fprintf(out, "ELEC %d\nMULT %d\nSUPER ON\nNOSYM\nGEOMETRY ANGSTROM\n", qm->nelectrons,
- qm->multiplicity);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
-#ifdef DOUBLE
- fprintf(out, "%10.7lf %10.7lf %10.7lf %5.3lf %2s\n", i / 2., i / 3., i / 4.,
- qm->atomicnumberQM[i] * 1.0, periodic_system[qm->atomicnumberQM[i]]);
-#else
- fprintf(out, "%10.7f %10.7f %10.7f %5.3f %2s\n", i / 2., i / 3., i / 4.,
- qm->atomicnumberQM[i] * 1.0, periodic_system[qm->atomicnumberQM[i]]);
-#endif
- }
- if (mm->nrMMatoms)
- {
- for (j = i; j < i + 2; j++)
- {
-#ifdef DOUBLE
- fprintf(out, "%10.7lf %10.7lf %10.7lf %5.3lf BQ\n", j / 5., j / 6., j / 7., 1.0);
-#else
- fprintf(out, "%10.7f %10.7f %10.7f %5.3f BQ\n", j / 5., j / 6., j / 7., 2.0);
-#endif
- }
- }
- fprintf(out, "END\nBASIS %s\nRUNTYPE GRADIENT\nSCFTYPE %s\n", eQMbasis_names[qm->QMbasis],
- eQMmethod_names[qm->QMmethod]); /* see enum.h */
- F77_FUNC(inigms, IMIGMS)();
- }
-}
-
-real call_gamess(const t_QMrec* qm, const t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* do the actual QMMM calculation using GAMESS-UK. In this
- * implementation (3-2001) a system call is made to the GAMESS-UK
- * binary. Now we are working to get the electron integral, SCF, and
- * gradient routines linked directly
- */
- int i, j;
- real QMener = 0.0, *qmgrad, *mmgrad, *mmcrd, *qmcrd, energy = 0;
-
- snew(qmcrd, 3 * (qm->nrQMatoms));
- snew(mmcrd, 3 * (mm->nrMMatoms));
- snew(qmgrad, 3 * (qm->nrQMatoms));
- snew(mmgrad, 3 * (mm->nrMMatoms));
-
- /* copy the data from qr into the arrays that are going to be used
- * in the fortran routines of gamess
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- qmcrd[DIM * i + j] = 1 / BOHR2NM * qm->xQM[i][j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- mmcrd[DIM * i + j] = 1 / BOHR2NM * mm->xMM[i][j];
- }
- }
- for (i = 0; i < 3 * qm->nrQMatoms; i += 3)
- {
- fprintf(stderr, "%8.5f, %8.5f, %8.5f\n", qmcrd[i], qmcrd[i + 1], qmcrd[i + 2]);
- }
-
- F77_FUNC(grads, GRADS)
- (&qm->nrQMatoms, qmcrd, &mm->nrMMatoms, mm->MMcharges, mmcrd, qmgrad, mmgrad, &energy);
-
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = HARTREE_BOHR2MD * qmgrad[3 * i + j];
- fshift[i][j] = HARTREE_BOHR2MD * qmgrad[3 * i + j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = HARTREE_BOHR2MD * mmgrad[3 * i + j];
- fshift[i][j] = HARTREE_BOHR2MD * mmgrad[3 * i + j];
- }
- }
- /* convert a.u to kJ/mol */
- QMener = energy * HARTREE2KJ * AVOGADRO;
- return (QMener);
-}
-
-#pragma GCC diagnostic pop
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "qm_gaussian.h"
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <cmath>
-
-#include "gromacs/fileio/confio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/gmxlib/nrnb.h"
-#include "gromacs/math/units.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/force.h"
-#include "gromacs/mdlib/forcerec.h"
-#include "gromacs/mdlib/qmmm.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/utility/cstringutil.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-// When not built in a configuration with QMMM support, much of this
-// code is unreachable by design. Tell clang not to warn about it.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-/* TODO: this should be made thread-safe */
-
-/* Gaussian interface routines */
-
-void init_gaussian(t_QMrec* qm)
-{
- ivec basissets[eQMbasisNR] = { { 0, 3, 0 }, { 0, 3, 0 }, /*added for double sto-3g entry in names.c*/
- { 5, 0, 0 }, { 5, 0, 1 }, { 5, 0, 11 }, { 5, 6, 0 },
- { 1, 6, 0 }, { 1, 6, 1 }, { 1, 6, 11 }, { 4, 6, 0 } };
- char* buf = nullptr;
- int i;
-
- if (!GMX_QMMM_GAUSSIAN)
- {
- gmx_fatal(FARGS,
- "Cannot call GAUSSIAN unless linked against it. Use cmake "
- "-DGMX_QMMM_PROGRAM=GAUSSIAN, and ensure that linking will work correctly.");
- }
-
- /* using the ivec above to convert the basis read form the mdp file
- * in a human readable format into some numbers for the gaussian
- * route. This is necessary as we are using non standard routes to
- * do SH.
- */
-
- /* per layer we make a new subdir for integral file, checkpoint
- * files and such. These dirs are stored in the QMrec for
- * convenience
- */
-
-
- if (!qm->nQMcpus) /* this we do only once per layer
- * as we call g01 externally
- */
-
- {
- for (i = 0; i < DIM; i++)
- {
- qm->SHbasis[i] = basissets[qm->QMbasis][i];
- }
-
- /* init gradually switching on of the SA */
- qm->SAstep = 0;
- /* we read the number of cpus and environment from the environment
- * if set.
- */
- buf = getenv("GMX_QM_GAUSSIAN_NCPUS");
- if (buf)
- {
- sscanf(buf, "%d", &qm->nQMcpus);
- }
- else
- {
- qm->nQMcpus = 1;
- }
- fprintf(stderr, "number of CPUs for gaussian = %d\n", qm->nQMcpus);
- buf = getenv("GMX_QM_GAUSSIAN_MEMORY");
- if (buf)
- {
- sscanf(buf, "%d", &qm->QMmem);
- }
- else
- {
- qm->QMmem = 50000000;
- }
- fprintf(stderr, "memory for gaussian = %d\n", qm->QMmem);
- buf = getenv("GMX_QM_ACCURACY");
- if (buf)
- {
- sscanf(buf, "%d", &qm->accuracy);
- }
- else
- {
- qm->accuracy = 8;
- }
- fprintf(stderr, "accuracy in l510 = %d\n", qm->accuracy);
-
- buf = getenv("GMX_QM_CPMCSCF");
- if (buf)
- {
- sscanf(buf, "%d", &i);
- qm->cpmcscf = (i != 0);
- }
- else
- {
- qm->cpmcscf = FALSE;
- }
- if (qm->cpmcscf)
- {
- fprintf(stderr, "using cp-mcscf in l1003\n");
- }
- else
- {
- fprintf(stderr, "NOT using cp-mcscf in l1003\n");
- }
- buf = getenv("GMX_QM_SA_STEP");
- if (buf)
- {
- sscanf(buf, "%d", &qm->SAstep);
- }
- else
- {
- /* init gradually switching on of the SA */
- qm->SAstep = 0;
- }
- /* we read the number of cpus and environment from the environment
- * if set.
- */
- fprintf(stderr, "Level of SA at start = %d\n", qm->SAstep);
- /* gaussian settings on the system */
- buf = getenv("GMX_QM_GAUSS_DIR");
-
- if (buf)
- {
- qm->gauss_dir = gmx_strdup(buf);
- }
- else
- {
- gmx_fatal(FARGS, "no $GMX_QM_GAUSS_DIR, check gaussian manual\n");
- }
-
- buf = getenv("GMX_QM_GAUSS_EXE");
- if (buf)
- {
- qm->gauss_exe = gmx_strdup(buf);
- }
- else
- {
- gmx_fatal(FARGS, "no $GMX_QM_GAUSS_EXE set, check gaussian manual\n");
- }
- buf = getenv("GMX_QM_MODIFIED_LINKS_DIR");
- if (buf)
- {
- qm->devel_dir = gmx_strdup(buf);
- }
- else
- {
- gmx_fatal(FARGS,
- "no $GMX_QM_MODIFIED_LINKS_DIR, this is were the modified links reside.\n");
- }
-
- /* if(fr->bRF){*/
- /* reactionfield, file is needed using gaussian */
- /* rffile=fopen("rf.dat","w");*/
- /* fprintf(rffile,"%f %f\n",fr->epsilon_r,fr->rcoulomb/BOHR2NM);*/
- /* fclose(rffile);*/
- /* }*/
- }
- fprintf(stderr, "gaussian initialised...\n");
-}
-
-
-static void write_gaussian_SH_input(int step, gmx_bool swap, const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
-{
- int i;
- gmx_bool bSA;
- FILE* out;
- t_QMMMrec* QMMMrec;
- QMMMrec = fr->qr;
- bSA = (qm->SAstep > 0);
-
- out = fopen("input.com", "w");
- /* write the route */
- fprintf(out, "%s", "%scr=input\n");
- fprintf(out, "%s", "%rwf=input\n");
- fprintf(out, "%s", "%int=input\n");
- fprintf(out, "%s", "%d2e=input\n");
- /* if(step)
- * fprintf(out,"%s","%nosave\n");
- */
- fprintf(out, "%s", "%chk=input\n");
- fprintf(out, "%s%d\n", "%mem=", qm->QMmem);
- fprintf(out, "%s%3d\n", "%nprocshare=", qm->nQMcpus);
-
- /* use the versions of
- * l301 that computes the interaction between MM and QM atoms.
- * l510 that can punch the CI coefficients
- * l701 that can do gradients on MM atoms
- */
-
- /* local version */
- fprintf(out, "%s%s%s", "%subst l510 ", qm->devel_dir, "/l510\n");
- fprintf(out, "%s%s%s", "%subst l301 ", qm->devel_dir, "/l301\n");
- fprintf(out, "%s%s%s", "%subst l701 ", qm->devel_dir, "/l701\n");
-
- fprintf(out, "%s%s%s", "%subst l1003 ", qm->devel_dir, "/l1003\n");
- fprintf(out, "%s%s%s", "%subst l9999 ", qm->devel_dir, "/l9999\n");
- /* print the nonstandard route
- */
- fprintf(out, "%s", "#P nonstd\n 1/18=10,20=1,38=1/1;\n");
- fprintf(out, "%s", " 2/9=110,15=1,17=6,18=5,40=1/2;\n");
- if (mm->nrMMatoms)
- {
- fprintf(out, " 3/5=%d,6=%d,7=%d,25=1,32=1,43=1,94=-2/1,2,3;\n", qm->SHbasis[0],
- qm->SHbasis[1], qm->SHbasis[2]); /*basisset stuff */
- }
- else
- {
- fprintf(out, " 3/5=%d,6=%d,7=%d,25=1,32=1,43=0,94=-2/1,2,3;\n", qm->SHbasis[0],
- qm->SHbasis[1], qm->SHbasis[2]); /*basisset stuff */
- }
- /* development */
- if (step + 1) /* fetch initial guess from check point file */
- { /* hack, to alyays read from chk file!!!!! */
- fprintf(out, "%s%d,%s%d%s", " 4/5=1,7=6,17=", qm->CASelectrons, "18=", qm->CASorbitals,
- "/1,5;\n");
- }
- else /* generate the first checkpoint file */
- {
- fprintf(out, "%s%d,%s%d%s", " 4/5=0,7=6,17=", qm->CASelectrons, "18=", qm->CASorbitals,
- "/1,5;\n");
- }
- /* the rest of the input depends on where the system is on the PES
- */
- if (swap && bSA) /* make a slide to the other surface */
- {
- if (qm->CASorbitals > 6) /* use direct and no full diag */
- {
- fprintf(out, " 5/5=2,16=-2,17=10000000,28=2,32=2,38=6,97=100/10;\n");
- }
- else
- {
- if (qm->cpmcscf)
- {
- fprintf(out, " 5/5=2,6=%d,17=31000200,28=2,32=2,38=6,97=100/10;\n", qm->accuracy);
- if (mm->nrMMatoms > 0)
- {
- fprintf(out, " 7/7=1,16=-2,30=1/1;\n");
- }
- fprintf(out, " 11/31=1,42=1,45=1/1;\n");
- fprintf(out, " 10/6=1,10=700006,28=2,29=1,31=1,97=100/3;\n");
- fprintf(out, " 7/30=1/16;\n 99/10=4/99;\n");
- }
- else
- {
- fprintf(out, " 5/5=2,6=%d,17=11000000,28=2,32=2,38=6,97=100/10;\n", qm->accuracy);
- fprintf(out, " 7/7=1,16=-2,30=1/1,2,3,16;\n 99/10=4/99;\n");
- }
- }
- }
- else if (bSA) /* do a "state-averaged" CAS calculation */
- {
- if (qm->CASorbitals > 6) /* no full diag */
- {
- fprintf(out, " 5/5=2,16=-2,17=10000000,28=2,32=2,38=6/10;\n");
- }
- else
- {
- if (qm->cpmcscf)
- {
- fprintf(out, " 5/5=2,6=%d,17=31000200,28=2,32=2,38=6/10;\n", qm->accuracy);
- if (mm->nrMMatoms > 0)
- {
- fprintf(out, " 7/7=1,16=-2,30=1/1;\n");
- }
- fprintf(out, " 11/31=1,42=1,45=1/1;\n");
- fprintf(out, " 10/6=1,10=700006,28=2,29=1,31=1/3;\n");
- fprintf(out, " 7/30=1/16;\n 99/10=4/99;\n");
- }
- else
- {
- fprintf(out, " 5/5=2,6=%d,17=11000000,28=2,32=2,38=6/10;\n", qm->accuracy);
- fprintf(out, " 7/7=1,16=-2,30=1/1,2,3,16;\n 99/10=4/99;\n");
- }
- }
- }
- else if (swap) /* do a "swapped" CAS calculation */
- {
- if (qm->CASorbitals > 6)
- {
- fprintf(out, " 5/5=2,16=-2,17=0,28=2,32=2,38=6,97=100/10;\n");
- }
- else
- {
- fprintf(out, " 5/5=2,6=%d,17=1000000,28=2,32=2,38=6,97=100/10;\n", qm->accuracy);
- }
- fprintf(out, " 7/7=1,16=-2,30=1/1,2,3,16;\n 99/10=4/99;\n");
- }
- else /* do a "normal" CAS calculation */
- {
- if (qm->CASorbitals > 6)
- {
- fprintf(out, " 5/5=2,16=-2,17=0,28=2,32=2,38=6/10;\n");
- }
- else
- {
- fprintf(out, " 5/5=2,6=%d,17=1000000,28=2,32=2,38=6/10;\n", qm->accuracy);
- }
- fprintf(out, " 7/7=1,16=-2,30=1/1,2,3,16;\n 99/10=4/99;\n");
- }
- fprintf(out, "\ninput-file generated by gromacs\n\n");
- fprintf(out, "%2d%2d\n", qm->QMcharge, qm->multiplicity);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- fprintf(out, "%3d %10.7f %10.7f %10.7f\n", qm->atomicnumberQM[i],
- qm->xQM[i][XX] / BOHR2NM, qm->xQM[i][YY] / BOHR2NM, qm->xQM[i][ZZ] / BOHR2NM);
- }
- /* MM point charge data */
- if (QMMMrec->QMMMscheme != eQMMMschemeoniom && mm->nrMMatoms)
- {
- fprintf(out, "\n");
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- fprintf(out, "%10.7f %10.7f %10.7f %8.4f\n", mm->xMM[i][XX] / BOHR2NM,
- mm->xMM[i][YY] / BOHR2NM, mm->xMM[i][ZZ] / BOHR2NM, mm->MMcharges[i]);
- }
- }
- if (bSA) /* put the SA coefficients at the end of the file */
- {
- fprintf(out, "\n%10.8f %10.8f\n", qm->SAstep * 0.5 / qm->SAsteps, 1 - qm->SAstep * 0.5 / qm->SAsteps);
- fprintf(stderr, "State Averaging level = %d/%d\n", qm->SAstep, qm->SAsteps);
- }
- fprintf(out, "\n");
- fclose(out);
-} /* write_gaussian_SH_input */
-
-static void write_gaussian_input(int step, const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
-{
- int i;
- t_QMMMrec* QMMMrec;
- FILE* out;
-
- QMMMrec = fr->qr;
- out = fopen("input.com", "w");
- /* write the route */
-
- if (qm->QMmethod >= eQMmethodRHF)
- {
- fprintf(out, "%s", "%chk=input\n");
- }
- else
- {
- fprintf(out, "%s", "%chk=se\n");
- }
- if (qm->nQMcpus > 1)
- {
- fprintf(out, "%s%3d\n", "%nprocshare=", qm->nQMcpus);
- }
- fprintf(out, "%s%d\n", "%mem=", qm->QMmem);
- fprintf(out, "%s%s%s", "%subst l701 ", qm->devel_dir, "/l701\n");
- fprintf(out, "%s%s%s", "%subst l301 ", qm->devel_dir, "/l301\n");
- fprintf(out, "%s%s%s", "%subst l9999 ", qm->devel_dir, "/l9999\n");
- if (step)
- {
- fprintf(out, "%s", "#T ");
- }
- else
- {
- fprintf(out, "%s", "#P ");
- }
- if (qm->QMmethod == eQMmethodB3LYPLAN)
- {
- fprintf(out, " %s", "B3LYP/GEN Pseudo=Read");
- }
- else
- {
- fprintf(out, " %s", eQMmethod_names[qm->QMmethod]);
-
- if (qm->QMmethod >= eQMmethodRHF)
- {
- if (qm->QMmethod == eQMmethodCASSCF)
- {
- /* in case of cas, how many electrons and orbitals do we need?
- */
- fprintf(out, "(%d,%d)", qm->CASelectrons, qm->CASorbitals);
- }
- fprintf(out, "/%s", eQMbasis_names[qm->QMbasis]);
- }
- }
- if (QMMMrec->QMMMscheme == eQMMMschemenormal && mm->nrMMatoms)
- {
- fprintf(out, " %s", "Charge ");
- }
- if (step || qm->QMmethod == eQMmethodCASSCF)
- {
- /* fetch guess from checkpoint file, always for CASSCF */
- fprintf(out, "%s", " guess=read");
- }
- fprintf(out, "\nNosymm units=bohr\n");
-
- fprintf(out, "FORCE Punch=(Derivatives) ");
- fprintf(out, "iop(3/33=1)\n\n");
- fprintf(out, "input-file generated by gromacs\n\n");
- fprintf(out, "%2d%2d\n", qm->QMcharge, qm->multiplicity);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- fprintf(out, "%3d %10.7f %10.7f %10.7f\n", qm->atomicnumberQM[i],
- qm->xQM[i][XX] / BOHR2NM, qm->xQM[i][YY] / BOHR2NM, qm->xQM[i][ZZ] / BOHR2NM);
- }
-
- /* Pseudo Potential and ECP are included here if selected (MEthod suffix LAN) */
- if (qm->QMmethod == eQMmethodB3LYPLAN)
- {
- fprintf(out, "\n");
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- if (qm->atomicnumberQM[i] < 21)
- {
- fprintf(out, "%d ", i + 1);
- }
- }
- fprintf(out, "\n%s\n****\n", eQMbasis_names[qm->QMbasis]);
-
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- if (qm->atomicnumberQM[i] > 21)
- {
- fprintf(out, "%d ", i + 1);
- }
- }
- fprintf(out, "\n%s\n****\n\n", "lanl2dz");
-
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- if (qm->atomicnumberQM[i] > 21)
- {
- fprintf(out, "%d ", i + 1);
- }
- }
- fprintf(out, "\n%s\n", "lanl2dz");
- }
-
-
- /* MM point charge data */
- if (QMMMrec->QMMMscheme != eQMMMschemeoniom && mm->nrMMatoms)
- {
- fprintf(stderr, "nr mm atoms in gaussian.c = %d\n", mm->nrMMatoms);
- fprintf(out, "\n");
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- fprintf(out, "%10.7f %10.7f %10.7f %8.4f\n", mm->xMM[i][XX] / BOHR2NM,
- mm->xMM[i][YY] / BOHR2NM, mm->xMM[i][ZZ] / BOHR2NM, mm->MMcharges[i]);
- }
- }
- fprintf(out, "\n");
-
-
- fclose(out);
-
-} /* write_gaussian_input */
-
-static real read_gaussian_output(rvec QMgrad[], rvec MMgrad[], t_QMrec* qm, t_MMrec* mm)
-{
- int i;
- char buf[300];
- real QMener;
- FILE* in;
-
- in = fopen("fort.7", "r");
-
- /* (There was additional content in the file in case
- * of QM optimizations / transition state search,
- * which was removed.
- */
- /* the next line is the energy and in the case of CAS, the energy
- * difference between the two states.
- */
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-
-#if GMX_DOUBLE
- sscanf(buf, "%lf\n", &QMener);
-#else
- sscanf(buf, "%f\n", &QMener);
-#endif
- /* next lines contain the gradients of the QM atoms */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf %lf %lf\n", &QMgrad[i][XX], &QMgrad[i][YY], &QMgrad[i][ZZ]);
-#else
- sscanf(buf, "%f %f %f\n", &QMgrad[i][XX], &QMgrad[i][YY], &QMgrad[i][ZZ]);
-#endif
- }
- /* the next lines are the gradients of the MM atoms */
- if (qm->QMmethod >= eQMmethodRHF)
- {
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf %lf %lf\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#else
- sscanf(buf, "%f %f %f\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#endif
- }
- }
- fclose(in);
- return (QMener);
-}
-
-static real read_gaussian_SH_output(rvec QMgrad[], rvec MMgrad[], int step, t_QMrec* qm, t_MMrec* mm)
-{
- int i;
- char buf[300];
- real QMener, DeltaE;
- FILE* in;
-
- in = fopen("fort.7", "r");
- /* first line is the energy and in the case of CAS, the energy
- * difference between the two states.
- */
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-
-#if GMX_DOUBLE
- sscanf(buf, "%lf %lf\n", &QMener, &DeltaE);
-#else
- sscanf(buf, "%f %f\n", &QMener, &DeltaE);
-#endif
-
- /* switch on/off the State Averaging */
-
- if (DeltaE > qm->SAoff)
- {
- if (qm->SAstep > 0)
- {
- qm->SAstep--;
- }
- }
- else if (DeltaE < qm->SAon || (qm->SAstep > 0))
- {
- if (qm->SAstep < qm->SAsteps)
- {
- qm->SAstep++;
- }
- }
-
- /* for debugging: */
- fprintf(stderr, "Gap = %5f,SA = %3d\n", DeltaE, static_cast<int>(qm->SAstep > 0));
- /* next lines contain the gradients of the QM atoms */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-
-#if GMX_DOUBLE
- sscanf(buf, "%lf %lf %lf\n", &QMgrad[i][XX], &QMgrad[i][YY], &QMgrad[i][ZZ]);
-#else
- sscanf(buf, "%f %f %f\n", &QMgrad[i][XX], &QMgrad[i][YY], &QMgrad[i][ZZ]);
-#endif
- }
- /* the next lines, are the gradients of the MM atoms */
-
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf %lf %lf\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#else
- sscanf(buf, "%f %f %f\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#endif
- }
-
- /* the next line contains the two CI eigenvector elements */
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
- if (!step)
- {
- sscanf(buf, "%d", &qm->CIdim);
- snew(qm->CIvec1, qm->CIdim);
- snew(qm->CIvec1old, qm->CIdim);
- snew(qm->CIvec2, qm->CIdim);
- snew(qm->CIvec2old, qm->CIdim);
- }
- else
- {
- /* before reading in the new current CI vectors, copy the current
- * CI vector into the old one.
- */
- for (i = 0; i < qm->CIdim; i++)
- {
- qm->CIvec1old[i] = qm->CIvec1[i];
- qm->CIvec2old[i] = qm->CIvec2[i];
- }
- }
- /* first vector */
- for (i = 0; i < qm->CIdim; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf\n", &qm->CIvec1[i]);
-#else
- sscanf(buf, "%f\n", &qm->CIvec1[i]);
-#endif
- }
- /* second vector */
- for (i = 0; i < qm->CIdim; i++)
- {
- if (nullptr == fgets(buf, 300, in))
- {
- gmx_fatal(FARGS, "Error reading Gaussian output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf\n", &qm->CIvec2[i]);
-#else
- sscanf(buf, "%f\n", &qm->CIvec2[i]);
-#endif
- }
- fclose(in);
- return (QMener);
-}
-
-static real inproduct(const real* a, const real* b, int n)
-{
- int i;
- real dot = 0.0;
-
- /* computes the inner product between two vectors (a.b), both of
- * which have length n.
- */
- for (i = 0; i < n; i++)
- {
- dot += a[i] * b[i];
- }
- return (dot);
-}
-
-static int hop(int step, t_QMrec* qm)
-{
- int swap = 0;
- real d11 = 0.0, d12 = 0.0, d21 = 0.0, d22 = 0.0;
-
- /* calculates the inproduct between the current Ci vector and the
- * previous CI vector. A diabatic hop will be made if d12 and d21
- * are much bigger than d11 and d22. In that case hop returns true,
- * otherwise it returns false.
- */
- if (step) /* only go on if more than one step has been done */
- {
- d11 = inproduct(qm->CIvec1, qm->CIvec1old, qm->CIdim);
- d12 = inproduct(qm->CIvec1, qm->CIvec2old, qm->CIdim);
- d21 = inproduct(qm->CIvec2, qm->CIvec1old, qm->CIdim);
- d22 = inproduct(qm->CIvec2, qm->CIvec2old, qm->CIdim);
- }
- fprintf(stderr, "-------------------\n");
- fprintf(stderr, "d11 = %13.8f\n", d11);
- fprintf(stderr, "d12 = %13.8f\n", d12);
- fprintf(stderr, "d21 = %13.8f\n", d21);
- fprintf(stderr, "d22 = %13.8f\n", d22);
- fprintf(stderr, "-------------------\n");
-
- if ((fabs(d12) > 0.5) && (fabs(d21) > 0.5))
- {
- swap = 1;
- }
-
- return (swap);
-}
-
-static void do_gaussian(int step, char* exe)
-{
- char buf[STRLEN];
-
- /* make the call to the gaussian binary through system()
- * The location of the binary will be picked up from the
- * environment using getenv().
- */
- if (step) /* hack to prevent long inputfiles */
- {
- sprintf(buf, "%s < %s > %s", exe, "input.com", "input.log");
- }
- else
- {
- sprintf(buf, "%s < %s > %s", exe, "input.com", "input.log");
- }
- fprintf(stderr, "Calling '%s'\n", buf);
- if (system(buf) != 0)
- {
- gmx_fatal(FARGS, "Call to '%s' failed\n", buf);
- }
-}
-
-real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* normal gaussian jobs */
- static int step = 0;
- int i, j;
- real QMener = 0.0;
- rvec * QMgrad, *MMgrad;
- char* exe;
-
- snew(exe, 30);
- sprintf(exe, "%s/%s", qm->gauss_dir, qm->gauss_exe);
- snew(QMgrad, qm->nrQMatoms);
- snew(MMgrad, mm->nrMMatoms);
-
- write_gaussian_input(step, fr, qm, mm);
- do_gaussian(step, exe);
- QMener = read_gaussian_output(QMgrad, MMgrad, qm, mm);
- /* put the QMMM forces in the force array and to the fshift
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- fshift[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- fshift[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- }
- }
- QMener = QMener * HARTREE2KJ * AVOGADRO;
- step++;
- free(exe);
- return (QMener);
-
-} /* call_gaussian */
-
-real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* a gaussian call routine intended for doing diabatic surface
- * "sliding". See the manual for the theoretical background of this
- * TSH method.
- */
- static int step = 0;
- int state, i, j;
- real QMener = 0.0;
- static gmx_bool swapped = FALSE; /* handle for identifying the current PES */
- gmx_bool swap = FALSE; /* the actual swap */
- rvec * QMgrad, *MMgrad;
- char* buf;
- char* exe;
-
- snew(exe, 30);
- sprintf(exe, "%s/%s", qm->gauss_dir, qm->gauss_exe);
- /* hack to do ground state simulations */
- if (!step)
- {
- snew(buf, 20);
- buf = getenv("GMX_QM_GROUND_STATE");
- if (buf)
- {
- sscanf(buf, "%d", &state);
- }
- else
- {
- state = 2;
- }
- if (state == 1)
- {
- swapped = TRUE;
- }
- }
- /* end of hack */
-
-
- /* copy the QMMMrec pointer */
- snew(QMgrad, qm->nrQMatoms);
- snew(MMgrad, mm->nrMMatoms);
- /* at step 0 there should be no SA */
- /* if(!step)
- * qr->bSA=FALSE;*/
- /* temporray set to step + 1, since there is a chk start */
- write_gaussian_SH_input(step, swapped, fr, qm, mm);
-
- do_gaussian(step, exe);
- QMener = read_gaussian_SH_output(QMgrad, MMgrad, step, qm, mm);
-
- /* check for a surface hop. Only possible if we were already state
- * averaging.
- */
- if (qm->SAstep > 0)
- {
- if (!swapped)
- {
- swap = ((step != 0) && (hop(step, qm) != 0));
- swapped = swap;
- }
- else /* already on the other surface, so check if we go back */
- {
- swap = ((step != 0) && (hop(step, qm) != 0));
- swapped = !swap; /* so swapped shoud be false again */
- }
- if (swap) /* change surface, so do another call */
- {
- write_gaussian_SH_input(step, swapped, fr, qm, mm);
- do_gaussian(step, exe);
- QMener = read_gaussian_SH_output(QMgrad, MMgrad, step, qm, mm);
- }
- }
- /* add the QMMM forces to the gmx force array and fshift
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- fshift[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- fshift[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- }
- }
- QMener = QMener * HARTREE2KJ * AVOGADRO;
- fprintf(stderr, "step %5d, SA = %5d, swap = %5d\n", step, static_cast<int>(qm->SAstep > 0),
- static_cast<int>(swapped));
- step++;
- free(exe);
- return (QMener);
-
-} /* call_gaussian_SH */
-
-#pragma GCC diagnostic pop
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "qm_mopac.h"
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <cmath>
-
-#include "gromacs/fileio/confio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/gmxlib/nrnb.h"
-#include "gromacs/math/units.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/qmmm.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-
-// When not built in a configuration with QMMM support, much of this
-// code is unreachable by design. Tell clang not to warn about it.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-#if GMX_QMMM_MOPAC
-/* mopac interface routines */
-void F77_FUNC(domldt, DOMLDT)(int* nrqmat, int labels[], char keywords[]);
-
-void F77_FUNC(domop, DOMOP)(int* nrqmat,
- double qmcrd[],
- int* nrmmat,
- double mmchrg[],
- double mmcrd[],
- double qmgrad[],
- double mmgrad[],
- double* energy,
- double qmcharges[]);
-
-#else /* GMX_QMMM_MOPAC */
-// Stub definitions to make compilation succeed when not configured
-// for MOPAC support. In that case, the module gives a fatal error
-// when the initialization function is called, so there is no need to
-// issue fatal errors here, because that introduces problems with
-// tools suggesting and prohibiting noreturn attributes.
-
-static void F77_FUNC(domldt, DOMLDT)(int* /*unused*/, int /*unused*/[], char /*unused*/[]) {}
-
-static void F77_FUNC(domop, DOMOP)(int* /*unused*/,
- double /*unused*/[],
- int* /*unused*/,
- double /*unused*/[],
- double /*unused*/[],
- double /*unused*/[],
- double /*unused*/[],
- double* /*unused*/,
- double /*unused*/[])
-{
-}
-
-#endif
-
-
-void init_mopac(t_QMrec* qm)
-{
- /* initializes the mopac routines ans sets up the semiempirical
- * computation by calling moldat(). The inline mopac routines can
- * only perform gradient operations. If one would like to optimize a
- * structure or find a transition state at PM3 level, gaussian is
- * used instead.
- */
- char* keywords;
-
- if (!GMX_QMMM_MOPAC)
- {
- gmx_fatal(FARGS,
- "Cannot call MOPAC unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=MOPAC, "
- "and ensure that linking will work correctly.");
- }
-
- snew(keywords, 240);
-
- if (!qm->bSH) /* if rerun then grad should not be done! */
- {
- sprintf(keywords, "PRECISE GEO-OK CHARGE=%d GRAD MMOK ANALYT %s\n", qm->QMcharge,
- eQMmethod_names[qm->QMmethod]);
- }
- else
- {
- sprintf(keywords, "PRECISE GEO-OK CHARGE=%d SINGLET GRAD %s C.I.=(%d,%d) root=2 MECI \n",
- qm->QMcharge, eQMmethod_names[qm->QMmethod], qm->CASorbitals, qm->CASelectrons / 2);
- }
- F77_FUNC(domldt, DOMLDT)(&qm->nrQMatoms, qm->atomicnumberQM, keywords);
- fprintf(stderr, "keywords are: %s\n", keywords);
- free(keywords);
-
-} /* init_mopac */
-
-real call_mopac(t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* do the actual QMMM calculation using directly linked mopac subroutines
- */
- double /* always double as the MOPAC routines are always compiled in
- double precission! */
- *qmcrd = nullptr,
- *qmchrg = nullptr, *mmcrd = nullptr, *mmchrg = nullptr, *qmgrad, *mmgrad = nullptr,
- energy = 0;
- int i, j;
- real QMener = 0.0;
- snew(qmcrd, 3 * (qm->nrQMatoms));
- snew(qmgrad, 3 * (qm->nrQMatoms));
- /* copy the data from qr into the arrays that are going to be used
- * in the fortran routines of MOPAC
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- qmcrd[3 * i + j] = static_cast<double>(qm->xQM[i][j]) * 10;
- }
- }
- if (mm->nrMMatoms)
- {
- /* later we will add the point charges here. There are some
- * conceptual problems with semi-empirical QM in combination with
- * point charges that we need to solve first....
- */
- gmx_fatal(FARGS,
- "At present only ONIOM is allowed in combination"
- " with MOPAC QM subroutines\n");
- }
- else
- {
- /* now compute the energy and the gradients.
- */
-
- snew(qmchrg, qm->nrQMatoms);
- F77_FUNC(domop, DOMOP)
- (&qm->nrQMatoms, qmcrd, &mm->nrMMatoms, mmchrg, mmcrd, qmgrad, mmgrad, &energy, qmchrg);
- /* add the gradients to the f[] array, and also to the fshift[].
- * the mopac gradients are in kCal/angstrom.
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = static_cast<real>(10) * CAL2JOULE * qmgrad[3 * i + j];
- fshift[i][j] = static_cast<real>(10) * CAL2JOULE * qmgrad[3 * i + j];
- }
- }
- QMener = static_cast<real> CAL2JOULE * energy;
- /* do we do something with the mulliken charges?? */
-
- free(qmchrg);
- }
- free(qmgrad);
- free(qmcrd);
- return (QMener);
-}
-
-real call_mopac_SH(t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* do the actual SH QMMM calculation using directly linked mopac
- subroutines */
-
- double /* always double as the MOPAC routines are always compiled in
- double precission! */
- *qmcrd = nullptr,
- *qmchrg = nullptr, *mmcrd = nullptr, *mmchrg = nullptr, *qmgrad, *mmgrad = nullptr,
- energy = 0;
- int i, j;
- real QMener = 0.0;
-
- snew(qmcrd, 3 * (qm->nrQMatoms));
- snew(qmgrad, 3 * (qm->nrQMatoms));
- /* copy the data from qr into the arrays that are going to be used
- * in the fortran routines of MOPAC
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- qmcrd[3 * i + j] = static_cast<double>(qm->xQM[i][j]) * 10;
- }
- }
- if (mm->nrMMatoms)
- {
- /* later we will add the point charges here. There are some
- * conceptual problems with semi-empirical QM in combination with
- * point charges that we need to solve first....
- */
- gmx_fatal(FARGS, "At present only ONIOM is allowed in combination with MOPAC\n");
- }
- else
- {
- /* now compute the energy and the gradients.
- */
- snew(qmchrg, qm->nrQMatoms);
-
- F77_FUNC(domop, DOMOP)
- (&qm->nrQMatoms, qmcrd, &mm->nrMMatoms, mmchrg, mmcrd, qmgrad, mmgrad, &energy, qmchrg);
- /* add the gradients to the f[] array, and also to the fshift[].
- * the mopac gradients are in kCal/angstrom.
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = static_cast<real>(10) * CAL2JOULE * qmgrad[3 * i + j];
- fshift[i][j] = static_cast<real>(10) * CAL2JOULE * qmgrad[3 * i + j];
- }
- }
- QMener = static_cast<real> CAL2JOULE * energy;
- }
- free(qmgrad);
- free(qmcrd);
- return (QMener);
-} /* call_mopac_SH */
-
-#pragma GCC diagnostic pop
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "qm_orca.h"
-
-#include "config.h"
-
-#include <cmath>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include "gromacs/fileio/confio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/gmxlib/nrnb.h"
-#include "gromacs/math/units.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/qmmm.h"
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-// When not built in a configuration with QMMM support, much of this
-// code is unreachable by design. Tell clang not to warn about it.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-/* ORCA interface routines */
-
-void init_orca(t_QMrec* qm)
-{
- char* buf;
- snew(buf, 200);
-
- if (!GMX_QMMM_ORCA)
- {
- gmx_fatal(FARGS,
- "Cannot call ORCA unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=ORCA, "
- "and ensure that linking will work correctly.");
- }
-
- /* ORCA settings on the system */
- buf = getenv("GMX_QM_ORCA_BASENAME");
- if (buf)
- {
- snew(qm->orca_basename, 200);
- sscanf(buf, "%s", qm->orca_basename);
- }
- else
- {
- gmx_fatal(FARGS, "$GMX_QM_ORCA_BASENAME is not set\n");
- }
-
- /* ORCA directory on the system */
- snew(buf, 200);
- buf = getenv("GMX_ORCA_PATH");
-
- if (buf)
- {
- snew(qm->orca_dir, 200);
- sscanf(buf, "%s", qm->orca_dir);
- }
- else
- {
- gmx_fatal(FARGS, "$GMX_ORCA_PATH not set, check manual\n");
- }
-
- fprintf(stderr, "Setting ORCA path to: %s...\n", qm->orca_dir);
- fprintf(stderr, "ORCA initialised...\n\n");
- /* since we append the output to the BASENAME.out file,
- we should delete an existent old out-file here. */
- sprintf(buf, "%s.out", qm->orca_basename);
- remove(buf);
-}
-
-
-static void write_orca_input(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
-{
- int i;
- t_QMMMrec* QMMMrec;
- FILE * out, *pcFile, *addInputFile;
- char * buf, *orcaInput, *addInputFilename, *pcFilename;
-
- QMMMrec = fr->qr;
-
- /* write the first part of the input-file */
- snew(orcaInput, 200);
- sprintf(orcaInput, "%s.inp", qm->orca_basename);
- out = fopen(orcaInput, "w");
-
- snew(addInputFilename, 200);
- sprintf(addInputFilename, "%s.ORCAINFO", qm->orca_basename);
- addInputFile = fopen(addInputFilename, "r");
-
- fprintf(out, "#input-file generated by GROMACS\n");
-
- fprintf(out, "!EnGrad TightSCF\n");
-
- /* here we include the insertion of the additional orca-input */
- snew(buf, 200);
- if (addInputFile != nullptr)
- {
- while (!feof(addInputFile))
- {
- if (fgets(buf, 200, addInputFile) != nullptr)
- {
- fputs(buf, out);
- }
- }
- }
- else
- {
- gmx_fatal(FARGS, "No information on the calculation given in %s\n", addInputFilename);
- }
-
- fclose(addInputFile);
-
- /* write charge and multiplicity */
- fprintf(out, "*xyz %2d%2d\n", qm->QMcharge, qm->multiplicity);
-
- /* write the QM coordinates */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- int atomNr;
- if (qm->atomicnumberQM[i] == 0)
- {
- atomNr = 1;
- }
- else
- {
- atomNr = qm->atomicnumberQM[i];
- }
- fprintf(out, "%3d %10.7f %10.7f %10.7f\n", atomNr, qm->xQM[i][XX] / 0.1,
- qm->xQM[i][YY] / 0.1, qm->xQM[i][ZZ] / 0.1);
- }
- fprintf(out, "*\n");
-
- /* write the MM point charge data */
- if (QMMMrec->QMMMscheme != eQMMMschemeoniom && mm->nrMMatoms)
- {
- /* name of the point charge file */
- snew(pcFilename, 200);
- sprintf(pcFilename, "%s.pc", qm->orca_basename);
- fprintf(out, "%s%s%s\n", "%pointcharges \"", pcFilename, "\"");
- pcFile = fopen(pcFilename, "w");
- fprintf(pcFile, "%d\n", mm->nrMMatoms);
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- fprintf(pcFile, "%8.4f %10.7f %10.7f %10.7f\n", mm->MMcharges[i],
- mm->xMM[i][XX] / 0.1, mm->xMM[i][YY] / 0.1, mm->xMM[i][ZZ] / 0.1);
- }
- fprintf(pcFile, "\n");
- fclose(pcFile);
- }
- fprintf(out, "\n");
-
- fclose(out);
-} /* write_orca_input */
-
-static real read_orca_output(rvec QMgrad[], rvec MMgrad[], const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
-{
- int i, j;
- char buf[300], orca_pcgradFilename[300], orca_engradFilename[300];
- real QMener;
- FILE * pcgrad, *engrad;
- int k;
- t_QMMMrec* QMMMrec;
- QMMMrec = fr->qr;
-
- /* the energy and gradients for the QM part are stored in the engrad file
- * and the gradients for the point charges are stored in the pc file.
- */
- sprintf(orca_engradFilename, "%s.engrad", qm->orca_basename);
- engrad = fopen(orca_engradFilename, "r");
- /* we read the energy and the gradient for the qm-atoms from the engrad file
- */
- /* we can skip the first seven lines
- */
- for (j = 0; j < 7; j++)
- {
- if (fgets(buf, 300, engrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
- }
- /* now comes the energy
- */
- if (fgets(buf, 300, engrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf\n", &QMener);
-#else
- sscanf(buf, "%f\n", &QMener);
-#endif
- /* we can skip the next three lines
- */
- for (j = 0; j < 3; j++)
- {
- if (fgets(buf, 300, engrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
- }
- /* next lines contain the gradients of the QM atoms
- * now comes the gradient, one value per line:
- * (atom1 x \n atom1 y \n atom1 z \n atom2 x ...
- */
-
- for (i = 0; i < 3 * qm->nrQMatoms; i++)
- {
- k = i / 3;
- if (fgets(buf, 300, engrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
-#if GMX_DOUBLE
- if (i % 3 == 0)
- {
- sscanf(buf, "%lf\n", &QMgrad[k][XX]);
- }
- else if (i % 3 == 1)
- {
- sscanf(buf, "%lf\n", &QMgrad[k][YY]);
- }
- else if (i % 3 == 2)
- {
- sscanf(buf, "%lf\n", &QMgrad[k][ZZ]);
- }
-#else
- if (i % 3 == 0)
- {
- sscanf(buf, "%f\n", &QMgrad[k][XX]);
- }
- else if (i % 3 == 1)
- {
- sscanf(buf, "%f\n", &QMgrad[k][YY]);
- }
- else if (i % 3 == 2)
- {
- sscanf(buf, "%f\n", &QMgrad[k][ZZ]);
- }
-#endif
- }
- fclose(engrad);
- /* write the MM point charge data
- */
- if (QMMMrec->QMMMscheme != eQMMMschemeoniom && mm->nrMMatoms)
- {
- sprintf(orca_pcgradFilename, "%s.pcgrad", qm->orca_basename);
- pcgrad = fopen(orca_pcgradFilename, "r");
-
- /* we read the gradient for the mm-atoms from the pcgrad file
- */
- /* we can skip the first line
- */
- if (fgets(buf, 300, pcgrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- if (fgets(buf, 300, pcgrad) == nullptr)
- {
- gmx_fatal(FARGS, "Unexpected end of ORCA output");
- }
-#if GMX_DOUBLE
- sscanf(buf, "%lf%lf%lf\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#else
- sscanf(buf, "%f%f%f\n", &MMgrad[i][XX], &MMgrad[i][YY], &MMgrad[i][ZZ]);
-#endif
- }
- fclose(pcgrad);
- }
- return (QMener);
-}
-
-static void do_orca(char* orca_dir, char* basename)
-{
-
- /* make the call to the orca binary through system()
- * The location of the binary is set through the
- * environment.
- */
- char buf[100];
- sprintf(buf, "%s/%s %s.inp >> %s.out", orca_dir, "orca", basename, basename);
- fprintf(stderr, "Calling '%s'\n", buf);
- if (system(buf) != 0)
- {
- gmx_fatal(FARGS, "Call to '%s' failed\n", buf);
- }
-}
-
-real call_orca(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
-{
- /* normal orca jobs */
- static int step = 0;
- int i, j;
- real QMener;
- rvec * QMgrad, *MMgrad;
- char* exe;
-
- snew(exe, 30);
- sprintf(exe, "%s", "orca");
- snew(QMgrad, qm->nrQMatoms);
- snew(MMgrad, mm->nrMMatoms);
-
- write_orca_input(fr, qm, mm);
- do_orca(qm->orca_dir, qm->orca_basename);
- QMener = read_orca_output(QMgrad, MMgrad, fr, qm, mm);
- /* put the QMMM forces in the force array and to the fshift
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- fshift[i][j] = HARTREE_BOHR2MD * QMgrad[i][j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- f[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- fshift[i + qm->nrQMatoms][j] = HARTREE_BOHR2MD * MMgrad[i][j];
- }
- }
- QMener = QMener * HARTREE2KJ * AVOGADRO;
- step++;
- free(exe);
- return (QMener);
-} /* call_orca */
-
-/* end of orca sub routines */
-
-#pragma GCC diagnostic pop
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#include "gmxpre.h"
-
-#include "qmmm.h"
-
-#include "config.h"
-
-#include <cmath>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include <algorithm>
-
-#include "gromacs/domdec/domdec_struct.h"
-#include "gromacs/fileio/confio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/gmxlib/nrnb.h"
-#include "gromacs/math/functions.h"
-#include "gromacs/math/units.h"
-#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/qm_gamess.h"
-#include "gromacs/mdlib/qm_gaussian.h"
-#include "gromacs/mdlib/qm_mopac.h"
-#include "gromacs/mdlib/qm_orca.h"
-#include "gromacs/mdtypes/commrec.h"
-#include "gromacs/mdtypes/forceoutput.h"
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/mdtypes/mdatom.h"
-#include "gromacs/mdtypes/nblist.h"
-#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/pbc.h"
-#include "gromacs/topology/mtop_lookup.h"
-#include "gromacs/topology/mtop_util.h"
-#include "gromacs/topology/topology.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
-
-// When not built in a configuration with QMMM support, much of this
-// code is unreachable by design. Tell clang not to warn about it.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunreachable-code"
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-
-/* this struct and these comparison functions are needed for creating
- * a QMMM input for the QM routines from the QMMM neighbor list.
- */
-
-typedef struct
-{
- int j;
- int shift;
-} t_j_particle;
-
-static bool struct_comp(const t_j_particle& a, const t_j_particle& b)
-{
- return a.j < b.j;
-}
-
-static real call_QMroutine(const t_commrec gmx_unused* cr,
- const t_forcerec gmx_unused* fr,
- t_QMrec gmx_unused* qm,
- t_MMrec gmx_unused* mm,
- rvec gmx_unused f[],
- rvec gmx_unused fshift[])
-{
- /* makes a call to the requested QM routine (qm->QMmethod)
- * Note that f is actually the gradient, i.e. -f
- */
- /* do a semi-empiprical calculation */
-
- if (qm->QMmethod < eQMmethodRHF && !(mm->nrMMatoms))
- {
- if (GMX_QMMM_MOPAC)
- {
- if (qm->bSH)
- {
- return call_mopac_SH(qm, mm, f, fshift);
- }
- else
- {
- return call_mopac(qm, mm, f, fshift);
- }
- }
- else
- {
- gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
- }
- }
- else
- {
- /* do an ab-initio calculation */
- if (qm->bSH && qm->QMmethod == eQMmethodCASSCF)
- {
- if (GMX_QMMM_GAUSSIAN)
- {
- return call_gaussian_SH(fr, qm, mm, f, fshift);
- }
- else
- {
- gmx_fatal(FARGS, "Ab-initio Surface-hopping only supported with Gaussian.");
- }
- }
- else
- {
- if (GMX_QMMM_GAMESS)
- {
- return call_gamess(qm, mm, f, fshift);
- }
- else if (GMX_QMMM_GAUSSIAN)
- {
- return call_gaussian(fr, qm, mm, f, fshift);
- }
- else if (GMX_QMMM_ORCA)
- {
- return call_orca(fr, qm, mm, f, fshift);
- }
- else
- {
- gmx_fatal(FARGS,
- "Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
- }
- }
- }
-}
-
-static void init_QMroutine(const t_commrec gmx_unused* cr, t_QMrec gmx_unused* qm, t_MMrec gmx_unused* mm)
-{
- /* makes a call to the requested QM routine (qm->QMmethod)
- */
- if (qm->QMmethod < eQMmethodRHF)
- {
- if (GMX_QMMM_MOPAC)
- {
- /* do a semi-empiprical calculation */
- init_mopac(qm);
- }
- else
- {
- gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
- }
- }
- else
- {
- /* do an ab-initio calculation */
- if (GMX_QMMM_GAMESS)
- {
- init_gamess(cr, qm, mm);
- }
- else if (GMX_QMMM_GAUSSIAN)
- {
- init_gaussian(qm);
- }
- else if (GMX_QMMM_ORCA)
- {
- init_orca(qm);
- }
- else
- {
- gmx_fatal(FARGS, "Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
- }
- }
-} /* init_QMroutine */
-
-static void update_QMMM_coord(const rvec* x, const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
-{
- /* shifts the QM and MM particles into the central box and stores
- * these shifted coordinates in the coordinate arrays of the
- * QMMMrec. These coordinates are passed on the QM subroutines.
- */
- int i;
-
- /* shift the QM atoms into the central box
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- rvec_sub(x[qm->indexQM[i]], fr->shift_vec[qm->shiftQM[i]], qm->xQM[i]);
- }
- /* also shift the MM atoms into the central box, if any
- */
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- rvec_sub(x[mm->indexMM[i]], fr->shift_vec[mm->shiftMM[i]], mm->xMM[i]);
- }
-} /* update_QMMM_coord */
-
-/* end of QMMM subroutines */
-
-/* QMMM core routines */
-
-static t_QMrec* mk_QMrec()
-{
- t_QMrec* qm;
- snew(qm, 1);
- return qm;
-} /* mk_QMrec */
-
-static t_MMrec* mk_MMrec()
-{
- t_MMrec* mm;
- snew(mm, 1);
- return mm;
-} /* mk_MMrec */
-
-static void init_QMrec(int grpnr, t_QMrec* qm, int nr, const int* atomarray, const gmx_mtop_t* mtop, const t_inputrec* ir)
-{
- /* fills the t_QMrec struct of QM group grpnr
- */
-
- qm->nrQMatoms = nr;
- snew(qm->xQM, nr);
- snew(qm->indexQM, nr);
- snew(qm->shiftQM, nr); /* the shifts */
- for (int i = 0; i < nr; i++)
- {
- qm->indexQM[i] = atomarray[i];
- }
-
- snew(qm->atomicnumberQM, nr);
- int molb = 0;
- for (int i = 0; i < qm->nrQMatoms; i++)
- {
- const t_atom& atom = mtopGetAtomParameters(mtop, qm->indexQM[i], &molb);
- qm->nelectrons += mtop->atomtypes.atomnumber[atom.type];
- qm->atomicnumberQM[i] = mtop->atomtypes.atomnumber[atom.type];
- }
-
- qm->QMcharge = ir->opts.QMcharge[grpnr];
- qm->multiplicity = ir->opts.QMmult[grpnr];
- qm->nelectrons -= ir->opts.QMcharge[grpnr];
-
- qm->QMmethod = ir->opts.QMmethod[grpnr];
- qm->QMbasis = ir->opts.QMbasis[grpnr];
- /* trajectory surface hopping setup (Gaussian only) */
- qm->bSH = ir->opts.bSH[grpnr];
- qm->CASorbitals = ir->opts.CASorbitals[grpnr];
- qm->CASelectrons = ir->opts.CASelectrons[grpnr];
- qm->SAsteps = ir->opts.SAsteps[grpnr];
- qm->SAon = ir->opts.SAon[grpnr];
- qm->SAoff = ir->opts.SAoff[grpnr];
- /* hack to prevent gaussian from reinitializing all the time */
- qm->nQMcpus = 0; /* number of CPU's to be used by g01, is set
- * upon initializing gaussian
- * (init_gaussian()
- */
- /* print the current layer to allow users to check their input */
- fprintf(stderr, "Layer %d\nnr of QM atoms %d\n", grpnr, nr);
- fprintf(stderr, "QMlevel: %s/%s\n\n", eQMmethod_names[qm->QMmethod], eQMbasis_names[qm->QMbasis]);
-} /* init_QMrec */
-
-static t_QMrec* copy_QMrec(t_QMrec* qm)
-{
- /* copies the contents of qm into a new t_QMrec struct */
- t_QMrec* qmcopy;
- int i;
-
- qmcopy = mk_QMrec();
- qmcopy->nrQMatoms = qm->nrQMatoms;
- snew(qmcopy->xQM, qmcopy->nrQMatoms);
- snew(qmcopy->indexQM, qmcopy->nrQMatoms);
- snew(qmcopy->atomicnumberQM, qm->nrQMatoms);
- snew(qmcopy->shiftQM, qmcopy->nrQMatoms); /* the shifts */
- for (i = 0; i < qmcopy->nrQMatoms; i++)
- {
- qmcopy->shiftQM[i] = qm->shiftQM[i];
- qmcopy->indexQM[i] = qm->indexQM[i];
- qmcopy->atomicnumberQM[i] = qm->atomicnumberQM[i];
- }
- qmcopy->nelectrons = qm->nelectrons;
- qmcopy->multiplicity = qm->multiplicity;
- qmcopy->QMcharge = qm->QMcharge;
- qmcopy->nelectrons = qm->nelectrons;
- qmcopy->QMmethod = qm->QMmethod;
- qmcopy->QMbasis = qm->QMbasis;
- /* trajectory surface hopping setup (Gaussian only) */
- qmcopy->bSH = qm->bSH;
- qmcopy->CASorbitals = qm->CASorbitals;
- qmcopy->CASelectrons = qm->CASelectrons;
- qmcopy->SAsteps = qm->SAsteps;
- qmcopy->SAon = qm->SAon;
- qmcopy->SAoff = qm->SAoff;
-
- /* Gaussian init. variables */
- qmcopy->nQMcpus = qm->nQMcpus;
- for (i = 0; i < DIM; i++)
- {
- qmcopy->SHbasis[i] = qm->SHbasis[i];
- }
- qmcopy->QMmem = qm->QMmem;
- qmcopy->accuracy = qm->accuracy;
- qmcopy->cpmcscf = qm->cpmcscf;
- qmcopy->SAstep = qm->SAstep;
-
- return (qmcopy);
-
-} /*copy_QMrec */
-
-#if GMX_QMMM
-
-t_QMMMrec* mk_QMMMrec()
-{
- t_QMMMrec* qr;
-
- snew(qr, 1);
-
- return qr;
-
-} /* mk_QMMMrec */
-
-#else /* GMX_QMMM */
-
-t_QMMMrec* mk_QMMMrec()
-{
- gmx_incons("Compiled without QMMM");
-} /* mk_QMMMrec */
-#endif
-
-std::vector<int> qmmmAtomIndices(const t_inputrec& ir, const gmx_mtop_t& mtop)
-{
- const int numQmmmGroups = ir.opts.ngQM;
- const SimulationGroups& groups = mtop.groups;
- std::vector<int> qmmmAtoms;
- for (int i = 0; i < numQmmmGroups; i++)
- {
- for (const AtomProxy atomP : AtomRange(mtop))
- {
- int index = atomP.globalAtomNumber();
- if (getGroupType(groups, SimulationAtomGroupType::QuantumMechanics, index) == i)
- {
- qmmmAtoms.push_back(index);
- }
- }
- if (ir.QMMMscheme == eQMMMschemeoniom)
- {
- /* I assume that users specify the QM groups from small to
- * big(ger) in the mdp file
- */
- gmx_mtop_ilistloop_all_t iloop = gmx_mtop_ilistloop_all_init(&mtop);
- int nral1 = 1 + NRAL(F_VSITE2);
- int atomOffset = 0;
- while (const InteractionLists* ilists = gmx_mtop_ilistloop_all_next(iloop, &atomOffset))
- {
- const InteractionList& ilist = (*ilists)[F_VSITE2];
- for (int j = 0; j < ilist.size(); j += nral1)
- {
- const int vsite = atomOffset + ilist.iatoms[j]; /* the vsite */
- const int ai = atomOffset + ilist.iatoms[j + 1]; /* constructing atom */
- const int aj = atomOffset + ilist.iatoms[j + 2]; /* constructing atom */
- if (getGroupType(groups, SimulationAtomGroupType::QuantumMechanics, vsite)
- == getGroupType(groups, SimulationAtomGroupType::QuantumMechanics, ai)
- && getGroupType(groups, SimulationAtomGroupType::QuantumMechanics, vsite)
- == getGroupType(groups, SimulationAtomGroupType::QuantumMechanics, aj))
- {
- /* this dummy link atom needs to be removed from qmmmAtoms
- * before making the QMrec of this layer!
- */
- qmmmAtoms.erase(std::remove_if(qmmmAtoms.begin(), qmmmAtoms.end(),
- [&vsite](int atom) { return atom == vsite; }),
- qmmmAtoms.end());
- }
- }
- }
- }
- }
- return qmmmAtoms;
-}
-
-void removeQmmmAtomCharges(gmx_mtop_t* mtop, gmx::ArrayRef<const int> qmmmAtoms)
-{
- int molb = 0;
- for (gmx::index i = 0; i < qmmmAtoms.ssize(); i++)
- {
- int indexInMolecule;
- mtopGetMolblockIndex(mtop, qmmmAtoms[i], &molb, nullptr, &indexInMolecule);
- t_atom* atom = &mtop->moltype[mtop->molblock[molb].type].atoms.atom[indexInMolecule];
- atom->q = 0.0;
- atom->qB = 0.0;
- }
-}
-
-void init_QMMMrec(const t_commrec* cr, const gmx_mtop_t* mtop, const t_inputrec* ir, const t_forcerec* fr)
-{
- /* we put the atomsnumbers of atoms that belong to the QMMM group in
- * an array that will be copied later to QMMMrec->indexQM[..]. Also
- * it will be used to create an QMMMrec->bQMMM index array that
- * simply contains true/false for QM and MM (the other) atoms.
- */
-
- t_QMMMrec* qr;
- t_MMrec* mm;
-
- if (!GMX_QMMM)
- {
- gmx_incons("Compiled without QMMM");
- }
-
- if (ir->cutoff_scheme != ecutsGROUP)
- {
- gmx_fatal(FARGS, "QMMM is currently only supported with cutoff-scheme=group");
- }
- if (!EI_DYNAMICS(ir->eI))
- {
- gmx_fatal(FARGS, "QMMM is only supported with dynamics");
- }
-
- /* issue a fatal if the user wants to run with more than one node */
- if (PAR(cr))
- {
- gmx_fatal(FARGS, "QM/MM does not work in parallel, use a single rank instead\n");
- }
-
- /* Make a local copy of the QMMMrec */
- qr = fr->qr;
-
- /* bQMMM[..] is an array containing TRUE/FALSE for atoms that are
- * QM/not QM. We first set all elemenst at false. Afterwards we use
- * the qm_arr (=MMrec->indexQM) to changes the elements
- * corresponding to the QM atoms at TRUE. */
-
- qr->QMMMscheme = ir->QMMMscheme;
-
- /* we take the possibility into account that a user has
- * defined more than one QM group:
- */
- /* an ugly work-around in case there is only one group In this case
- * the whole system is treated as QM. Otherwise the second group is
- * always the rest of the total system and is treated as MM.
- */
-
- /* small problem if there is only QM.... so no MM */
-
- int numQmmmGroups = ir->opts.ngQM;
-
- if (qr->QMMMscheme == eQMMMschemeoniom)
- {
- qr->nrQMlayers = numQmmmGroups;
- }
- else
- {
- qr->nrQMlayers = 1;
- }
-
- /* there are numQmmmGroups groups of QM atoms. In case of multiple QM groups
- * I assume that the users wants to do ONIOM. However, maybe it
- * should also be possible to define more than one QM subsystem with
- * independent neighbourlists. I have to think about
- * that.. 11-11-2003
- */
- std::vector<int> qmmmAtoms = qmmmAtomIndices(*ir, *mtop);
- snew(qr->qm, numQmmmGroups);
- for (int i = 0; i < numQmmmGroups; i++)
- {
- /* new layer */
- if (qr->QMMMscheme == eQMMMschemeoniom)
- {
- /* add the atoms to the bQMMM array
- */
-
- /* I assume that users specify the QM groups from small to
- * big(ger) in the mdp file
- */
- qr->qm[i] = mk_QMrec();
- /* store QM atoms in this layer in the QMrec and initialise layer
- */
- init_QMrec(i, qr->qm[i], qmmmAtoms.size(), qmmmAtoms.data(), mtop, ir);
- }
- }
- if (qr->QMMMscheme != eQMMMschemeoniom)
- {
-
- /* standard QMMM, all layers are merged together so there is one QM
- * subsystem and one MM subsystem.
- * Also we set the charges to zero in mtop to prevent the innerloops
- * from doubly counting the electostatic QM MM interaction
- * TODO: Consider doing this in grompp instead.
- */
-
- qr->qm[0] = mk_QMrec();
- /* store QM atoms in the QMrec and initialise
- */
- init_QMrec(0, qr->qm[0], qmmmAtoms.size(), qmmmAtoms.data(), mtop, ir);
-
- /* MM rec creation */
- mm = mk_MMrec();
- mm->scalefactor = ir->scalefactor;
- mm->nrMMatoms = (mtop->natoms) - (qr->qm[0]->nrQMatoms); /* rest of the atoms */
- qr->mm = mm;
- }
- else /* ONIOM */
- { /* MM rec creation */
- mm = mk_MMrec();
- mm->scalefactor = ir->scalefactor;
- mm->nrMMatoms = 0;
- qr->mm = mm;
- }
-
- /* these variables get updated in the update QMMMrec */
-
- if (qr->nrQMlayers == 1)
- {
- /* with only one layer there is only one initialisation
- * needed. Multilayer is a bit more complicated as it requires
- * re-initialisation at every step of the simulation. This is due
- * to the use of COMMON blocks in the fortran QM subroutines.
- */
- if (qr->qm[0]->QMmethod < eQMmethodRHF)
- {
- if (GMX_QMMM_MOPAC)
- {
- /* semi-empiprical 1-layer ONIOM calculation requested (mopac93) */
- init_mopac(qr->qm[0]);
- }
- else
- {
- gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
- }
- }
- else
- {
- /* ab initio calculation requested (gamess/gaussian/ORCA) */
- if (GMX_QMMM_GAMESS)
- {
- init_gamess(cr, qr->qm[0], qr->mm);
- }
- else if (GMX_QMMM_GAUSSIAN)
- {
- init_gaussian(qr->qm[0]);
- }
- else if (GMX_QMMM_ORCA)
- {
- init_orca(qr->qm[0]);
- }
- else
- {
- gmx_fatal(FARGS,
- "Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
- }
- }
- }
-} /* init_QMMMrec */
-
-void update_QMMMrec(const t_commrec* cr, const t_forcerec* fr, const rvec* x, const t_mdatoms* md, const matrix box)
-{
- /* updates the coordinates of both QM atoms and MM atoms and stores
- * them in the QMMMrec.
- *
- * NOTE: is NOT yet working if there are no PBC. Also in ns.c, simple
- * ns needs to be fixed!
- */
- int mm_max = 0, mm_nr = 0, mm_nr_new, i, j, is, k, shift;
- t_j_particle *mm_j_particles = nullptr, *qm_i_particles = nullptr;
- t_QMMMrec* qr;
- t_nblist* QMMMlist;
- rvec dx;
- ivec crd;
- t_QMrec* qm;
- t_MMrec* mm;
- t_pbc pbc;
- int* parallelMMarray = nullptr;
-
- if (!GMX_QMMM)
- {
- gmx_incons("Compiled without QMMM");
- }
-
- /* every cpu has this array. On every processor we fill this array
- * with 1's and 0's. 1's indicate the atoms is a QM atom on the
- * current cpu in a later stage these arrays are all summed. indexes
- * > 0 indicate the atom is a QM atom. Every node therefore knows
- * whcih atoms are part of the QM subsystem.
- */
- /* copy some pointers */
- qr = fr->qr;
- mm = qr->mm;
- QMMMlist = fr->QMMMlist;
-
- /* init_pbc(box); needs to be called first, see pbc.h */
- ivec null_ivec;
- clear_ivec(null_ivec);
- set_pbc_dd(&pbc, fr->ePBC, DOMAINDECOMP(cr) ? cr->dd->nc : null_ivec, FALSE, box);
- /* only in standard (normal) QMMM we need the neighbouring MM
- * particles to provide a electric field of point charges for the QM
- * atoms.
- */
- if (qr->QMMMscheme == eQMMMschemenormal) /* also implies 1 QM-layer */
- {
- /* we NOW create/update a number of QMMMrec entries:
- *
- * 1) the shiftQM, containing the shifts of the QM atoms
- *
- * 2) the indexMM array, containing the index of the MM atoms
- *
- * 3) the shiftMM, containing the shifts of the MM atoms
- *
- * 4) the shifted coordinates of the MM atoms
- *
- * the shifts are used for computing virial of the QM/MM particles.
- */
- qm = qr->qm[0]; /* in case of normal QMMM, there is only one group */
- snew(qm_i_particles, QMMMlist->nri);
- if (QMMMlist->nri)
- {
- qm_i_particles[0].shift = XYZ2IS(0, 0, 0);
- for (i = 0; i < QMMMlist->nri; i++)
- {
- qm_i_particles[i].j = QMMMlist->iinr[i];
-
- if (i)
- {
- qm_i_particles[i].shift =
- pbc_dx_aiuc(&pbc, x[QMMMlist->iinr[0]], x[QMMMlist->iinr[i]], dx);
- }
- /* However, since nri >= nrQMatoms, we do a quicksort, and throw
- * out double, triple, etc. entries later, as we do for the MM
- * list too.
- */
-
- /* compute the shift for the MM j-particles with respect to
- * the QM i-particle and store them.
- */
-
- crd[0] = IS2X(QMMMlist->shift[i]) + IS2X(qm_i_particles[i].shift);
- crd[1] = IS2Y(QMMMlist->shift[i]) + IS2Y(qm_i_particles[i].shift);
- crd[2] = IS2Z(QMMMlist->shift[i]) + IS2Z(qm_i_particles[i].shift);
- is = XYZ2IS(crd[0], crd[1], crd[2]);
- for (j = QMMMlist->jindex[i]; j < QMMMlist->jindex[i + 1]; j++)
- {
- if (mm_nr >= mm_max)
- {
- mm_max += 1000;
- srenew(mm_j_particles, mm_max);
- }
-
- mm_j_particles[mm_nr].j = QMMMlist->jjnr[j];
- mm_j_particles[mm_nr].shift = is;
- mm_nr++;
- }
- }
-
- /* quicksort QM and MM shift arrays and throw away multiple entries */
-
-
- std::sort(qm_i_particles, qm_i_particles + QMMMlist->nri, struct_comp);
- /* The mm_j_particles argument to qsort is not allowed to be nullptr */
- if (mm_nr > 0)
- {
- std::sort(mm_j_particles, mm_j_particles + mm_nr, struct_comp);
- }
- /* remove multiples in the QM shift array, since in init_QMMM() we
- * went through the atom numbers from 0 to md.nr, the order sorted
- * here matches the one of QMindex already.
- */
- j = 0;
- for (i = 0; i < QMMMlist->nri; i++)
- {
- if (i == 0 || qm_i_particles[i].j != qm_i_particles[i - 1].j)
- {
- qm_i_particles[j++] = qm_i_particles[i];
- }
- }
- mm_nr_new = 0;
- /* Remove double entries for the MM array.
- * Also remove mm atoms that have no charges!
- * actually this is already done in the ns.c
- */
- for (i = 0; i < mm_nr; i++)
- {
- if ((i == 0 || mm_j_particles[i].j != mm_j_particles[i - 1].j)
- && !md->bQM[mm_j_particles[i].j]
- && ((md->chargeA[mm_j_particles[i].j] != 0.0_real)
- || (md->chargeB && (md->chargeB[mm_j_particles[i].j] != 0.0_real))))
- {
- mm_j_particles[mm_nr_new++] = mm_j_particles[i];
- }
- }
- mm_nr = mm_nr_new;
- /* store the data retrieved above into the QMMMrec
- */
- k = 0;
- /* Keep the compiler happy,
- * shift will always be set in the loop for i=0
- */
- shift = 0;
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- /* not all qm particles might have appeared as i
- * particles. They might have been part of the same charge
- * group for instance.
- */
- if (qm->indexQM[i] == qm_i_particles[k].j)
- {
- shift = qm_i_particles[k++].shift;
- }
- /* use previous shift, assuming they belong the same charge
- * group anyway,
- */
-
- qm->shiftQM[i] = shift;
- }
- }
- /* parallel excecution */
- if (PAR(cr))
- {
- snew(parallelMMarray, 2 * (md->nr));
- /* only MM particles have a 1 at their atomnumber. The second part
- * of the array contains the shifts. Thus:
- * p[i]=1/0 depending on wether atomnumber i is a MM particle in the QM
- * step or not. p[i+md->nr] is the shift of atomnumber i.
- */
- for (i = 0; i < 2 * (md->nr); i++)
- {
- parallelMMarray[i] = 0;
- }
-
- for (i = 0; i < mm_nr; i++)
- {
- parallelMMarray[mm_j_particles[i].j] = 1;
- parallelMMarray[mm_j_particles[i].j + (md->nr)] = mm_j_particles[i].shift;
- }
- gmx_sumi(md->nr, parallelMMarray, cr);
- mm_nr = 0;
-
- mm_max = 0;
- for (i = 0; i < md->nr; i++)
- {
- if (parallelMMarray[i])
- {
- if (mm_nr >= mm_max)
- {
- mm_max += 1000;
- srenew(mm->indexMM, mm_max);
- srenew(mm->shiftMM, mm_max);
- }
- mm->indexMM[mm_nr] = i;
- mm->shiftMM[mm_nr++] = parallelMMarray[i + md->nr] / parallelMMarray[i];
- }
- }
- mm->nrMMatoms = mm_nr;
- free(parallelMMarray);
- }
- /* serial execution */
- else
- {
- mm->nrMMatoms = mm_nr;
- srenew(mm->shiftMM, mm_nr);
- srenew(mm->indexMM, mm_nr);
- for (i = 0; i < mm_nr; i++)
- {
- mm->indexMM[i] = mm_j_particles[i].j;
- mm->shiftMM[i] = mm_j_particles[i].shift;
- }
- }
- /* (re) allocate memory for the MM coordiate array. The QM
- * coordinate array was already allocated in init_QMMM, and is
- * only (re)filled in the update_QMMM_coordinates routine
- */
- srenew(mm->xMM, mm->nrMMatoms);
- /* now we (re) fill the array that contains the MM charges with
- * the forcefield charges. If requested, these charges will be
- * scaled by a factor
- */
- srenew(mm->MMcharges, mm->nrMMatoms);
- for (i = 0; i < mm->nrMMatoms; i++) /* no free energy yet */
- {
- mm->MMcharges[i] = md->chargeA[mm->indexMM[i]] * mm->scalefactor;
- }
- /* the next routine fills the coordinate fields in the QMMM rec of
- * both the qunatum atoms and the MM atoms, using the shifts
- * calculated above.
- */
-
- update_QMMM_coord(x, fr, qr->qm[0], qr->mm);
- free(qm_i_particles);
- free(mm_j_particles);
- }
- else /* ONIOM */ /* ????? */
- {
- mm->nrMMatoms = 0;
- /* do for each layer */
- for (j = 0; j < qr->nrQMlayers; j++)
- {
- qm = qr->qm[j];
- qm->shiftQM[0] = XYZ2IS(0, 0, 0);
- for (i = 1; i < qm->nrQMatoms; i++)
- {
- qm->shiftQM[i] = pbc_dx_aiuc(&pbc, x[qm->indexQM[0]], x[qm->indexQM[i]], dx);
- }
- update_QMMM_coord(x, fr, qm, mm);
- }
- }
-} /* update_QMMM_rec */
-
-real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShiftForces, const t_forcerec* fr)
-{
- real QMener = 0.0;
- /* a selection for the QM package depending on which is requested
- * (Gaussian, GAMESS-UK, MOPAC or ORCA) needs to be implemented here. Now
- * it works through defines.... Not so nice yet
- */
- t_QMMMrec* qr;
- t_QMrec * qm, *qm2;
- t_MMrec* mm = nullptr;
- rvec * forces = nullptr, *fshift = nullptr, *forces2 = nullptr,
- *fshift2 = nullptr; /* needed for multilayer ONIOM */
- int i, j, k;
-
- if (!GMX_QMMM)
- {
- gmx_incons("Compiled without QMMM");
- }
-
- /* make a local copy the QMMMrec pointer
- */
- qr = fr->qr;
- mm = qr->mm;
-
- /* now different procedures are carried out for one layer ONION and
- * normal QMMM on one hand and multilayer oniom on the other
- */
- gmx::ArrayRef<gmx::RVec> fMM = forceWithShiftForces->force();
- gmx::ArrayRef<gmx::RVec> fshiftMM = forceWithShiftForces->shiftForces();
- if (qr->QMMMscheme == eQMMMschemenormal || qr->nrQMlayers == 1)
- {
- qm = qr->qm[0];
- snew(forces, (qm->nrQMatoms + mm->nrMMatoms));
- snew(fshift, (qm->nrQMatoms + mm->nrMMatoms));
- QMener = call_QMroutine(cr, fr, qm, mm, forces, fshift);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- fMM[qm->indexQM[i]][j] -= forces[i][j];
- fshiftMM[qm->shiftQM[i]][j] += fshift[i][j];
- }
- }
- for (i = 0; i < mm->nrMMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- fMM[mm->indexMM[i]][j] -= forces[qm->nrQMatoms + i][j];
- fshiftMM[mm->shiftMM[i]][j] += fshift[qm->nrQMatoms + i][j];
- }
- }
- free(forces);
- free(fshift);
- }
- else /* Multi-layer ONIOM */
- {
- for (i = 0; i < qr->nrQMlayers - 1; i++) /* last layer is special */
- {
- qm = qr->qm[i];
- qm2 = copy_QMrec(qr->qm[i + 1]);
-
- qm2->nrQMatoms = qm->nrQMatoms;
-
- for (j = 0; j < qm2->nrQMatoms; j++)
- {
- for (k = 0; k < DIM; k++)
- {
- qm2->xQM[j][k] = qm->xQM[j][k];
- }
- qm2->indexQM[j] = qm->indexQM[j];
- qm2->atomicnumberQM[j] = qm->atomicnumberQM[j];
- qm2->shiftQM[j] = qm->shiftQM[j];
- }
-
- qm2->QMcharge = qm->QMcharge;
- /* this layer at the higher level of theory */
- srenew(forces, qm->nrQMatoms);
- srenew(fshift, qm->nrQMatoms);
- /* we need to re-initialize the QMroutine every step... */
- init_QMroutine(cr, qm, mm);
- QMener += call_QMroutine(cr, fr, qm, mm, forces, fshift);
-
- /* this layer at the lower level of theory */
- srenew(forces2, qm->nrQMatoms);
- srenew(fshift2, qm->nrQMatoms);
- init_QMroutine(cr, qm2, mm);
- QMener -= call_QMroutine(cr, fr, qm2, mm, forces2, fshift2);
- /* E = E1high-E1low The next layer includes the current layer at
- * the lower level of theory, which provides + E2low
- * this is similar for gradients
- */
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- fMM[qm->indexQM[i]][j] -= (forces[i][j] - forces2[i][j]);
- fshiftMM[qm->shiftQM[i]][j] += (fshift[i][j] - fshift2[i][j]);
- }
- }
- free(qm2);
- }
- /* now the last layer still needs to be done: */
- qm = qr->qm[qr->nrQMlayers - 1]; /* C counts from 0 */
- init_QMroutine(cr, qm, mm);
- srenew(forces, qm->nrQMatoms);
- srenew(fshift, qm->nrQMatoms);
- QMener += call_QMroutine(cr, fr, qm, mm, forces, fshift);
- for (i = 0; i < qm->nrQMatoms; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- fMM[qm->indexQM[i]][j] -= forces[i][j];
- fshiftMM[qm->shiftQM[i]][j] += fshift[i][j];
- }
- }
- free(forces);
- free(fshift);
- free(forces2);
- free(fshift2);
- }
- return (QMener);
-} /* calculate_QMMM */
-
-#pragma GCC diagnostic pop
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-#ifndef GMX_MDLIB_QMMM_H
-#define GMX_MDLIB_QMMM_H
-
-#include "config.h"
-
-#include <vector>
-
-#include "gromacs/math/vectypes.h"
-#include "gromacs/mdlib/tgroup.h"
-#include "gromacs/utility/arrayref.h"
-
-#define GMX_QMMM (GMX_QMMM_MOPAC || GMX_QMMM_GAMESS || GMX_QMMM_GAUSSIAN || GMX_QMMM_ORCA)
-
-struct gmx_localtop_t;
-struct gmx_mtop_t;
-struct t_commrec;
-struct t_forcerec;
-struct t_inputrec;
-struct t_mdatoms;
-struct t_QMMMrec;
-
-namespace gmx
-{
-class ForceWithShiftForces;
-}
-
-typedef struct
-{
- int nrQMatoms; /* total nr of QM atoms */
- rvec* xQM; /* shifted to center of box */
- int* indexQM; /* atom i = atom indexQM[i] in mdrun */
- int* atomicnumberQM; /* atomic numbers of QM atoms */
- real* QMcharges; /* atomic charges of QM atoms(ONIOM) */
- int* shiftQM;
- int QMcharge; /* charge of the QM system */
- int multiplicity; /* multipicity (no of unpaired eln) */
- int QMmethod; /* see enums.h for all methods */
- int QMbasis; /* see enums.h for all bases */
- int nelectrons; /* total number of elecs in QM region*/
- /* Gaussian specific stuff */
- int nQMcpus; /* no. of CPUs used for the QM calc. */
- int QMmem; /* memory for the gaussian calc. */
- int accuracy; /* convergence criterium (E(-x)) */
- gmx_bool cpmcscf; /* using cpmcscf(l1003)*/
- char* gauss_dir;
- char* gauss_exe;
- char* devel_dir;
- char* orca_basename; /* basename for I/O with orca */
- char* orca_dir; /* directory for ORCA */
- /* Surface hopping stuff */
- gmx_bool bSH; /* surface hopping (diabatic only) */
- real SAon; /* at which energy gap the SA starts */
- real SAoff; /* at which energy gap the SA stops */
- int SAsteps; /* stepwise switchinng on the SA */
- int SAstep; /* current state of SA */
- int CIdim;
- real* CIvec1;
- real* CIvec2;
- real* CIvec1old;
- real* CIvec2old;
- ivec SHbasis;
- int CASelectrons;
- int CASorbitals;
-} t_QMrec;
-
-typedef struct
-{
- int nrMMatoms; /* nr of MM atoms, updated every step*/
- rvec* xMM; /* shifted to center of box */
- int* indexMM; /* atom i = atom indexMM[I] in mdrun */
- real* MMcharges; /* MM point charges in std QMMM calc.*/
- int* shiftMM;
- int* MMatomtype; /* only important for semi-emp. */
- real scalefactor;
-} t_MMrec;
-
-
-typedef struct t_QMMMrec
-{
- int QMMMscheme; /* ONIOM (multi-layer) or normal */
- int nrQMlayers; /* number of QM layers (total layers +1 (MM)) */
- t_QMrec** qm; /* atoms and run params for each QM group */
- t_MMrec* mm; /* there can only be one MM subsystem ! */
-} t_QMMMrec;
-
-void atomic_number(int nr, char*** atomtype, int* nucnum);
-
-t_QMMMrec* mk_QMMMrec();
-/* allocates memory for QMMMrec */
-
-void init_QMMMrec(const t_commrec* cr, const gmx_mtop_t* mtop, const t_inputrec* ir, const t_forcerec* fr);
-
-/* init_QMMMrec initializes the QMMM record. From
- * topology->atoms.atomname and topology->atoms.atomtype the atom
- * names and types are read; from inputrec->QMcharge
- * resp. inputrec->QMmult the nelecs and multiplicity are determined
- * and md->cQMMM gives numbers of the MM and QM atoms
- */
-void update_QMMMrec(const t_commrec* cr, const t_forcerec* fr, const rvec* x, const t_mdatoms* md, const matrix box);
-
-/* update_QMMMrec fills the MM stuff in QMMMrec. The MM atoms are
- * taken froom the neighbourlists of the QM atoms. In a QMMM run this
- * routine should be called at every step, since it updates the MM
- * elements of the t_QMMMrec struct.
- */
-real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShiftForces, const t_forcerec* fr);
-
-/* QMMM computes the QM forces. This routine makes either function
- * calls to gmx QM routines (derived from MOPAC7 (semi-emp.) and MPQC
- * (ab initio)) or generates input files for an external QM package
- * (listed in QMMMrec.QMpackage). The binary of the QM package is
- * called by system().
- */
-
-/*! \brief
- * Return vector of atom indices for atoms in the QMMM region.
- *
- * \param[in] mtop Topology to use for populating array.
- * \param[in] ir Inputrec used in simulation.
- * \returns Vector of atoms.
- */
-std::vector<int> qmmmAtomIndices(const t_inputrec& ir, const gmx_mtop_t& mtop);
-
-/*! \brief
- * Remove charges from QMMM atoms.
- *
- * \param[in] mtop Topology used for removing atoms.
- * \param[in] qmmmAtoms ArrayRef to vector conatining qmmm atom indices.
- */
-void removeQmmmAtomCharges(gmx_mtop_t* mtop, gmx::ArrayRef<const int> qmmmAtoms);
-
-#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/domdec.h"
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/mdrunutility/printtime.h"
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
+#include "gromacs/math/arrayrefwithpadding.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/vec.h"
sfree(settled);
}
-void settle_set_constraints(settledata* settled, const t_ilist* il_settle, const t_mdatoms& mdatoms)
+void settle_set_constraints(settledata* settled, const InteractionList& il_settle, const t_mdatoms& mdatoms)
{
#if GMX_SIMD_HAVE_REAL
const int pack_size = GMX_SIMD_REAL_WIDTH;
#endif
const int nral1 = 1 + NRAL(F_SETTLE);
- int nsettle = il_settle->nr / nral1;
+ int nsettle = il_settle.size() / nral1;
settled->nsettle = nsettle;
if (nsettle > 0)
{
- const t_iatom* iatoms = il_settle->iatoms;
+ ArrayRef<const int> iatoms = il_settle.iatoms;
/* Here we initialize the normal SETTLE parameters */
if (settled->massw.mO < 0)
}
}
-void settle_proj(settledata* settled,
- ConstraintVariable econq,
- int nsettle,
- const t_iatom iatoms[],
- const t_pbc* pbc,
- const rvec x[],
- rvec* der,
- rvec* derp,
- int calcvir_atom_end,
- tensor vir_r_m_dder)
+void settle_proj(settledata* settled,
+ ConstraintVariable econq,
+ int nsettle,
+ const t_iatom iatoms[],
+ const t_pbc* pbc,
+ ArrayRef<const RVec> x,
+ ArrayRef<RVec> der,
+ ArrayRef<RVec> derp,
+ int calcvir_atom_end,
+ tensor vir_r_m_dder)
{
/* Settle for projection out constraint components
* of derivatives of the coordinates.
}
}
-void csettle(settledata* settled,
- int nthread,
- int thread,
- const t_pbc* pbc,
- const real x[],
- real xprime[],
- real invdt,
- real* v,
- bool bCalcVirial,
- tensor vir_r_m_dr,
- bool* bErrorHasOccurred)
+void csettle(settledata* settled,
+ int nthread,
+ int thread,
+ const t_pbc* pbc,
+ ArrayRefWithPadding<const RVec> x,
+ ArrayRefWithPadding<RVec> xprime,
+ real invdt,
+ ArrayRefWithPadding<RVec> v,
+ bool bCalcVirial,
+ tensor vir_r_m_dr,
+ bool* bErrorHasOccurred)
{
+ const real* xPtr = as_rvec_array(x.paddedArrayRef().data())[0];
+ real* xprimePtr = as_rvec_array(xprime.paddedArrayRef().data())[0];
+ real* vPtr = as_rvec_array(v.paddedArrayRef().data())[0];
+
#if GMX_SIMD_HAVE_REAL
if (settled->bUseSimd)
{
set_pbc_simd(pbc, pbcSimd);
settleTemplateWrapper<SimdReal, SimdBool, GMX_SIMD_REAL_WIDTH, const real*>(
- settled, nthread, thread, pbcSimd, x, xprime, invdt, v, bCalcVirial, vir_r_m_dr,
- bErrorHasOccurred);
+ settled, nthread, thread, pbcSimd, xPtr, xprimePtr, invdt, vPtr, bCalcVirial,
+ vir_r_m_dr, bErrorHasOccurred);
}
else
#endif
}
else
{
- set_pbc(&pbcNo, epbcNONE, nullptr);
+ set_pbc(&pbcNo, PbcType::No, nullptr);
pbcNonNull = &pbcNo;
}
- settleTemplateWrapper<real, bool, 1, const t_pbc*>(settled, nthread, thread, pbcNonNull, x,
- xprime, invdt, v, bCalcVirial,
- vir_r_m_dr, bErrorHasOccurred);
+ settleTemplateWrapper<real, bool, 1, const t_pbc*>(settled, nthread, thread, pbcNonNull,
+ &xPtr[0], &xprimePtr[0], invdt, &vPtr[0],
+ bCalcVirial, vir_r_m_dr, bErrorHasOccurred);
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/idef.h"
-struct gmx_cmap_t;
struct gmx_mtop_t;
+struct InteractionList;
struct t_inputrec;
struct t_mdatoms;
struct t_pbc;
namespace gmx
{
+template<typename>
+class ArrayRef;
+template<typename>
+class ArrayRefWithPadding;
enum class ConstraintVariable : int;
/* Abstract type for SETTLE that is defined only in the file that uses it */
void settle_free(settledata* settled);
/*! \brief Set up the indices for the settle constraints */
-void settle_set_constraints(settledata* settled, const t_ilist* il_settle, const t_mdatoms& mdatoms);
+void settle_set_constraints(settledata* settled, const InteractionList& il_settle, const t_mdatoms& mdatoms);
/*! \brief Constrain coordinates using SETTLE.
* Can be called on any number of threads.
*/
-void csettle(settledata* settled, /* The SETTLE structure */
- int nthread, /* The number of threads used */
- int thread, /* Our thread index */
- const t_pbc* pbc, /* PBC data pointer, can be NULL */
- const real x[], /* Reference coordinates */
- real xprime[], /* New coords, to be settled */
- real invdt, /* 1/delta_t */
- real* v, /* Also constrain v if v!=NULL */
- bool bCalcVirial, /* Calculate the virial contribution */
- tensor vir_r_m_dr, /* sum r x m delta_r */
- bool* bErrorHasOccurred /* True if a settle error occurred */
+void csettle(settledata* settled, /* The SETTLE structure */
+ int nthread, /* The number of threads used */
+ int thread, /* Our thread index */
+ const t_pbc* pbc, /* PBC data pointer, can be NULL */
+ ArrayRefWithPadding<const RVec> x, /* Reference coordinates */
+ ArrayRefWithPadding<RVec> xprime, /* New coords, to be settled */
+ real invdt, /* 1/delta_t */
+ ArrayRefWithPadding<RVec> v, /* Also constrain v if v!=NULL */
+ bool bCalcVirial, /* Calculate the virial contribution */
+ tensor vir_r_m_dr, /* sum r x m delta_r */
+ bool* bErrorHasOccurred /* True if a settle error occurred */
);
/*! \brief Analytical algorithm to subtract the components of derivatives
* of coordinates working on settle type constraint.
*/
-void settle_proj(settledata* settled,
- ConstraintVariable econq,
- int nsettle,
- const t_iatom iatoms[],
- const t_pbc* pbc, /* PBC data pointer, can be NULL */
- const rvec x[],
- rvec* der,
- rvec* derp,
- int CalcVirAtomEnd,
- tensor vir_r_m_dder);
+void settle_proj(settledata* settled,
+ ConstraintVariable econq,
+ int nsettle,
+ const int iatoms[],
+ const t_pbc* pbc, /* PBC data pointer, can be NULL */
+ ArrayRef<const RVec> x,
+ ArrayRef<RVec> der,
+ ArrayRef<RVec> derp,
+ int CalcVirAtomEnd,
+ tensor vir_r_m_dder);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* using CUDA, including class initialization, data-structures management
* and GPU kernel.
*
- * \note Management of CUDA stream and periodic boundary should be unified with LINCS
- * and removed from here once constraints are fully integrated with update module.
- * \todo Reconsider naming to use "gpu" suffix instead of "cuda".
*
* \author Artem Zhmurov <zhmurov@gmail.com>
*
*/
#include "gmxpre.h"
-#include "settle_cuda.cuh"
+#include "settle_gpu.cuh"
#include <assert.h>
#include <stdio.h>
* \param [in] gm_x Coordinates of atoms before the timestep.
* \param [in,out] gm_x Coordinates of atoms after the timestep (constrained coordinates will be
* saved here).
- * \param [in] pbcAiuc Periodic boundary conditions data.
* \param [in] invdt Reciprocal timestep.
* \param [in] gm_v Velocities of the particles.
* \param [in] gm_virialScaled Virial tensor.
+ * \param [in] pbcAiuc Periodic boundary conditions data.
*/
template<bool updateVelocities, bool computeVirial>
__launch_bounds__(c_maxThreadsPerBlock) __global__
const SettleParameters pars,
const float3* __restrict__ gm_x,
float3* __restrict__ gm_xprime,
- const PbcAiuc pbcAiuc,
- float invdt,
+ float invdt,
float3* __restrict__ gm_v,
- float* __restrict__ gm_virialScaled)
+ float* __restrict__ gm_virialScaled,
+ const PbcAiuc pbcAiuc)
{
/* ******************************************************************* */
/* ** */
return kernelPtr;
}
-void SettleCuda::apply(const float3* d_x,
- float3* d_xp,
- const bool updateVelocities,
- float3* d_v,
- const real invdt,
- const bool computeVirial,
- tensor virialScaled)
+void SettleGpu::apply(const float3* d_x,
+ float3* d_xp,
+ const bool updateVelocities,
+ float3* d_v,
+ const real invdt,
+ const bool computeVirial,
+ tensor virialScaled,
+ const PbcAiuc pbcAiuc)
{
ensureNoPendingCudaError("In CUDA version SETTLE");
{
// Fill with zeros so the values can be reduced to it
// Only 6 values are needed because virial is symmetrical
- clearDeviceBufferAsync(&d_virialScaled_, 0, 6, commandStream_);
+ clearDeviceBufferAsync(&d_virialScaled_, 0, 6, deviceStream_);
}
auto kernelPtr = getSettleKernelPtr(updateVelocities, computeVirial);
{
config.sharedMemorySize = 0;
}
- config.stream = commandStream_;
const auto kernelArgs = prepareGpuKernelArguments(kernelPtr, config, &numSettles_, &d_atomIds_,
- &settleParameters_, &d_x, &d_xp, &pbcAiuc_,
- &invdt, &d_v, &d_virialScaled_);
+ &settleParameters_, &d_x, &d_xp, &invdt, &d_v,
+ &d_virialScaled_, &pbcAiuc);
- launchGpuKernel(kernelPtr, config, nullptr, "settle_kernel<updateVelocities, computeVirial>", kernelArgs);
+ launchGpuKernel(kernelPtr, config, deviceStream_, nullptr,
+ "settle_kernel<updateVelocities, computeVirial>", kernelArgs);
if (computeVirial)
{
- copyFromDeviceBuffer(h_virialScaled_.data(), &d_virialScaled_, 0, 6, commandStream_,
+ copyFromDeviceBuffer(h_virialScaled_.data(), &d_virialScaled_, 0, 6, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
// Mapping [XX, XY, XZ, YY, YZ, ZZ] internal format to a tensor object
return;
}
-SettleCuda::SettleCuda(const gmx_mtop_t& mtop, CommandStream commandStream) :
- commandStream_(commandStream)
+SettleGpu::SettleGpu(const gmx_mtop_t& mtop, const DeviceContext& deviceContext, const DeviceStream& deviceStream) :
+ deviceContext_(deviceContext),
+ deviceStream_(deviceStream)
{
static_assert(sizeof(real) == sizeof(float),
"Real numbers should be in single precision in GPU code.");
initSettleParameters(&settleParameters_, mO, mH, dOH, dHH);
- allocateDeviceBuffer(&d_virialScaled_, 6, nullptr);
+ allocateDeviceBuffer(&d_virialScaled_, 6, deviceContext_);
h_virialScaled_.resize(6);
}
-SettleCuda::~SettleCuda()
+SettleGpu::~SettleGpu()
{
// Early exit if there is no settles
if (numSettles_ == 0)
}
}
-void SettleCuda::set(const t_idef& idef, const t_mdatoms gmx_unused& md)
+void SettleGpu::set(const InteractionDefinitions& idef, const t_mdatoms gmx_unused& md)
{
- const int nral1 = 1 + NRAL(F_SETTLE);
- t_ilist il_settle = idef.il[F_SETTLE];
- t_iatom* iatoms = il_settle.iatoms;
- numSettles_ = il_settle.nr / nral1;
+ const int nral1 = 1 + NRAL(F_SETTLE);
+ const InteractionList& il_settle = idef.il[F_SETTLE];
+ ArrayRef<const int> iatoms = il_settle.iatoms;
+ numSettles_ = il_settle.size() / nral1;
- reallocateDeviceBuffer(&d_atomIds_, numSettles_, &numAtomIds_, &numAtomIdsAlloc_, nullptr);
+ reallocateDeviceBuffer(&d_atomIds_, numSettles_, &numAtomIds_, &numAtomIdsAlloc_, deviceContext_);
h_atomIds_.resize(numSettles_);
for (int i = 0; i < numSettles_; i++)
{
settler.z = iatoms[i * nral1 + 3]; // Second hydrogen index
h_atomIds_.at(i) = settler;
}
- copyToDeviceBuffer(&d_atomIds_, h_atomIds_.data(), 0, numSettles_, commandStream_,
+ copyToDeviceBuffer(&d_atomIds_, h_atomIds_.data(), 0, numSettles_, deviceStream_,
GpuApiCallBehavior::Sync, nullptr);
}
-void SettleCuda::setPbc(const t_pbc* pbc)
-{
- setPbcAiuc(pbc->ndim_ePBC, pbc->box, &pbcAiuc_);
-}
-
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \internal \file
*
- * \brief Declares class for CUDA implementation of SETTLE
+ * \brief Declares class for GPU implementation of SETTLE
*
* \author Artem Zhmurov <zhmurov@gmail.com>
*
* \ingroup module_mdlib
*/
-#ifndef GMX_MDLIB_SETTLE_CUDA_CUH
-#define GMX_MDLIB_SETTLE_CUDA_CUH
+#ifndef GMX_MDLIB_SETTLE_GPU_CUH
+#define GMX_MDLIB_SETTLE_GPU_CUH
#include "gmxpre.h"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/math/functions.h"
#include "gromacs/math/invertmatrix.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/pbc_aiuc.h"
-#include "gromacs/topology/idef.h"
#include "gromacs/topology/topology.h"
+class InteractionDefinitions;
+
namespace gmx
{
initializeProjectionMatrix(invmO, invmH, dOH, dHH, p->invmat);
}
-/*! \internal \brief Class with interfaces and data for CUDA version of SETTLE. */
-class SettleCuda
+/*! \internal \brief Class with interfaces and data for GPU version of SETTLE. */
+class SettleGpu
{
public:
* \param[in] mtop Topology of the system to gen the masses for O and H atoms and
* target O-H and H-H distances. These values are also checked for
* consistency.
- * \param[in] commandStream Device stream to use.
+ * \param[in] deviceContext Device context (dummy in CUDA).
+ * \param[in] deviceStream Device stream to use.
*/
- SettleCuda(const gmx_mtop_t& mtop, CommandStream commandStream);
+ SettleGpu(const gmx_mtop_t& mtop, const DeviceContext& deviceContext, const DeviceStream& deviceStream);
- ~SettleCuda();
+ ~SettleGpu();
/*! \brief Apply SETTLE.
*
* multipliers when velocities are updated)
* \param[in] computeVirial If virial should be updated.
* \param[in,out] virialScaled Scaled virial tensor to be updated.
+ * \param[in] pbcAiuc PBC data.
*/
void apply(const float3* d_x,
float3* d_xp,
float3* d_v,
const real invdt,
const bool computeVirial,
- tensor virialScaled);
+ tensor virialScaled,
+ const PbcAiuc pbcAiuc);
/*! \brief
* Update data-structures (e.g. after NB search step).
* \param[in] idef System topology
* \param[in] md Atoms data. Can be used to update masses if needed (not used now).
*/
- void set(const t_idef& idef, const t_mdatoms& md);
-
- /*! \brief
- * Update PBC data.
- *
- * Converts pbc data from t_pbc into the PbcAiuc format and stores the latter.
- *
- * \todo PBC should not be handled by constraints.
- *
- * \param[in] pbc The PBC data in t_pbc format.
- */
- void setPbc(const t_pbc* pbc);
-
+ void set(const InteractionDefinitions& idef, const t_mdatoms& md);
private:
- //! CUDA stream
- CommandStream commandStream_;
- //! Periodic boundary data
- PbcAiuc pbcAiuc_;
+ //! GPU context object
+ const DeviceContext& deviceContext_;
+ //! GPU stream
+ const DeviceStream& deviceStream_;
//! Scaled virial tensor (9 reals, GPU)
std::vector<float> h_virialScaled_;
} // namespace gmx
-#endif
+#endif // GMX_MDLIB_SETTLE_GPU_CUH
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
-#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/mdatom.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/invblock.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
namespace gmx
{
-struct shakedata
-{
- rvec* rij;
- real* half_of_reduced_mass;
- real* distance_squared_tolerance;
- real* constraint_distance_squared;
- int nalloc;
- /* SOR stuff */
- real delta;
- real omega;
- real gamma;
- int nblocks; /* The number of SHAKE blocks */
- int* sblock; /* The SHAKE blocks */
- int sblock_nalloc; /* The allocation size of sblock */
- /*! \brief Scaled Lagrange multiplier for each constraint.
- *
- * Value is -2 * eta from p. 336 of the paper, divided by the
- * constraint distance. */
- real* scaled_lagrange_multiplier;
- int lagr_nalloc; /* The allocation size of scaled_lagrange_multiplier */
-};
-
-shakedata* shake_init()
-{
- shakedata* d;
-
- snew(d, 1);
-
- d->nalloc = 0;
- d->rij = nullptr;
- d->half_of_reduced_mass = nullptr;
- d->distance_squared_tolerance = nullptr;
- d->constraint_distance_squared = nullptr;
-
- /* SOR initialization */
- d->delta = 0.1;
- d->omega = 1.0;
- d->gamma = 1000000;
-
- return d;
-}
-
-void done_shake(shakedata* d)
-{
- sfree(d->rij);
- sfree(d->half_of_reduced_mass);
- sfree(d->distance_squared_tolerance);
- sfree(d->constraint_distance_squared);
- sfree(d->sblock);
- sfree(d->scaled_lagrange_multiplier);
- sfree(d);
-}
-
typedef struct
{
int iatom[3];
//! Reallocates a vector.
static void resizeLagrangianData(shakedata* shaked, int ncons)
{
- if (ncons > shaked->lagr_nalloc)
- {
- shaked->lagr_nalloc = over_alloc_dd(ncons);
- srenew(shaked->scaled_lagrange_multiplier, shaked->lagr_nalloc);
- }
+ shaked->scaled_lagrange_multiplier.resize(ncons);
}
-void make_shake_sblock_serial(shakedata* shaked, const t_idef* idef, const t_mdatoms& md)
+void make_shake_sblock_serial(shakedata* shaked, InteractionDefinitions* idef, const t_mdatoms& md)
{
- int i, j, m, ncons;
+ int i, m, ncons;
int bstart, bnr;
t_blocka sblocks;
t_sortblock* sb;
- t_iatom* iatom;
int* inv_sblock;
/* Since we are processing the local topology,
* the F_CONSTRNC ilist has been concatenated to the F_CONSTR ilist.
*/
- ncons = idef->il[F_CONSTR].nr / 3;
+ ncons = idef->il[F_CONSTR].size() / 3;
init_blocka(&sblocks);
sfree(sblocks.index); // To solve memory leak
- gen_sblocks(nullptr, 0, md.homenr, idef, &sblocks, FALSE);
+ gen_sblocks(nullptr, md.homenr, *idef, &sblocks, FALSE);
/*
bstart=(idef->nodeid > 0) ? blocks->multinr[idef->nodeid-1] : 0;
nblocks=blocks->multinr[idef->nodeid] - bstart;
*/
- bstart = 0;
- shaked->nblocks = sblocks.nr;
+ bstart = 0;
if (debug)
{
- fprintf(debug, "ncons: %d, bstart: %d, nblocks: %d\n", ncons, bstart, shaked->nblocks);
+ fprintf(debug, "ncons: %d, bstart: %d, nblocks: %d\n", ncons, bstart, sblocks.nr);
}
/* Calculate block number for each atom */
* sort the constraints in order of the sblock number
* and the atom numbers, really sorting a segment of the array!
*/
- iatom = idef->il[F_CONSTR].iatoms;
+ int* iatom = idef->il[F_CONSTR].iatoms.data();
snew(sb, ncons);
for (i = 0; (i < ncons); i++, iatom += 3)
{
pr_sortblock(debug, "After sorting", ncons, sb);
}
- iatom = idef->il[F_CONSTR].iatoms;
+ iatom = idef->il[F_CONSTR].iatoms.data();
for (i = 0; (i < ncons); i++, iatom += 3)
{
for (m = 0; (m < 3); m++)
}
}
- j = 0;
- snew(shaked->sblock, shaked->nblocks + 1);
+ shaked->sblock.clear();
bnr = -2;
for (i = 0; (i < ncons); i++)
{
if (sb[i].blocknr != bnr)
{
- bnr = sb[i].blocknr;
- shaked->sblock[j++] = 3 * i;
+ bnr = sb[i].blocknr;
+ shaked->sblock.push_back(3 * i);
}
}
/* Last block... */
- shaked->sblock[j++] = 3 * ncons;
+ shaked->sblock.push_back(3 * ncons);
- if (j != (shaked->nblocks + 1))
- {
- fprintf(stderr, "bstart: %d\n", bstart);
- fprintf(stderr, "j: %d, nblocks: %d, ncons: %d\n", j, shaked->nblocks, ncons);
- for (i = 0; (i < ncons); i++)
- {
- fprintf(stderr, "i: %5d sb[i].blocknr: %5d\n", i, sb[i].blocknr);
- }
- for (j = 0; (j <= shaked->nblocks); j++)
- {
- fprintf(stderr, "sblock[%3d]=%5d\n", j, shaked->sblock[j]);
- }
- gmx_fatal(FARGS,
- "DEATH HORROR: "
- "sblocks does not match idef->il[F_CONSTR]");
- }
sfree(sb);
sfree(inv_sblock);
resizeLagrangianData(shaked, ncons);
}
-// TODO: Check if this code is useful. It might never be called.
-void make_shake_sblock_dd(shakedata* shaked, const t_ilist* ilcon, const gmx_domdec_t* dd)
+void make_shake_sblock_dd(shakedata* shaked, const InteractionList& ilcon)
{
- int ncons, c, cg;
- t_iatom* iatom;
+ int ncons, c, cg;
- if (dd->ncg_home + 1 > shaked->sblock_nalloc)
- {
- shaked->sblock_nalloc = over_alloc_dd(dd->ncg_home + 1);
- srenew(shaked->sblock, shaked->sblock_nalloc);
- }
-
- ncons = ilcon->nr / 3;
- iatom = ilcon->iatoms;
- shaked->nblocks = 0;
- cg = 0;
+ ncons = ilcon.size() / 3;
+ const int* iatom = ilcon.iatoms.data();
+ shaked->sblock.clear();
+ cg = 0;
for (c = 0; c < ncons; c++)
{
if (c == 0 || iatom[1] >= cg + 1)
{
- shaked->sblock[shaked->nblocks++] = 3 * c;
+ shaked->sblock.push_back(3 * c);
while (iatom[1] >= cg + 1)
{
cg++;
}
iatom += 3;
}
- shaked->sblock[shaked->nblocks] = 3 * ncons;
+ shaked->sblock.push_back(3 * ncons);
resizeLagrangianData(shaked, ncons);
}
* The algorithm here is based section five of Ryckaert, Ciccotti and
* Berendsen, J Comp Phys, 23, 327, 1977.
*
- * \param[in] iatom Mini-topology of triples of constraint type (unused in this
- * function) and indices of the two atoms involved
+ * \param[in] iatom Mini-topology of triplets of constraint type (unused
+ * in this function) and indices of two atoms involved
* \param[in] ncon Number of constraints
* \param[out] nnit Number of iterations performed
* \param[in] maxnit Maximum number of iterations permitted
* \param[in] constraint_distance_squared The objective value for each constraint
- * \param[inout] positions The initial (and final) values of the positions of all atoms
+ * \param[inout] positions The initial (and final) values of the positions
+ * of all atoms
+ * \param[in] pbc PBC information
* \param[in] initial_displacements The initial displacements of each constraint
* \param[in] half_of_reduced_mass Half of the reduced mass for each constraint
* \param[in] omega SHAKE over-relaxation factor (set non-1.0 by
- * using shake-sor=yes in the .mdp, but there is no documentation anywhere)
+ * using shake-sor=yes in the .mdp,
+ * but there is no documentation anywhere)
* \param[in] invmass Inverse mass of each atom
* \param[in] distance_squared_tolerance Multiplicative tolerance on the difference in the
* square of the constrained distance (see code)
- * \param[out] scaled_lagrange_multiplier Scaled Lagrange multiplier for each constraint (-2 * eta from p. 336
- * of the paper, divided by the constraint distance)
- * \param[out] nerror Zero upon success, returns one more than the index of the
- * problematic constraint if the input was malformed
+ * \param[out] scaled_lagrange_multiplier Scaled Lagrange multiplier for each constraint
+ * (-2 * eta from p. 336 of the paper, divided by
+ * the constraint distance)
+ * \param[out] nerror Zero upon success, returns one more than the index of
+ * the problematic constraint if the input was malformed
*
* \todo Make SHAKE use better data structures, in particular for iatom. */
-void cshake(const int iatom[],
- int ncon,
- int* nnit,
- int maxnit,
- const real constraint_distance_squared[],
- real positions[],
- const real initial_displacements[],
- const real half_of_reduced_mass[],
- real omega,
- const real invmass[],
- const real distance_squared_tolerance[],
- real scaled_lagrange_multiplier[],
- int* nerror)
+void cshake(const int iatom[],
+ int ncon,
+ int* nnit,
+ int maxnit,
+ ArrayRef<const real> constraint_distance_squared,
+ ArrayRef<RVec> positions,
+ const t_pbc* pbc,
+ ArrayRef<const RVec> initial_displacements,
+ ArrayRef<const real> half_of_reduced_mass,
+ real omega,
+ const real invmass[],
+ ArrayRef<const real> distance_squared_tolerance,
+ ArrayRef<real> scaled_lagrange_multiplier,
+ int* nerror)
{
/* default should be increased! MRS 8/4/2009 */
const real mytol = 1e-10;
- int ll, i, j, i3, j3, l3;
- int ix, iy, iz, jx, jy, jz;
+ int ll, i, j, l3;
real r_dot_r_prime;
real constraint_distance_squared_ll;
- real r_prime_squared;
real scaled_lagrange_multiplier_ll;
- real r_prime_x, r_prime_y, r_prime_z, diff, im, jm;
+ real diff, im, jm;
real xh, yh, zh, rijx, rijy, rijz;
int nit, error, nconv;
real iconvf;
for (ll = 0; (ll < ncon) && (error == 0); ll++)
{
l3 = 3 * ll;
- rijx = initial_displacements[l3 + XX];
- rijy = initial_displacements[l3 + YY];
- rijz = initial_displacements[l3 + ZZ];
+ rijx = initial_displacements[ll][XX];
+ rijy = initial_displacements[ll][YY];
+ rijz = initial_displacements[ll][ZZ];
i = iatom[l3 + 1];
j = iatom[l3 + 2];
- i3 = 3 * i;
- j3 = 3 * j;
- ix = i3 + XX;
- iy = i3 + YY;
- iz = i3 + ZZ;
- jx = j3 + XX;
- jy = j3 + YY;
- jz = j3 + ZZ;
/* Compute r prime between atoms i and j, which is the
displacement *before* this update stage */
- r_prime_x = positions[ix] - positions[jx];
- r_prime_y = positions[iy] - positions[jy];
- r_prime_z = positions[iz] - positions[jz];
- r_prime_squared = (r_prime_x * r_prime_x + r_prime_y * r_prime_y + r_prime_z * r_prime_z);
+ rvec r_prime;
+ if (pbc)
+ {
+ pbc_dx(pbc, positions[i], positions[j], r_prime);
+ }
+ else
+ {
+ rvec_sub(positions[i], positions[j], r_prime);
+ }
+ const real r_prime_squared = norm2(r_prime);
constraint_distance_squared_ll = constraint_distance_squared[ll];
diff = constraint_distance_squared_ll - r_prime_squared;
if (iconvf > 1.0)
{
nconv = static_cast<int>(iconvf);
- r_dot_r_prime = (rijx * r_prime_x + rijy * r_prime_y + rijz * r_prime_z);
+ r_dot_r_prime = (rijx * r_prime[XX] + rijy * r_prime[YY] + rijz * r_prime[ZZ]);
if (r_dot_r_prime < constraint_distance_squared_ll * mytol)
{
zh = rijz * scaled_lagrange_multiplier_ll;
im = invmass[i];
jm = invmass[j];
- positions[ix] += xh * im;
- positions[iy] += yh * im;
- positions[iz] += zh * im;
- positions[jx] -= xh * jm;
- positions[jy] -= yh * jm;
- positions[jz] -= zh * jm;
+ positions[i][XX] += xh * im;
+ positions[i][YY] += yh * im;
+ positions[i][ZZ] += zh * im;
+ positions[j][XX] -= xh * jm;
+ positions[j][YY] -= yh * jm;
+ positions[j][ZZ] -= zh * jm;
}
}
}
}
//! Implements RATTLE (ie. SHAKE for velocity verlet integrators)
-static void crattle(const int iatom[],
- int ncon,
- int* nnit,
- int maxnit,
- const real constraint_distance_squared[],
- real vp[],
- const real rij[],
- const real m2[],
- real omega,
- const real invmass[],
- const real distance_squared_tolerance[],
- real scaled_lagrange_multiplier[],
- int* nerror,
- real invdt)
+static void crattle(const int iatom[],
+ int ncon,
+ int* nnit,
+ int maxnit,
+ ArrayRef<const real> constraint_distance_squared,
+ ArrayRef<RVec> vp,
+ ArrayRef<const RVec> rij,
+ ArrayRef<const real> m2,
+ real omega,
+ const real invmass[],
+ ArrayRef<const real> distance_squared_tolerance,
+ ArrayRef<real> scaled_lagrange_multiplier,
+ int* nerror,
+ real invdt)
{
/*
* r.c. van schaik and w.f. van gunsteren
* second part of rattle algorithm
*/
- int ll, i, j, i3, j3, l3;
- int ix, iy, iz, jx, jy, jz;
+ int ll, i, j, l3;
real constraint_distance_squared_ll;
- real vpijd, vx, vy, vz, acor, fac, im, jm;
+ real vpijd, acor, fac, im, jm;
real xh, yh, zh, rijx, rijy, rijz;
int nit, error, nconv;
real iconvf;
for (ll = 0; (ll < ncon) && (error == 0); ll++)
{
l3 = 3 * ll;
- rijx = rij[l3 + XX];
- rijy = rij[l3 + YY];
- rijz = rij[l3 + ZZ];
+ rijx = rij[ll][XX];
+ rijy = rij[ll][YY];
+ rijz = rij[ll][ZZ];
i = iatom[l3 + 1];
j = iatom[l3 + 2];
- i3 = 3 * i;
- j3 = 3 * j;
- ix = i3 + XX;
- iy = i3 + YY;
- iz = i3 + ZZ;
- jx = j3 + XX;
- jy = j3 + YY;
- jz = j3 + ZZ;
- vx = vp[ix] - vp[jx];
- vy = vp[iy] - vp[jy];
- vz = vp[iz] - vp[jz];
-
- vpijd = vx * rijx + vy * rijy + vz * rijz;
+ rvec v;
+ rvec_sub(vp[i], vp[j], v);
+
+ vpijd = v[XX] * rijx + v[YY] * rijy + v[ZZ] * rijz;
constraint_distance_squared_ll = constraint_distance_squared[ll];
/* iconv is zero when the error is smaller than a bound */
im = invmass[i];
jm = invmass[j];
- vp[ix] += xh * im;
- vp[iy] += yh * im;
- vp[iz] += zh * im;
- vp[jx] -= xh * jm;
- vp[jy] -= yh * jm;
- vp[jz] -= zh * jm;
+ vp[i][XX] += xh * im;
+ vp[i][YY] += yh * im;
+ vp[i][ZZ] += zh * im;
+ vp[j][XX] -= xh * jm;
+ vp[j][YY] -= yh * jm;
+ vp[j][ZZ] -= zh * jm;
}
}
}
}
//! Applies SHAKE
-static int vec_shakef(FILE* fplog,
- shakedata* shaked,
- const real invmass[],
- int ncon,
- t_iparams ip[],
- t_iatom* iatom,
- real tol,
- const rvec x[],
- rvec prime[],
- real omega,
- bool bFEP,
- real lambda,
- real scaled_lagrange_multiplier[],
- real invdt,
- rvec* v,
- bool bCalcVir,
- tensor vir_r_m_dr,
- ConstraintVariable econq)
+static int vec_shakef(FILE* fplog,
+ shakedata* shaked,
+ const real invmass[],
+ int ncon,
+ ArrayRef<const t_iparams> ip,
+ const int* iatom,
+ real tol,
+ ArrayRef<const RVec> x,
+ ArrayRef<RVec> prime,
+ const t_pbc* pbc,
+ real omega,
+ bool bFEP,
+ real lambda,
+ ArrayRef<real> scaled_lagrange_multiplier,
+ real invdt,
+ ArrayRef<RVec> v,
+ bool bCalcVir,
+ tensor vir_r_m_dr,
+ ConstraintVariable econq)
{
- rvec* rij;
- real * half_of_reduced_mass, *distance_squared_tolerance, *constraint_distance_squared;
- int maxnit = 1000;
- int nit = 0, ll, i, j, d, d2, type;
- t_iatom* ia;
- real L1;
- real mm = 0., tmp;
- int error = 0;
- real constraint_distance;
-
- if (ncon > shaked->nalloc)
- {
- shaked->nalloc = over_alloc_dd(ncon);
- srenew(shaked->rij, shaked->nalloc);
- srenew(shaked->half_of_reduced_mass, shaked->nalloc);
- srenew(shaked->distance_squared_tolerance, shaked->nalloc);
- srenew(shaked->constraint_distance_squared, shaked->nalloc);
- }
- rij = shaked->rij;
- half_of_reduced_mass = shaked->half_of_reduced_mass;
- distance_squared_tolerance = shaked->distance_squared_tolerance;
- constraint_distance_squared = shaked->constraint_distance_squared;
-
- L1 = 1.0 - lambda;
- ia = iatom;
+ int maxnit = 1000;
+ int nit = 0, ll, i, j, d, d2, type;
+ real L1;
+ real mm = 0., tmp;
+ int error = 0;
+ real constraint_distance;
+
+ shaked->rij.resize(ncon);
+ shaked->half_of_reduced_mass.resize(ncon);
+ shaked->distance_squared_tolerance.resize(ncon);
+ shaked->constraint_distance_squared.resize(ncon);
+
+ ArrayRef<RVec> rij = shaked->rij;
+ ArrayRef<real> half_of_reduced_mass = shaked->half_of_reduced_mass;
+ ArrayRef<real> distance_squared_tolerance = shaked->distance_squared_tolerance;
+ ArrayRef<real> constraint_distance_squared = shaked->constraint_distance_squared;
+
+ L1 = 1.0 - lambda;
+ const int* ia = iatom;
for (ll = 0; (ll < ncon); ll++, ia += 3)
{
type = ia[0];
switch (econq)
{
case ConstraintVariable::Positions:
- cshake(iatom, ncon, &nit, maxnit, constraint_distance_squared, prime[0], rij[0],
+ cshake(iatom, ncon, &nit, maxnit, constraint_distance_squared, prime, pbc, rij,
half_of_reduced_mass, omega, invmass, distance_squared_tolerance,
scaled_lagrange_multiplier, &error);
break;
case ConstraintVariable::Velocities:
- crattle(iatom, ncon, &nit, maxnit, constraint_distance_squared, prime[0], rij[0],
+ crattle(iatom, ncon, &nit, maxnit, constraint_distance_squared, prime, rij,
half_of_reduced_mass, omega, invmass, distance_squared_tolerance,
scaled_lagrange_multiplier, &error, invdt);
break;
i = ia[1];
j = ia[2];
- if ((econq == ConstraintVariable::Positions) && v != nullptr)
+ if ((econq == ConstraintVariable::Positions) && !v.empty())
{
/* Correct the velocities */
mm = scaled_lagrange_multiplier[ll] * invmass[i] * invdt;
}
//! Check that constraints are satisfied.
-static void check_cons(FILE* log,
- int nc,
- const rvec x[],
- rvec prime[],
- rvec v[],
- t_iparams ip[],
- t_iatom* iatom,
- const real invmass[],
- ConstraintVariable econq)
+static void check_cons(FILE* log,
+ int nc,
+ ArrayRef<const RVec> x,
+ ArrayRef<const RVec> prime,
+ ArrayRef<const RVec> v,
+ const t_pbc* pbc,
+ ArrayRef<const t_iparams> ip,
+ const int* iatom,
+ const real invmass[],
+ ConstraintVariable econq)
{
- t_iatom* ia;
- int ai, aj;
- int i;
- real d, dp;
- rvec dx, dv;
+ int ai, aj;
+ int i;
+ real d, dp;
+ rvec dx, dv;
- GMX_ASSERT(v, "Input has to be non-null");
+ GMX_ASSERT(!v.empty(), "Input has to be non-null");
fprintf(log, " i mi j mj before after should be\n");
- ia = iatom;
+ const int* ia = iatom;
for (i = 0; (i < nc); i++, ia += 3)
{
ai = ia[1];
switch (econq)
{
case ConstraintVariable::Positions:
- rvec_sub(prime[ai], prime[aj], dx);
+ if (pbc)
+ {
+ pbc_dx(pbc, prime[ai], prime[aj], dx);
+ }
+ else
+ {
+ rvec_sub(prime[ai], prime[aj], dx);
+ }
dp = norm(dx);
fprintf(log, "%5d %5.2f %5d %5.2f %10.5f %10.5f %10.5f\n", ai + 1,
1.0 / invmass[ai], aj + 1, 1.0 / invmass[aj], d, dp, ip[ia[0]].constr.dA);
}
//! Applies SHAKE.
-static bool bshakef(FILE* log,
- shakedata* shaked,
- const real invmass[],
- const t_idef& idef,
- const t_inputrec& ir,
- const rvec x_s[],
- rvec prime[],
- t_nrnb* nrnb,
- real lambda,
- real* dvdlambda,
- real invdt,
- rvec* v,
- bool bCalcVir,
- tensor vir_r_m_dr,
- bool bDumpOnError,
- ConstraintVariable econq)
+static bool bshakef(FILE* log,
+ shakedata* shaked,
+ const real invmass[],
+ const InteractionDefinitions& idef,
+ const t_inputrec& ir,
+ ArrayRef<const RVec> x_s,
+ ArrayRef<RVec> prime,
+ const t_pbc* pbc,
+ t_nrnb* nrnb,
+ real lambda,
+ real* dvdlambda,
+ real invdt,
+ ArrayRef<RVec> v,
+ bool bCalcVir,
+ tensor vir_r_m_dr,
+ bool bDumpOnError,
+ ConstraintVariable econq)
{
- t_iatom* iatoms;
- real * lam, dt_2, dvdl;
- int i, n0, ncon, blen, type, ll;
- int tnit = 0, trij = 0;
+ real dt_2, dvdl;
+ int i, n0, ncon, blen, type, ll;
+ int tnit = 0, trij = 0;
- ncon = idef.il[F_CONSTR].nr / 3;
+ ncon = idef.il[F_CONSTR].size() / 3;
for (ll = 0; ll < ncon; ll++)
{
// TODO Rewrite this block so that it is obvious that i, iatoms
// and lam are all iteration variables. Is this easier if the
// sblock data structure is organized differently?
- iatoms = &(idef.il[F_CONSTR].iatoms[shaked->sblock[0]]);
- lam = shaked->scaled_lagrange_multiplier;
- for (i = 0; (i < shaked->nblocks);)
+ const int* iatoms = &(idef.il[F_CONSTR].iatoms[shaked->sblock[0]]);
+ ArrayRef<real> lam = shaked->scaled_lagrange_multiplier;
+ for (i = 0; (i < shaked->numShakeBlocks());)
{
blen = (shaked->sblock[i + 1] - shaked->sblock[i]);
blen /= 3;
n0 = vec_shakef(log, shaked, invmass, blen, idef.iparams, iatoms, ir.shake_tol, x_s, prime,
- shaked->omega, ir.efep != efepNO, lambda, lam, invdt, v, bCalcVir,
+ pbc, shaked->omega, ir.efep != efepNO, lambda, lam, invdt, v, bCalcVir,
vir_r_m_dr, econq);
if (n0 == 0)
if (bDumpOnError && log)
{
{
- check_cons(log, blen, x_s, prime, v, idef.iparams, iatoms, invmass, econq);
+ check_cons(log, blen, x_s, prime, v, pbc, idef.iparams, iatoms, invmass, econq);
}
}
return FALSE;
tnit += n0 * blen;
trij += blen;
iatoms += 3 * blen; /* Increment pointer! */
- lam += blen;
+ lam = lam.subArray(blen, lam.ssize() - blen);
i++;
}
/* only for position part? */
{
if (ir.efep != efepNO)
{
- real bondA, bondB;
+ ArrayRef<const t_iparams> iparams = idef.iparams;
+
/* TODO This should probably use invdt, so that sd integrator scaling works properly */
dt_2 = 1 / gmx::square(ir.delta_t);
dvdl = 0;
/* The vector scaled_lagrange_multiplier[ll] contains the value -2 r_ll eta_ll
(eta_ll is the estimate of the Langrangian, definition on page 336 of Ryckaert et
al 1977), so the pre-factors are already present. */
- bondA = idef.iparams[type].constr.dA;
- bondB = idef.iparams[type].constr.dB;
+ const real bondA = iparams[type].constr.dA;
+ const real bondB = iparams[type].constr.dB;
dvdl += shaked->scaled_lagrange_multiplier[ll] * dt_2 * (bondB - bondA);
}
*dvdlambda += dvdl;
}
inc_nrnb(nrnb, eNR_SHAKE, tnit);
inc_nrnb(nrnb, eNR_SHAKE_RIJ, trij);
- if (v)
+ if (!v.empty())
{
inc_nrnb(nrnb, eNR_CONSTR_V, trij * 2);
}
return TRUE;
}
-bool constrain_shake(FILE* log,
- shakedata* shaked,
- const real invmass[],
- const t_idef& idef,
- const t_inputrec& ir,
- const rvec x_s[],
- rvec xprime[],
- rvec vprime[],
- t_nrnb* nrnb,
- real lambda,
- real* dvdlambda,
- real invdt,
- rvec* v,
- bool bCalcVir,
- tensor vir_r_m_dr,
- bool bDumpOnError,
- ConstraintVariable econq)
+bool constrain_shake(FILE* log,
+ shakedata* shaked,
+ const real invmass[],
+ const InteractionDefinitions& idef,
+ const t_inputrec& ir,
+ ArrayRef<const RVec> x_s,
+ ArrayRef<RVec> xprime,
+ ArrayRef<RVec> vprime,
+ const t_pbc* pbc,
+ t_nrnb* nrnb,
+ real lambda,
+ real* dvdlambda,
+ real invdt,
+ ArrayRef<RVec> v,
+ bool bCalcVir,
+ tensor vir_r_m_dr,
+ bool bDumpOnError,
+ ConstraintVariable econq)
{
- if (shaked->nblocks == 0)
+ if (shaked->numShakeBlocks() == 0)
{
return true;
}
switch (econq)
{
case (ConstraintVariable::Positions):
- bOK = bshakef(log, shaked, invmass, idef, ir, x_s, xprime, nrnb, lambda, dvdlambda,
+ bOK = bshakef(log, shaked, invmass, idef, ir, x_s, xprime, pbc, nrnb, lambda, dvdlambda,
invdt, v, bCalcVir, vir_r_m_dr, bDumpOnError, econq);
break;
case (ConstraintVariable::Velocities):
- bOK = bshakef(log, shaked, invmass, idef, ir, x_s, vprime, nrnb, lambda, dvdlambda,
- invdt, nullptr, bCalcVir, vir_r_m_dr, bDumpOnError, econq);
+ bOK = bshakef(log, shaked, invmass, idef, ir, x_s, vprime, pbc, nrnb, lambda, dvdlambda,
+ invdt, {}, bCalcVir, vir_r_m_dr, bDumpOnError, econq);
break;
default:
gmx_fatal(FARGS,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_MDLIB_SHAKE_H
#define GMX_MDLIB_SHAKE_H
+#include "gromacs/math/vec.h"
#include "gromacs/topology/block.h"
-#include "gromacs/topology/idef.h"
+#include "gromacs/utility/real.h"
-struct gmx_domdec_t;
+struct InteractionList;
+class InteractionDefinitions;
struct t_inputrec;
struct t_mdatoms;
struct t_nrnb;
+struct t_pbc;
namespace gmx
{
+template<typename T>
+class ArrayRef;
enum class ConstraintVariable : int;
-/* Abstract type for SHAKE that is defined only in the file that uses it */
-struct shakedata;
-
-/*! \brief Initializes and return the SHAKE data structure */
-shakedata* shake_init();
+/*! \libinternal
+ * \brief Working data for the SHAKE algorithm
+ */
+struct shakedata
+{
+ //! Returns the number of SHAKE blocks */
+ int numShakeBlocks() const { return sblock.size() - 1; }
-//! Destroy SHAKE. Needed to solve memory leaks.
-void done_shake(shakedata* d);
+ //! The reference constraint vectors
+ std::vector<RVec> rij;
+ //! The reduced mass of the two atoms in each constraint times 0.5
+ std::vector<real> half_of_reduced_mass;
+ //! Multiplicative tolerance on the difference in the square of the constrained distance
+ std::vector<real> distance_squared_tolerance;
+ //! The reference constraint distances squared
+ std::vector<real> constraint_distance_squared;
+ /* SOR stuff */
+ //! SOR delta
+ real delta = 0.1;
+ //! SOR omega
+ real omega = 1.0;
+ //! SOR gamma
+ real gamma = 1000000;
+ //! The SHAKE blocks, block i contains constraints sblock[i]/3 to sblock[i+1]/3 */
+ std::vector<int> sblock = { 0 };
+ /*! \brief Scaled Lagrange multiplier for each constraint.
+ *
+ * Value is -2 * eta from p. 336 of the paper, divided by the
+ * constraint distance. */
+ std::vector<real> scaled_lagrange_multiplier;
+};
//! Make SHAKE blocks when not using DD.
-void make_shake_sblock_serial(shakedata* shaked, const t_idef* idef, const t_mdatoms& md);
+void make_shake_sblock_serial(shakedata* shaked, InteractionDefinitions* idef, const t_mdatoms& md);
//! Make SHAKE blocks when using DD.
-void make_shake_sblock_dd(shakedata* shaked, const t_ilist* ilcon, const gmx_domdec_t* dd);
+void make_shake_sblock_dd(shakedata* shaked, const InteractionList& ilcon);
/*! \brief Shake all the atoms blockwise. It is assumed that all the constraints
* in the idef->shakes field are sorted, to ascending block nr. The
* sblock[n] to sblock[n+1]. Array sblock should be large enough.
* Return TRUE when OK, FALSE when shake-error
*/
-bool constrain_shake(FILE* log, /* Log file */
- shakedata* shaked, /* Total number of atoms */
- const real invmass[], /* Atomic masses */
- const t_idef& idef, /* The interaction def */
- const t_inputrec& ir, /* Input record */
- const rvec x_s[], /* Coords before update */
- rvec xprime[], /* Output coords when constraining x */
- rvec vprime[], /* Output coords when constraining v */
- t_nrnb* nrnb, /* Performance measure */
- real lambda, /* FEP lambda */
- real* dvdlambda, /* FEP force */
- real invdt, /* 1/delta_t */
- rvec* v, /* Also constrain v if v!=NULL */
- bool bCalcVir, /* Calculate r x m delta_r */
- tensor vir_r_m_dr, /* sum r x m delta_r */
- bool bDumpOnError, /* Dump debugging stuff on error*/
- ConstraintVariable econq); /* which type of constraint is occurring */
+bool constrain_shake(FILE* log, /* Log file */
+ shakedata* shaked, /* Total number of atoms */
+ const real invmass[], /* Atomic masses */
+ const InteractionDefinitions& idef, /* The interaction def */
+ const t_inputrec& ir, /* Input record */
+ ArrayRef<const RVec> x_s, /* Coords before update */
+ ArrayRef<RVec> xprime, /* Output coords when constraining x */
+ ArrayRef<RVec> vprime, /* Output coords when constraining v */
+ const t_pbc* pbc, /* PBC information */
+ t_nrnb* nrnb, /* Performance measure */
+ real lambda, /* FEP lambda */
+ real* dvdlambda, /* FEP force */
+ real invdt, /* 1/delta_t */
+ ArrayRef<RVec> v, /* Also constrain v if not empty */
+ bool bCalcVir, /* Calculate r x m delta_r */
+ tensor vir_r_m_dr, /* sum r x m delta_r */
+ bool bDumpOnError, /* Dump debugging stuff on error*/
+ ConstraintVariable econq); /* which type of constraint is occurring */
/*! \brief Regular iterative shake */
-void cshake(const int iatom[],
- int ncon,
- int* nnit,
- int maxnit,
- const real dist2[],
- real xp[],
- const real rij[],
- const real m2[],
- real omega,
- const real invmass[],
- const real tt[],
- real lagr[],
- int* nerror);
+void cshake(const int iatom[],
+ int ncon,
+ int* nnit,
+ int maxnit,
+ ArrayRef<const real> dist2,
+ ArrayRef<RVec> xp,
+ const t_pbc* pbc,
+ ArrayRef<const RVec> rij,
+ ArrayRef<const real> half_of_reduced_mass,
+ real omega,
+ const real invmass[],
+ ArrayRef<const real> distance_squared_tolerance,
+ ArrayRef<real> scaled_lagrange_multiplier,
+ int* nerror);
} // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013-2020, by the GROMACS development team, led by
+ * Copyright (c) 2013-2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/partition.h"
#include "gromacs/essentialdynamics/edsam.h"
#include "gromacs/ewald/pme.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/ewald/pme_pp_comm_gpu.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nonbonded/nb_free_energy.h"
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdlib/enerdata_utils.h"
#include "gromacs/mdlib/force.h"
+#include "gromacs/mdlib/force_flags.h"
#include "gromacs/mdlib/forcerec.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/update.h"
+#include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdlib/wholemoleculetransform.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/forceoutput.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/iforceprovider.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/mdtypes/state_propagator_data_gpu.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/nbnxm/nbnxm.h"
+#include "gromacs/nbnxm/nbnxm_gpu.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/pulling/pull_rotation.h"
const rvec x[],
const gmx::ForceWithShiftForces& forceWithShiftForces,
tensor vir_part,
- const t_graph* graph,
const matrix box,
t_nrnb* nrnb,
const t_forcerec* fr,
- int ePBC)
+ PbcType pbcType)
{
/* The short-range virial from surrounding boxes */
const rvec* fshift = as_rvec_array(forceWithShiftForces.shiftForces().data());
- calc_vir(SHIFTS, fr->shift_vec, fshift, vir_part, ePBC == epbcSCREW, box);
+ calc_vir(SHIFTS, fr->shift_vec, fshift, vir_part, pbcType == PbcType::Screw, box);
inc_nrnb(nrnb, eNR_VIRIAL, SHIFTS);
/* Calculate partial virial, for local atoms only, based on short range.
* Total virial is computed in global_stat, called from do_md
*/
const rvec* f = as_rvec_array(forceWithShiftForces.force().data());
- f_calc_vir(start, start + homenr, x, f, vir_part, graph, box);
+ f_calc_vir(start, start + homenr, x, f, vir_part, box);
inc_nrnb(nrnb, eNR_VIRIAL, homenr);
if (debug)
* which is why pull_potential is called close to other communication.
*/
wallcycle_start(wcycle, ewcPULLPOT);
- set_pbc(&pbc, ir->ePBC, box);
+ set_pbc(&pbc, ir->pbcType, box);
dvdl = 0;
enerd->term[F_COM_PULL] += pull_potential(pull_work, mdatoms, &pbc, cr, t, lambda[efptRESTRAINT],
as_rvec_array(x.data()), force, &dvdl);
enerd->dvdl_lin[efptRESTRAINT] += dvdl;
+ for (auto& dhdl : enerd->dhdlLambda)
+ {
+ dhdl += dvdl;
+ }
wallcycle_stop(wcycle, ewcPULLPOT);
}
enerd->dvdl_lin[efptCOUL] += dvdl_q;
enerd->dvdl_lin[efptVDW] += dvdl_lj;
+ for (auto& dhdl : enerd->dhdlLambda)
+ {
+ dhdl += dvdl_q + dvdl_lj;
+ }
+
if (wcycle)
{
dd_cycles_add(cr->dd, cycles_seppme, ddCyclPME);
ForceOutputs* forceOutputs,
tensor vir_force,
const t_mdatoms* mdatoms,
- const t_graph* graph,
const t_forcerec* fr,
const gmx_vsite_t* vsite,
const StepWorkload& stepWork)
*/
matrix virial = { { 0 } };
spread_vsite_f(vsite, x, fDirectVir, nullptr, stepWork.computeVirial, virial, nrnb,
- &top->idef, fr->ePBC, fr->bMolPBC, graph, box, cr, wcycle);
+ top->idef, fr->pbcType, fr->bMolPBC, box, cr, wcycle);
forceWithVirial.addVirialContribution(virial);
}
if (awh)
{
enerd->term[F_COM_PULL] += awh->applyBiasForcesAndUpdateBias(
- inputrec->ePBC, *mdatoms, box, forceWithVirial, t, step, wcycle, fplog);
+ inputrec->pbcType, *mdatoms, box, forceWithVirial, t, step, wcycle, fplog);
}
}
}
}
-/*! \brief Makes PME flags from StepWorkload data.
- *
- * \param[in] stepWork Step schedule flags
- * \returns PME flags
- */
-static int makePmeFlags(const StepWorkload& stepWork)
-{
- return GMX_PME_SPREAD | GMX_PME_SOLVE | (stepWork.computeVirial ? GMX_PME_CALC_ENER_VIR : 0)
- | (stepWork.computeEnergy ? GMX_PME_CALC_ENER_VIR : 0)
- | (stepWork.computeForces ? GMX_PME_CALC_F : 0);
-}
-
/*! \brief Launch the prepare_step and spread stages of PME GPU.
*
* \param[in] pmedata The PME structure
* \param[in] box The box matrix
* \param[in] stepWork Step schedule flags
- * \param[in] pmeFlags PME flags
* \param[in] xReadyOnDevice Event synchronizer indicating that the coordinates are ready in
* the device memory. \param[in] wcycle The wallcycle structure
*/
static inline void launchPmeGpuSpread(gmx_pme_t* pmedata,
const matrix box,
const StepWorkload& stepWork,
- int pmeFlags,
GpuEventSynchronizer* xReadyOnDevice,
gmx_wallcycle_t wcycle)
{
- pme_gpu_prepare_computation(pmedata, stepWork.haveDynamicBox, box, wcycle, pmeFlags,
- stepWork.useGpuPmeFReduction);
+ pme_gpu_prepare_computation(pmedata, box, wcycle, stepWork);
pme_gpu_launch_spread(pmedata, xReadyOnDevice, wcycle);
}
*
* \param[in] pmedata The PME structure
* \param[in] wcycle The wallcycle structure
+ * \param[in] stepWork Step schedule flags
*/
-static void launchPmeGpuFftAndGather(gmx_pme_t* pmedata, gmx_wallcycle_t wcycle)
+static void launchPmeGpuFftAndGather(gmx_pme_t* pmedata, gmx_wallcycle_t wcycle, const gmx::StepWorkload& stepWork)
{
- pme_gpu_launch_complex_transforms(pmedata, wcycle);
- pme_gpu_launch_gather(pmedata, wcycle, PmeForceOutputHandling::Set);
+ pme_gpu_launch_complex_transforms(pmedata, wcycle, stepWork);
+ pme_gpu_launch_gather(pmedata, wcycle);
}
/*! \brief
* \param[in,out] forceOutputs Output buffer for the forces and virial
* \param[in,out] enerd Energy data structure results are reduced into
* \param[in] stepWork Step schedule flags
- * \param[in] pmeFlags PME flags
* \param[in] wcycle The wallcycle structure
*/
static void alternatePmeNbGpuWaitReduce(nonbonded_verlet_t* nbv,
gmx::ForceOutputs* forceOutputs,
gmx_enerdata_t* enerd,
const StepWorkload& stepWork,
- int pmeFlags,
gmx_wallcycle_t wcycle)
{
bool isPmeGpuDone = false;
{
GpuTaskCompletion completionType =
(isNbGpuDone) ? GpuTaskCompletion::Wait : GpuTaskCompletion::Check;
- isPmeGpuDone = pme_gpu_try_finish_task(pmedata, pmeFlags, wcycle, &forceWithVirial,
+ isPmeGpuDone = pme_gpu_try_finish_task(pmedata, stepWork, wcycle, &forceWithVirial,
enerd, completionType);
}
/*! \brief Set up flags that have the lifetime of the domain indicating what type of work is there to compute.
*/
-static DomainLifetimeWorkload setupDomainLifetimeWorkload(const t_inputrec& inputrec,
- const t_forcerec& fr,
- const pull_t* pull_work,
- const gmx_edsam* ed,
- const t_idef& idef,
- const t_fcdata& fcd,
- const t_mdatoms& mdatoms,
+static DomainLifetimeWorkload setupDomainLifetimeWorkload(const t_inputrec& inputrec,
+ const t_forcerec& fr,
+ const pull_t* pull_work,
+ const gmx_edsam* ed,
+ const InteractionDefinitions& idef,
+ const t_fcdata& fcd,
+ const t_mdatoms& mdatoms,
const SimulationWorkload& simulationWork,
const StepWorkload& stepWork)
{
/* \brief Launch end-of-step GPU tasks: buffer clearing and rolling pruning.
*
- * TODO: eliminate the \p useGpuNonbonded and \p useGpuNonbonded when these are
+ * TODO: eliminate \p useGpuPmeOnThisRank when this is
* incorporated in DomainLifetimeWorkload.
*/
static void launchGpuEndOfStepTasks(nonbonded_verlet_t* nbv,
gmx_pme_t* pmedata,
gmx_enerdata_t* enerd,
const gmx::MdrunScheduleWorkload& runScheduleWork,
- bool useGpuNonbonded,
- bool useGpuPme,
+ bool useGpuPmeOnThisRank,
int64_t step,
gmx_wallcycle_t wcycle)
{
- if (useGpuNonbonded)
+ if (runScheduleWork.simulationWork.useGpuNonbonded)
{
/* Launch pruning before buffer clearing because the API overhead of the
* clear kernel launches can leave the GPU idle while it could be running
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
- if (useGpuPme)
+ if (useGpuPmeOnThisRank)
{
pme_gpu_reinit_computation(pmedata, wcycle);
}
}
}
+//! \brief Data structure to hold dipole-related data and staging arrays
+struct DipoleData
+{
+ //! Dipole staging for fast summing over MPI
+ gmx::DVec muStaging[2] = { { 0.0, 0.0, 0.0 } };
+ //! Dipole staging for states A and B (index 0 and 1 resp.)
+ gmx::RVec muStateAB[2] = { { 0.0_real, 0.0_real, 0.0_real } };
+};
+
+
+static void reduceAndUpdateMuTot(DipoleData* dipoleData,
+ const t_commrec* cr,
+ const bool haveFreeEnergy,
+ gmx::ArrayRef<const real> lambda,
+ rvec muTotal,
+ const DDBalanceRegionHandler& ddBalanceRegionHandler)
+{
+ if (PAR(cr))
+ {
+ gmx_sumd(2 * DIM, dipoleData->muStaging[0], cr);
+ ddBalanceRegionHandler.reopenRegionCpu();
+ }
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < DIM; j++)
+ {
+ dipoleData->muStateAB[i][j] = dipoleData->muStaging[i][j];
+ }
+ }
+
+ if (!haveFreeEnergy)
+ {
+ copy_rvec(dipoleData->muStateAB[0], muTotal);
+ }
+ else
+ {
+ for (int j = 0; j < DIM; j++)
+ {
+ muTotal[j] = (1.0 - lambda[efptCOUL]) * dipoleData->muStateAB[0][j]
+ + lambda[efptCOUL] * dipoleData->muStateAB[1][j];
+ }
+ }
+}
void do_force(FILE* fplog,
const t_commrec* cr,
gmx_enerdata_t* enerd,
t_fcdata* fcd,
gmx::ArrayRef<real> lambda,
- t_graph* graph,
t_forcerec* fr,
gmx::MdrunScheduleWorkload* runScheduleWork,
const gmx_vsite_t* vsite,
- rvec mu_tot,
+ rvec muTotal,
double t,
gmx_edsam* ed,
int legacyFlags,
const DDBalanceRegionHandler& ddBalanceRegionHandler)
{
- int i, j;
- double mu[2 * DIM];
+ GMX_ASSERT(force.unpaddedArrayRef().ssize() >= fr->natoms_force_constr,
+ "The size of the force buffer should be at least the number of atoms to compute "
+ "forces for");
+
nonbonded_verlet_t* nbv = fr->nbv.get();
interaction_const_t* ic = fr->ic;
gmx::StatePropagatorDataGpu* stateGpu = fr->stateGpu;
- // TODO remove the code below when the legacy flags are not in use anymore
- /* modify force flag if not doing nonbonded */
- if (!fr->bNonbonded)
- {
- legacyFlags &= ~GMX_FORCE_NONBONDED;
- }
-
const SimulationWorkload& simulationWork = runScheduleWork->simulationWork;
const bool useGpuPmeOnThisRank = simulationWork.useGpuPme && thisRankHasDuty(cr, DUTY_PME);
- const int pmeFlags = makePmeFlags(stepWork);
-
- // Switches on whether to use GPU for position and force buffer operations
- // TODO consider all possible combinations of triggers, and how to combine optimally in each case.
- const BufferOpsUseGpu useGpuXBufOps =
- stepWork.useGpuXBufferOps ? BufferOpsUseGpu::True : BufferOpsUseGpu::False;
- // GPU Force buffer ops are disabled on virial steps, because the virial calc is not yet ported to GPU
- const BufferOpsUseGpu useGpuFBufOps =
- stepWork.useGpuFBufferOps ? BufferOpsUseGpu::True : BufferOpsUseGpu::False;
/* At a search step we need to start the first balancing region
* somewhere early inside the step after communication during domain
ddBalanceRegionHandler.openBeforeForceComputationCpu(DdAllowBalanceRegionReopen::yes);
}
- const int start = 0;
- const int homenr = mdatoms->homenr;
-
clear_mat(vir_force);
- if (stepWork.stateChanged)
- {
- if (inputrecNeedMutot(inputrec))
- {
- /* Calculate total (local) dipole moment in a temporary common array.
- * This makes it possible to sum them over nodes faster.
- */
- calc_mu(start, homenr, x.unpaddedArrayRef(), mdatoms->chargeA, mdatoms->chargeB,
- mdatoms->nChargePerturbed, mu, mu + DIM);
- }
- }
-
- if (fr->ePBC != epbcNONE)
+ if (fr->pbcType != PbcType::No)
{
/* Compute shift vectors every step,
* because of pressure coupling or box deformation!
const bool calcCGCM = (fillGrid && !DOMAINDECOMP(cr));
if (calcCGCM)
{
- put_atoms_in_box_omp(fr->ePBC, box, x.unpaddedArrayRef().subArray(0, homenr),
+ put_atoms_in_box_omp(fr->pbcType, box, x.unpaddedArrayRef().subArray(0, mdatoms->homenr),
gmx_omp_nthreads_get(emntDefault));
- inc_nrnb(nrnb, eNR_SHIFTX, homenr);
- }
- else if (EI_ENERGY_MINIMIZATION(inputrec->eI) && graph)
- {
- unshift_self(graph, box, as_rvec_array(x.unpaddedArrayRef().data()));
+ inc_nrnb(nrnb, eNR_SHIFTX, mdatoms->homenr);
}
}
nbnxn_atomdata_copy_shiftvec(stepWork.haveDynamicBox, fr->shift_vec, nbv->nbat.get());
-#if GMX_MPI
const bool pmeSendCoordinatesFromGpu =
- simulationWork.useGpuPmePpCommunication && !(stepWork.doNeighborSearch);
+ GMX_MPI && simulationWork.useGpuPmePpCommunication && !(stepWork.doNeighborSearch);
const bool reinitGpuPmePpComms =
- simulationWork.useGpuPmePpCommunication && (stepWork.doNeighborSearch);
-#endif
+ GMX_MPI && simulationWork.useGpuPmePpCommunication && (stepWork.doNeighborSearch);
- const auto localXReadyOnDevice = (stateGpu != nullptr)
+ const auto localXReadyOnDevice = (useGpuPmeOnThisRank || simulationWork.useGpuBufferOps)
? stateGpu->getCoordinatesReadyOnDeviceEvent(
AtomLocality::Local, simulationWork, stepWork)
: nullptr;
-#if GMX_MPI
// If coordinates are to be sent to PME task from CPU memory, perform that send here.
// Otherwise the send will occur after H2D coordinate transfer.
- if (!thisRankHasDuty(cr, DUTY_PME) && !pmeSendCoordinatesFromGpu)
+ if (GMX_MPI && !thisRankHasDuty(cr, DUTY_PME) && !pmeSendCoordinatesFromGpu)
{
- /* Send particle coordinates to the pme nodes.
- * Since this is only implemented for domain decomposition
- * and domain decomposition does not use the graph,
- * we do not need to worry about shifting.
- */
+ /* Send particle coordinates to the pme nodes */
if (!stepWork.doNeighborSearch && simulationWork.useGpuUpdate)
{
GMX_RELEASE_ASSERT(false,
step, simulationWork.useGpuPmePpCommunication, reinitGpuPmePpComms,
pmeSendCoordinatesFromGpu, localXReadyOnDevice, wcycle);
}
-#endif /* GMX_MPI */
// Coordinates on the device are needed if PME or BufferOps are offloaded.
// The local coordinates can be copied right away.
// NOTE: Consider moving this copy to right after they are updated and constrained,
// if the later is not offloaded.
- if (useGpuPmeOnThisRank || useGpuXBufOps == BufferOpsUseGpu::True)
+ if (useGpuPmeOnThisRank || stepWork.useGpuXBufferOps)
{
if (stepWork.doNeighborSearch)
{
+ // TODO refactor this to do_md, after partitioning.
stateGpu->reinit(mdatoms->homenr,
cr->dd != nullptr ? dd_numAtomsZones(*cr->dd) : mdatoms->homenr);
if (useGpuPmeOnThisRank)
// The conditions for gpuHaloExchange e.g. using GPU buffer
// operations were checked before construction, so here we can
// just use it and assert upon any conditions.
- gmx::GpuHaloExchange* gpuHaloExchange =
- (havePPDomainDecomposition(cr) ? cr->dd->gpuHaloExchange.get() : nullptr);
- const bool ddUsesGpuDirectCommunication = (gpuHaloExchange != nullptr);
- GMX_ASSERT(!ddUsesGpuDirectCommunication || (useGpuXBufOps == BufferOpsUseGpu::True),
+ const bool ddUsesGpuDirectCommunication =
+ ((cr->dd != nullptr) && (!cr->dd->gpuHaloExchange.empty()));
+ GMX_ASSERT(!ddUsesGpuDirectCommunication || stepWork.useGpuXBufferOps,
"Must use coordinate buffer ops with GPU halo exchange");
- const bool useGpuForcesHaloExchange =
- ddUsesGpuDirectCommunication && (useGpuFBufOps == BufferOpsUseGpu::True);
+ const bool useGpuForcesHaloExchange = ddUsesGpuDirectCommunication && stepWork.useGpuFBufferOps;
// Copy coordinate from the GPU if update is on the GPU and there
// are forces to be computed on the CPU, or for the computation of
haveCopiedXFromGpu = true;
}
-#if GMX_MPI
// If coordinates are to be sent to PME task from GPU memory, perform that send here.
// Otherwise the send will occur before the H2D coordinate transfer.
if (!thisRankHasDuty(cr, DUTY_PME) && pmeSendCoordinatesFromGpu)
{
- /* Send particle coordinates to the pme nodes.
- * Since this is only implemented for domain decomposition
- * and domain decomposition does not use the graph,
- * we do not need to worry about shifting.
- */
+ /* Send particle coordinates to the pme nodes */
gmx_pme_send_coordinates(fr, cr, box, as_rvec_array(x.unpaddedArrayRef().data()), lambda[efptCOUL],
lambda[efptVDW], (stepWork.computeVirial || stepWork.computeEnergy),
step, simulationWork.useGpuPmePpCommunication, reinitGpuPmePpComms,
pmeSendCoordinatesFromGpu, localXReadyOnDevice, wcycle);
}
-#endif /* GMX_MPI */
if (useGpuPmeOnThisRank)
{
- launchPmeGpuSpread(fr->pmedata, box, stepWork, pmeFlags, localXReadyOnDevice, wcycle);
+ launchPmeGpuSpread(fr->pmedata, box, stepWork, localXReadyOnDevice, wcycle);
}
/* do gridding for pair search */
if (stepWork.doNeighborSearch)
{
- if (graph && stepWork.stateChanged)
+ if (fr->wholeMoleculeTransform && stepWork.stateChanged)
{
- /* Calculate intramolecular shift vectors to make molecules whole */
- mk_mshift(fplog, graph, fr->ePBC, box, as_rvec_array(x.unpaddedArrayRef().data()));
+ fr->wholeMoleculeTransform->updateForAtomPbcJumps(x.unpaddedArrayRef(), box);
}
// TODO
}
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
- }
- if (stepWork.doNeighborSearch)
- {
// Need to run after the GPU-offload bonded interaction lists
// are set up to be able to determine whether there is bonded work.
runScheduleWork->domainWork = setupDomainLifetimeWorkload(
wallcycle_start_nocount(wcycle, ewcNS);
wallcycle_sub_start(wcycle, ewcsNBS_SEARCH_LOCAL);
/* Note that with a GPU the launch overhead of the list transfer is not timed separately */
- nbv->constructPairlist(InteractionLocality::Local, &top->excls, step, nrnb);
+ nbv->constructPairlist(InteractionLocality::Local, top->excls, step, nrnb);
nbv->setupGpuShortRangeWork(fr->gpuBonded, InteractionLocality::Local);
wallcycle_sub_stop(wcycle, ewcsNBS_SEARCH_LOCAL);
wallcycle_stop(wcycle, ewcNS);
- if (useGpuXBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuXBufferOps)
{
nbv->atomdata_init_copy_x_to_nbat_x_gpu();
}
// For force buffer ops, we use the below conditon rather than
- // useGpuFBufOps to ensure that init is performed even if this
+ // useGpuFBufferOps to ensure that init is performed even if this
// NS step is also a virial step (on which f buf ops are deactivated).
if (simulationWork.useGpuBufferOps && simulationWork.useGpuNonbonded && (GMX_GPU == GMX_GPU_CUDA))
{
}
else if (!EI_TPI(inputrec->eI))
{
- if (useGpuXBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuXBufferOps)
{
GMX_ASSERT(stateGpu, "stateGpu should be valid when buffer ops are offloaded");
nbv->convertCoordinatesGpu(AtomLocality::Local, false, stateGpu->getCoordinates(),
wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_NONBONDED);
Nbnxm::gpu_upload_shiftvec(nbv->gpu_nbv, nbv->nbat.get());
- if (stepWork.doNeighborSearch || (useGpuXBufOps == BufferOpsUseGpu::False))
+ if (stepWork.doNeighborSearch || !stepWork.useGpuXBufferOps)
{
Nbnxm::gpu_copy_xq_to_gpu(nbv->gpu_nbv, nbv->nbat.get(), AtomLocality::Local);
}
if (domainWork.haveGpuBondedWork && !havePPDomainDecomposition(cr))
{
wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_BONDED);
- fr->gpuBonded->launchKernel(fr, stepWork, box);
+ fr->gpuBonded->setPbcAndlaunchKernel(fr->pbcType, box, fr->bMolPBC, stepWork);
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_BONDED);
}
// X copy/transform to allow overlap as well as after the GPU NB
// launch to avoid FFT launch overhead hijacking the CPU and delaying
// the nonbonded kernel.
- launchPmeGpuFftAndGather(fr->pmedata, wcycle);
+ launchPmeGpuFftAndGather(fr->pmedata, wcycle, stepWork);
}
/* Communicate coordinates and sum dipole if necessary +
wallcycle_start_nocount(wcycle, ewcNS);
wallcycle_sub_start(wcycle, ewcsNBS_SEARCH_NONLOCAL);
/* Note that with a GPU the launch overhead of the list transfer is not timed separately */
- nbv->constructPairlist(InteractionLocality::NonLocal, &top->excls, step, nrnb);
+ nbv->constructPairlist(InteractionLocality::NonLocal, top->excls, step, nrnb);
nbv->setupGpuShortRangeWork(fr->gpuBonded, InteractionLocality::NonLocal);
wallcycle_sub_stop(wcycle, ewcsNBS_SEARCH_NONLOCAL);
wallcycle_stop(wcycle, ewcNS);
+ // TODO refactor this GPU halo exchange re-initialisation
+ // to location in do_md where GPU halo exchange is
+ // constructed at partitioning, after above stateGpu
+ // re-initialization has similarly been refactored
if (ddUsesGpuDirectCommunication)
{
- gpuHaloExchange->reinitHalo(stateGpu->getCoordinates(), stateGpu->getForces());
+ reinitGpuHaloExchange(*cr, stateGpu->getCoordinates(), stateGpu->getForces());
}
}
else
{
// The following must be called after local setCoordinates (which records an event
// when the coordinate data has been copied to the device).
- gpuHaloExchange->communicateHaloCoordinates(box, localXReadyOnDevice);
+ communicateGpuHaloCoordinates(*cr, box, localXReadyOnDevice);
if (domainWork.haveCpuBondedWork || domainWork.haveFreeEnergyWork)
{
dd_move_x(cr->dd, box, x.unpaddedArrayRef(), wcycle);
}
- if (useGpuXBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuXBufferOps)
{
- // The condition here was (pme != nullptr && pme_gpu_get_device_x(fr->pmedata) != nullptr)
if (!useGpuPmeOnThisRank && !ddUsesGpuDirectCommunication)
{
stateGpu->copyCoordinatesToGpu(x.unpaddedArrayRef(), AtomLocality::NonLocal);
{
wallcycle_start(wcycle, ewcLAUNCH_GPU);
- if (stepWork.doNeighborSearch || (useGpuXBufOps == BufferOpsUseGpu::False))
+ if (stepWork.doNeighborSearch || !stepWork.useGpuXBufferOps)
{
wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_NONBONDED);
Nbnxm::gpu_copy_xq_to_gpu(nbv->gpu_nbv, nbv->nbat.get(), AtomLocality::NonLocal);
if (domainWork.haveGpuBondedWork)
{
wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_BONDED);
- fr->gpuBonded->launchKernel(fr, stepWork, box);
+ fr->gpuBonded->setPbcAndlaunchKernel(fr->pbcType, box, fr->bMolPBC, stepWork);
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_BONDED);
}
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
- if (stepWork.stateChanged && inputrecNeedMutot(inputrec))
+ gmx::ArrayRef<const gmx::RVec> xWholeMolecules;
+ if (fr->wholeMoleculeTransform)
{
- if (PAR(cr))
- {
- gmx_sumd(2 * DIM, mu, cr);
+ xWholeMolecules = fr->wholeMoleculeTransform->wholeMoleculeCoordinates(x.unpaddedArrayRef(), box);
+ }
- ddBalanceRegionHandler.reopenRegionCpu();
- }
+ DipoleData dipoleData;
- for (i = 0; i < 2; i++)
- {
- for (j = 0; j < DIM; j++)
- {
- fr->mu_tot[i][j] = mu[i * DIM + j];
- }
- }
- }
- if (mdatoms->nChargePerturbed == 0)
- {
- copy_rvec(fr->mu_tot[0], mu_tot);
- }
- else
+ if (simulationWork.computeMuTot)
{
- for (j = 0; j < DIM; j++)
- {
- mu_tot[j] = (1.0 - lambda[efptCOUL]) * fr->mu_tot[0][j] + lambda[efptCOUL] * fr->mu_tot[1][j];
- }
+ const int start = 0;
+
+ /* Calculate total (local) dipole moment in a temporary common array.
+ * This makes it possible to sum them over nodes faster.
+ */
+ gmx::ArrayRef<const gmx::RVec> xRef =
+ (xWholeMolecules.empty() ? x.unpaddedArrayRef() : xWholeMolecules);
+ calc_mu(start, mdatoms->homenr, xRef, mdatoms->chargeA, mdatoms->chargeB,
+ mdatoms->nChargePerturbed, dipoleData.muStaging[0], dipoleData.muStaging[1]);
+
+ reduceAndUpdateMuTot(&dipoleData, cr, (fr->efep != efepNO), lambda, muTotal, ddBalanceRegionHandler);
}
/* Reset energies */
}
}
- /* update QMMMrec, if necessary */
- if (fr->bQMMM)
- {
- update_QMMMrec(cr, fr, as_rvec_array(x.unpaddedArrayRef().data()), mdatoms, box);
- }
-
// TODO Force flags should include haveFreeEnergyWork for this domain
if (ddUsesGpuDirectCommunication && (domainWork.haveCpuBondedWork || domainWork.haveFreeEnergyWork))
{
stateGpu->waitCoordinatesReadyOnHost(AtomLocality::NonLocal);
}
/* Compute the bonded and non-bonded energies and optionally forces */
- do_force_lowlevel(fr, inputrec, &(top->idef), cr, ms, nrnb, wcycle, mdatoms, x, hist, &forceOut, enerd,
- fcd, box, lambda.data(), graph, fr->mu_tot, stepWork, ddBalanceRegionHandler);
+ do_force_lowlevel(fr, inputrec, top->idef, cr, ms, nrnb, wcycle, mdatoms, x, xWholeMolecules,
+ hist, &forceOut, enerd, fcd, box, lambda.data(),
+ as_rvec_array(dipoleData.muStateAB), stepWork, ddBalanceRegionHandler);
wallcycle_stop(wcycle, ewcFORCE);
wallcycle_stop(wcycle, ewcFORCE);
}
- if (useGpuFBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuFBufferOps)
{
gmx::FixedCapacityVector<GpuEventSynchronizer*, 1> dependencyList;
stateGpu->copyForcesToGpu(forceOut.forceWithShiftForces().force(),
AtomLocality::NonLocal);
dependencyList.push_back(stateGpu->getForcesReadyOnDeviceEvent(
- AtomLocality::NonLocal, useGpuFBufOps == BufferOpsUseGpu::True));
+ AtomLocality::NonLocal, stepWork.useGpuFBufferOps));
}
nbv->atomdata_add_nbat_f_to_f_gpu(AtomLocality::NonLocal, stateGpu->getForces(),
{
stateGpu->copyForcesToGpu(forceOut.forceWithShiftForces().force(), AtomLocality::Local);
}
- gpuHaloExchange->communicateHaloForces(domainWork.haveCpuLocalForceWork);
+ communicateGpuHaloForces(*cr, domainWork.haveCpuLocalForceWork);
}
else
{
- if (useGpuFBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuFBufferOps)
{
stateGpu->waitForcesReadyOnHost(AtomLocality::NonLocal);
}
// With both nonbonded and PME offloaded a GPU on the same rank, we use
// an alternating wait/reduction scheme.
bool alternateGpuWait = (!c_disableAlternatingWait && useGpuPmeOnThisRank && simulationWork.useGpuNonbonded
- && !DOMAINDECOMP(cr) && (useGpuFBufOps == BufferOpsUseGpu::False));
+ && !DOMAINDECOMP(cr) && !stepWork.useGpuFBufferOps);
if (alternateGpuWait)
{
- alternatePmeNbGpuWaitReduce(fr->nbv.get(), fr->pmedata, &forceOut, enerd, stepWork, pmeFlags, wcycle);
+ alternatePmeNbGpuWaitReduce(fr->nbv.get(), fr->pmedata, &forceOut, enerd, stepWork, wcycle);
}
if (!alternateGpuWait && useGpuPmeOnThisRank)
{
- pme_gpu_wait_and_reduce(fr->pmedata, pmeFlags, wcycle, &forceOut.forceWithVirial(), enerd);
+ pme_gpu_wait_and_reduce(fr->pmedata, stepWork, wcycle, &forceOut.forceWithVirial(), enerd);
}
/* Wait for local GPU NB outputs on the non-alternating wait path */
gmx::ArrayRef<gmx::RVec> forceWithShift = forceOut.forceWithShiftForces().force();
- if (useGpuFBufOps == BufferOpsUseGpu::True)
+ if (stepWork.useGpuFBufferOps)
{
// Flag to specify whether the CPU force buffer has contributions to
// local atoms. This depends on whether there are CPU-based force tasks
auto locality = havePPDomainDecomposition(cr) ? AtomLocality::Local : AtomLocality::All;
stateGpu->copyForcesToGpu(forceWithShift, locality);
- dependencyList.push_back(stateGpu->getForcesReadyOnDeviceEvent(
- locality, useGpuFBufOps == BufferOpsUseGpu::True));
+ dependencyList.push_back(
+ stateGpu->getForcesReadyOnDeviceEvent(locality, stepWork.useGpuFBufferOps));
}
if (useGpuForcesHaloExchange)
{
- dependencyList.push_back(gpuHaloExchange->getForcesReadyOnDeviceEvent());
+ dependencyList.push_back(cr->dd->gpuHaloExchange[0]->getForcesReadyOnDeviceEvent());
}
nbv->atomdata_add_nbat_f_to_f_gpu(AtomLocality::Local, stateGpu->getForces(), pmeForcePtr,
dependencyList, stepWork.useGpuPmeFReduction,
}
launchGpuEndOfStepTasks(nbv, fr->gpuBonded, fr->pmedata, enerd, *runScheduleWork,
- simulationWork.useGpuNonbonded, useGpuPmeOnThisRank, step, wcycle);
+ useGpuPmeOnThisRank, step, wcycle);
if (DOMAINDECOMP(cr))
{
{
rvec* fshift = as_rvec_array(forceOut.forceWithShiftForces().shiftForces().data());
spread_vsite_f(vsite, as_rvec_array(x.unpaddedArrayRef().data()), f, fshift, FALSE,
- nullptr, nrnb, &top->idef, fr->ePBC, fr->bMolPBC, graph, box, cr, wcycle);
+ nullptr, nrnb, top->idef, fr->pbcType, fr->bMolPBC, box, cr, wcycle);
}
if (stepWork.computeVirial)
{
/* Calculation of the virial must be done after vsites! */
calc_virial(0, mdatoms->homenr, as_rvec_array(x.unpaddedArrayRef().data()),
- forceOut.forceWithShiftForces(), vir_force, graph, box, nrnb, fr, inputrec->ePBC);
+ forceOut.forceWithShiftForces(), vir_force, box, nrnb, fr, inputrec->pbcType);
}
}
if (stepWork.computeForces)
{
post_process_forces(cr, step, nrnb, wcycle, top, box, as_rvec_array(x.unpaddedArrayRef().data()),
- &forceOut, vir_force, mdatoms, graph, fr, vsite, stepWork);
+ &forceOut, vir_force, mdatoms, fr, vsite, stepWork);
}
if (stepWork.computeEnergy)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_sum_sim(eglsNR, mpiBuffer_.data(), ms_);
}
// Communicate the signals from the master to the others.
- gmx_bcast(eglsNR * sizeof(mpiBuffer_[0]), mpiBuffer_.data(), cr_);
+ gmx_bcast(eglsNR * sizeof(mpiBuffer_[0]), mpiBuffer_.data(), cr_->mpi_comm_mygroup);
}
void SimulationSignaller::setSignals()
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-static int mk_grey(egCol egc[], t_graph* g, int* AtomI, int maxsid, t_sid sid[])
+static int mk_grey(gmx::ArrayRef<egCol> edgeColor, const t_graph* g, int* AtomI, int maxsid, t_sid sid[])
{
- int j, ng, ai, aj, g0;
+ int ng, ai, g0;
ng = 0;
ai = *AtomI;
- g0 = g->at_start;
+ g0 = g->edgeAtomBegin;
/* Loop over all the bonds */
- for (j = 0; (j < g->nedge[ai]); j++)
+ for (int aj : g->edges[ai])
{
- aj = g->edge[ai][j] - g0;
+ aj -= g0;
/* If there is a white one, make it gray and set pbc */
- if (egc[aj] == egcolWhite)
+ if (edgeColor[aj] == egcolWhite)
{
if (aj < *AtomI)
{
*AtomI = aj;
}
- egc[aj] = egcolGrey;
+ edgeColor[aj] = egcolGrey;
/* Check whether this one has been set before... */
range_check(aj + g0, 0, maxsid);
return ng;
}
-static int first_colour(int fC, egCol Col, t_graph* g, const egCol egc[])
+static int first_colour(const int fC, const egCol Col, const t_graph* g, gmx::ArrayRef<const egCol> edgeColor)
/* Return the first node with colour Col starting at fC.
* return -1 if none found.
*/
{
int i;
- for (i = fC; (i < g->nnodes); i++)
+ for (i = fC; i < int(g->edges.size()); i++)
{
- if ((g->nedge[i] > 0) && (egc[i] == Col))
+ if (!g->edges[i].empty() && edgeColor[i] == Col)
{
return i;
}
static int mk_sblocks(FILE* fp, t_graph* g, int maxsid, t_sid sid[])
{
- int ng, nnodes;
- int nW, nG, nB; /* Number of Grey, Black, White */
- int fW, fG; /* First of each category */
- egCol* egc = nullptr; /* The colour of each node */
- int g0, nblock;
+ int ng;
+ int nW, nG, nB; /* Number of Grey, Black, White */
+ int fW, fG; /* First of each category */
+ int g0, nblock;
- if (!g->nbound)
+ if (!g->numConnectedAtoms)
{
return 0;
}
nblock = 0;
- nnodes = g->nnodes;
- snew(egc, nnodes);
+ std::vector<egCol> edgeColor(g->edges.size(), egcolWhite);
- g0 = g->at_start;
- nW = g->nbound;
+ g0 = g->edgeAtomBegin;
+ nW = g->numConnectedAtoms;
nG = 0;
nB = 0;
* number than before, because no nodes are made white
* in the loop
*/
- if ((fW = first_colour(fW, egcolWhite, g, egc)) == -1)
+ if ((fW = first_colour(fW, egcolWhite, g, edgeColor)) == -1)
{
gmx_fatal(FARGS, "No WHITE nodes found while nW=%d\n", nW);
}
/* Make the first white node grey, and set the block number */
- egc[fW] = egcolGrey;
+ edgeColor[fW] = egcolGrey;
range_check(fW + g0, 0, maxsid);
sid[fW + g0].sid = nblock++;
nG++;
while (nG > 0)
{
- if ((fG = first_colour(fG, egcolGrey, g, egc)) == -1)
+ if ((fG = first_colour(fG, egcolGrey, g, edgeColor)) == -1)
{
gmx_fatal(FARGS, "No GREY nodes found while nG=%d\n", nG);
}
/* Make the first grey node black */
- egc[fG] = egcolBlack;
+ edgeColor[fG] = egcolBlack;
nB++;
nG--;
/* Make all the neighbours of this black node grey
* and set their block number
*/
- ng = mk_grey(egc, g, &fG, maxsid, sid);
+ ng = mk_grey(edgeColor, g, &fG, maxsid, sid);
/* ng is the number of white nodes made grey */
nG += ng;
nW -= ng;
}
}
- sfree(egc);
if (debug)
{
return nsid;
}
-void gen_sblocks(FILE* fp, int at_start, int at_end, const t_idef* idef, t_blocka* sblock, gmx_bool bSettle)
+void gen_sblocks(FILE* fp, int at_end, const InteractionDefinitions& idef, t_blocka* sblock, gmx_bool bSettle)
{
t_graph* g;
int i, i0;
t_sid* sid;
int nsid;
- g = mk_graph(nullptr, idef, at_start, at_end, TRUE, bSettle);
+ g = mk_graph(nullptr, idef, at_end, TRUE, bSettle);
if (debug)
{
p_graph(debug, "Graaf Dracula", g);
}
snew(sid, at_end);
- for (i = at_start; (i < at_end); i++)
+ for (i = 0; i < at_end; i++)
{
sid[i].atom = i;
sid[i].sid = -1;
}
/* Now sort the shake blocks... */
- std::sort(sid + at_start, sid + at_end, sid_comp);
+ std::sort(sid, sid + at_end, sid_comp);
if (debug)
{
fprintf(debug, "Sorted shake block\n");
- for (i = at_start; (i < at_end); i++)
+ for (i = 0; i < at_end; i++)
{
fprintf(debug, "sid[%5d] = atom:%5d sid:%5d\n", i, sid[i].atom, sid[i].sid);
}
}
/* Now check how many are NOT -1, i.e. how many have to be shaken */
- for (i0 = at_start; (i0 < at_end); i0++)
+ for (i0 = 0; i0 < at_end; i0++)
{
if (sid[i0].sid > -1)
{
* part of the shake block too. There may be cases where blocks overlap
* and they will have to be merged.
*/
- merge_sid(at_start, at_end, nsid, sid, sblock);
+ merge_sid(0, at_end, nsid, sid, sblock);
sfree(sid);
/* Due to unknown reason this free generates a problem sometimes */
done_graph(g);
- sfree(g);
if (debug)
{
fprintf(debug, "Done gen_sblocks\n");
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
+class InteractionDefinitions;
struct t_blocka;
-struct t_idef;
-void gen_sblocks(FILE* fp, int at_start, int at_end, const t_idef* idef, t_blocka* sblock, gmx_bool bSettle);
+void gen_sblocks(FILE* fp, int at_end, const InteractionDefinitions& idef, t_blocka* sblock, gmx_bool bSettle);
/* Generate shake blocks from the constraint list. Set bSettle to yes for shake
* blocks including settles. You normally do not want this.
*/
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_enerdata_t* enerd,
tensor fvir,
tensor svir,
- rvec mu_tot,
const t_inputrec* inputrec,
gmx_ekindata_t* ekind,
const gmx::Constraints* constr,
{
t_bin* rb;
int * itc0, *itc1;
- int ie = 0, ifv = 0, isv = 0, irmsd = 0, imu = 0;
+ int ie = 0, ifv = 0, isv = 0, irmsd = 0;
int idedl = 0, idedlo = 0, idvdll = 0, idvdlnl = 0, iepl = 0, icm = 0, imass = 0, ica = 0, inb = 0;
int isig = -1;
int icj = -1, ici = -1, icx = -1;
irmsd = add_binr(rb, 2, rmsdData.data());
}
}
- if (!inputrecNeedMutot(inputrec))
- {
- imu = add_binr(rb, DIM, mu_tot);
- }
for (j = 0; (j < egNR); j++)
{
{
extract_binr(rb, irmsd, rmsdData);
}
- if (!inputrecNeedMutot(inputrec))
- {
- extract_binr(rb, imu, DIM, mu_tot);
- }
for (j = 0; (j < egNR); j++)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_enerdata_t* enerd,
tensor fvir,
tensor svir,
- rvec mu_tot,
const t_inputrec* inputrec,
gmx_ekindata_t* ekind,
const gmx::Constraints* constr,
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(MdlibUnitTest mdlib-test
- calc_verletbuf.cpp
- constr.cpp
- constrtestdata.cpp
- constrtestrunners.cpp
- ebin.cpp
- energyoutput.cpp
- leapfrog.cpp
- leapfrogtestdata.cpp
- leapfrogtestrunners.cpp
- settle.cpp
- settletestdata.cpp
- settletestrunners.cpp
- shake.cpp
- simulationsignal.cpp
- updategroups.cpp
- updategroupscog.cpp)
-
-# TODO: Make CUDA source to compile inside the testing framework
-if(GMX_USE_CUDA)
- gmx_add_libgromacs_sources(constrtestrunners.cu
- leapfrogtestrunners.cu
- settletestrunners.cu)
-endif()
+ CPP_SOURCE_FILES
+ calc_verletbuf.cpp
+ constr.cpp
+ constrtestdata.cpp
+ constrtestrunners.cpp
+ ebin.cpp
+ energyoutput.cpp
+ leapfrog.cpp
+ leapfrogtestdata.cpp
+ leapfrogtestrunners.cpp
+ settle.cpp
+ settletestdata.cpp
+ settletestrunners.cpp
+ shake.cpp
+ simulationsignal.cpp
+ updategroups.cpp
+ updategroupscog.cpp
+ CUDA_CU_SOURCE_FILES
+ constrtestrunners.cu
+ leapfrogtestrunners.cu
+ settletestrunners.cu
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
runnersNames.emplace_back("LINCS");
if (GMX_GPU == GMX_GPU_CUDA && canComputeOnGpu())
{
- runnersNames.emplace_back("LINCS_CUDA");
+ runnersNames.emplace_back("LINCS_GPU");
}
return runnersNames;
}
// Infinitely small box
matrix boxNone = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
- set_pbc(&pbc, epbcNONE, boxNone);
+ set_pbc(&pbc, PbcType::No, boxNone);
pbcs_["PBCNone"] = pbc;
// Rectangular box
matrix boxXyz = { { 10.0, 0.0, 0.0 }, { 0.0, 20.0, 0.0 }, { 0.0, 0.0, 15.0 } };
- set_pbc(&pbc, epbcXYZ, boxXyz);
+ set_pbc(&pbc, PbcType::Xyz, boxXyz);
pbcs_["PBCXYZ"] = pbc;
//
algorithms_["SHAKE"] = applyShake;
// LINCS
algorithms_["LINCS"] = applyLincs;
- // LINCS using CUDA (will only be called if CUDA is available)
- algorithms_["LINCS_CUDA"] = applyLincsCuda;
+ // LINCS using GPU (will only be called if GPU is available)
+ algorithms_["LINCS_GPU"] = applyLincsGpu;
}
/*! \brief
* \param[in] testData Test data structure.
* \param[in] pbc Periodic boundary data.
*/
- void checkConstrainsLength(FloatingPointTolerance tolerance, const ConstraintsTestData& testData, t_pbc pbc)
+ static void checkConstrainsLength(FloatingPointTolerance tolerance,
+ const ConstraintsTestData& testData,
+ t_pbc pbc)
{
// Test if all the constraints are satisfied
int j = testData.constraints_.at(3 * c + 2);
RVec xij0, xij1;
real d0, d1;
- if (pbc.ePBC == epbcXYZ)
+ if (pbc.pbcType == PbcType::Xyz)
{
pbc_dx_aiuc(&pbc, testData.x_[i], testData.x_[j], xij0);
pbc_dx_aiuc(&pbc, testData.xPrime_[i], testData.xPrime_[j], xij1);
* \param[in] testData Test data structure.
* \param[in] pbc Periodic boundary data.
*/
- void checkConstrainsDirection(const ConstraintsTestData& testData, t_pbc pbc)
+ static void checkConstrainsDirection(const ConstraintsTestData& testData, t_pbc pbc)
{
for (index c = 0; c < ssize(testData.constraints_) / 3; c++)
int i = testData.constraints_.at(3 * c + 1);
int j = testData.constraints_.at(3 * c + 2);
RVec xij0, xij1;
- if (pbc.ePBC == epbcXYZ)
+ if (pbc.pbcType == PbcType::Xyz)
{
pbc_dx_aiuc(&pbc, testData.x_[i], testData.x_[j], xij0);
pbc_dx_aiuc(&pbc, testData.xPrime_[i], testData.xPrime_[j], xij1);
* \param[in] tolerance Allowed tolerance in COM coordinates.
* \param[in] testData Test data structure.
*/
- void checkCOMCoordinates(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
+ static void checkCOMCoordinates(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
{
RVec comPrime0({ 0.0, 0.0, 0.0 });
* \param[in] tolerance Allowed tolerance in COM velocity components.
* \param[in] testData Test data structure.
*/
- void checkCOMVelocity(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
+ static void checkCOMVelocity(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
{
RVec comV0({ 0.0, 0.0, 0.0 });
* \param[in] tolerance Tolerance for the tensor values.
* \param[in] testData Test data structure.
*/
- void checkVirialTensor(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
+ static void checkVirialTensor(FloatingPointTolerance tolerance, const ConstraintsTestData& testData)
{
for (int i = 0; i < DIM; i++)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
invdt_ = 1.0 / timestep; // Inverse timestep
- // Communication record
- cr_.nnodes = 1;
- cr_.dd = nullptr;
-
- // Multisim data
- ms_.sim = 0;
- ms_.nsim = 1;
-
// Input record - data that usually comes from configuration file (.mdp)
ir_.efep = 0;
ir_.init_t = initialTime;
dHdLambdaRef_ = 0;
}
- // Constraints and their parameters (local topology)
- for (int i = 0; i < F_NRE; i++)
- {
- idef_.il[i].nr = 0;
- }
- idef_.il[F_CONSTR].nr = constraints.size();
-
- snew(idef_.il[F_CONSTR].iatoms, constraints.size());
int maxType = 0;
- for (index i = 0; i < ssize(constraints); i++)
+ for (index i = 0; i < ssize(constraints); i += 3)
{
- if (i % 3 == 0)
+ if (maxType < constraints.at(i))
{
- if (maxType < constraints.at(i))
- {
- maxType = constraints.at(i);
- }
+ maxType = constraints.at(i);
}
- idef_.il[F_CONSTR].iatoms[i] = constraints.at(i);
}
- snew(idef_.iparams, maxType + 1);
+ auto& iparams = mtop_.ffparams.iparams;
+ iparams.resize(maxType + 1);
for (index i = 0; i < ssize(constraints) / 3; i++)
{
- idef_.iparams[constraints.at(3 * i)].constr.dA = constraintsR0.at(constraints.at(3 * i));
- idef_.iparams[constraints.at(3 * i)].constr.dB = constraintsR0.at(constraints.at(3 * i));
+ iparams[constraints.at(3 * i)].constr.dA = constraintsR0.at(constraints.at(3 * i));
+ iparams[constraints.at(3 * i)].constr.dB = constraintsR0.at(constraints.at(3 * i));
+ }
+ idef_ = std::make_unique<InteractionDefinitions>(mtop_.ffparams);
+ for (index i = 0; i < ssize(constraints); i++)
+ {
+ idef_->il[F_CONSTR].iatoms.push_back(constraints.at(i));
}
// Constraints and their parameters (global topology)
molBlock.nmol = 1;
mtop_.molblock.push_back(molBlock);
- mtop_.natoms = numAtoms;
- mtop_.ffparams.iparams.resize(maxType + 1);
- for (int i = 0; i <= maxType; i++)
- {
- mtop_.ffparams.iparams.at(i) = idef_.iparams[i];
- }
+ mtop_.natoms = numAtoms;
mtop_.bIntermolecularInteractions = false;
// Coordinates and velocities
dHdLambda_ = 0;
}
-/*! \brief
- * Cleaning up the memory.
- */
-ConstraintsTestData::~ConstraintsTestData()
-{
- sfree(idef_.il[F_CONSTR].iatoms);
- sfree(idef_.iparams);
-}
-
} // namespace test
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_MDLIB_TESTS_CONSTRTESTDATA_H
#define GMX_MDLIB_TESTS_CONSTRTESTDATA_H
+#include <memory>
#include <vector>
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/lincs.h"
#include "gromacs/mdlib/shake.h"
-#include "gromacs/mdrunutility/multisim.h"
-#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
std::vector<real> masses_;
//! Inverse masses
std::vector<real> invmass_;
- //! Communication record
- t_commrec cr_;
//! Input record (info that usually in .mdp file)
t_inputrec ir_;
//! Local topology
- t_idef idef_;
+ std::unique_ptr<InteractionDefinitions> idef_;
//! MD atoms
t_mdatoms md_;
- //! Multisim data
- gmx_multisim_t ms_;
//! Computational time array (normally used to benchmark performance)
t_nrnb nrnb_;
*
*/
void reset();
-
- /*! \brief
- * Cleaning up the memory.
- */
- ~ConstraintsTestData();
};
} // namespace test
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdlib/lincs.h"
#include "gromacs/mdlib/shake.h"
+#include "gromacs/mdrunutility/multisim.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
-#include "gromacs/topology/block.h"
#include "gromacs/topology/idef.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/unique_cptr.h"
#include "testutils/testasserts.h"
*/
void applyShake(ConstraintsTestData* testData, t_pbc gmx_unused pbc)
{
- shakedata* shaked = shake_init();
- make_shake_sblock_serial(shaked, &testData->idef_, testData->md_);
+ shakedata shaked;
+ make_shake_sblock_serial(&shaked, testData->idef_.get(), testData->md_);
bool success = constrain_shake(
- nullptr, shaked, testData->invmass_.data(), testData->idef_, testData->ir_,
- as_rvec_array(testData->x_.data()), as_rvec_array(testData->xPrime_.data()),
- as_rvec_array(testData->xPrime2_.data()), &testData->nrnb_, testData->md_.lambda,
- &testData->dHdLambda_, testData->invdt_, as_rvec_array(testData->v_.data()),
- testData->computeVirial_, testData->virialScaled_, false, gmx::ConstraintVariable::Positions);
+ nullptr, &shaked, testData->invmass_.data(), *testData->idef_, testData->ir_, testData->x_,
+ testData->xPrime_, testData->xPrime2_, nullptr, &testData->nrnb_, testData->md_.lambda,
+ &testData->dHdLambda_, testData->invdt_, testData->v_, testData->computeVirial_,
+ testData->virialScaled_, false, gmx::ConstraintVariable::Positions);
EXPECT_TRUE(success) << "Test failed with a false return value in SHAKE.";
- done_shake(shaked);
}
/*! \brief
int warncount_lincs = 0;
gmx_omp_nthreads_set(emntLINCS, 1);
+ // Communication record
+ t_commrec cr;
+ cr.nnodes = 1;
+ cr.dd = nullptr;
+
+ // Multi-sim record
+ gmx_multisim_t ms;
+
// Make blocka structure for faster LINCS setup
- std::vector<t_blocka> at2con_mt;
+ std::vector<ListOfLists<int>> at2con_mt;
at2con_mt.reserve(testData->mtop_.moltype.size());
for (const gmx_moltype_t& moltype : testData->mtop_.moltype)
{
// Initialize LINCS
lincsd = init_lincs(nullptr, testData->mtop_, testData->nflexcon_, at2con_mt, false,
testData->ir_.nLincsIter, testData->ir_.nProjOrder);
- set_lincs(testData->idef_, testData->md_, EI_DYNAMICS(testData->ir_.eI), &testData->cr_, lincsd);
+ set_lincs(*testData->idef_, testData->md_, EI_DYNAMICS(testData->ir_.eI), &cr, lincsd);
// Evaluate constraints
bool success = constrain_lincs(
- false, testData->ir_, 0, lincsd, testData->md_, &testData->cr_, &testData->ms_,
- as_rvec_array(testData->x_.data()), as_rvec_array(testData->xPrime_.data()),
- as_rvec_array(testData->xPrime2_.data()), pbc.box, &pbc, testData->md_.lambda,
- &testData->dHdLambda_, testData->invdt_, as_rvec_array(testData->v_.data()),
- testData->computeVirial_, testData->virialScaled_, gmx::ConstraintVariable::Positions,
- &testData->nrnb_, maxwarn, &warncount_lincs);
+ false, testData->ir_, 0, lincsd, testData->md_, &cr, &ms,
+ testData->x_.arrayRefWithPadding(), testData->xPrime_.arrayRefWithPadding(),
+ testData->xPrime2_.arrayRefWithPadding().unpaddedArrayRef(), pbc.box, &pbc,
+ testData->md_.lambda, &testData->dHdLambda_, testData->invdt_,
+ testData->v_.arrayRefWithPadding().unpaddedArrayRef(), testData->computeVirial_,
+ testData->virialScaled_, gmx::ConstraintVariable::Positions, &testData->nrnb_, maxwarn,
+ &warncount_lincs);
EXPECT_TRUE(success) << "Test failed with a false return value in LINCS.";
EXPECT_EQ(warncount_lincs, 0) << "There were warnings in LINCS.";
- for (auto& moltype : at2con_mt)
- {
- sfree(moltype.index);
- sfree(moltype.a);
- }
done_lincs(lincsd);
}
#if GMX_GPU != GMX_GPU_CUDA
/*! \brief
- * Stub for LINCS constraints on CUDA-enabled GPU to satisfy compiler.
+ * Stub for GPU version of LINCS constraints to satisfy compiler.
*
* \param[in] testData Test data structure.
* \param[in] pbc Periodic boundary data.
*/
-void applyLincsCuda(ConstraintsTestData gmx_unused* testData, t_pbc gmx_unused pbc)
+void applyLincsGpu(ConstraintsTestData gmx_unused* testData, t_pbc gmx_unused pbc)
{
FAIL() << "Dummy LINCS CUDA function was called instead of the real one.";
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/devicebuffer.cuh"
#include "gromacs/gpu_utils/gpu_utils.h"
-#include "gromacs/mdlib/lincs_cuda.cuh"
+#include "gromacs/mdlib/lincs_gpu.cuh"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/utility/unique_cptr.h"
{
/*! \brief
- * Initialize and apply LINCS constraints on CUDA-enabled GPU.
+ * Initialize and apply LINCS constraints on GPU.
*
* \param[in] testData Test data structure.
* \param[in] pbc Periodic boundary data.
*/
-void applyLincsCuda(ConstraintsTestData* testData, t_pbc pbc)
+void applyLincsGpu(ConstraintsTestData* testData, t_pbc pbc)
{
- auto lincsCuda =
- std::make_unique<LincsCuda>(testData->ir_.nLincsIter, testData->ir_.nProjOrder, nullptr);
+ DeviceInformation deviceInfo;
+ const DeviceContext deviceContext(deviceInfo);
+ const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+
+ auto lincsGpu = std::make_unique<LincsGpu>(testData->ir_.nLincsIter, testData->ir_.nProjOrder,
+ deviceContext, deviceStream);
bool updateVelocities = true;
int numAtoms = testData->numAtoms_;
float3 *d_x, *d_xp, *d_v;
- lincsCuda->set(testData->idef_, testData->md_);
- lincsCuda->setPbc(&pbc);
+ lincsGpu->set(*testData->idef_, testData->md_);
+ PbcAiuc pbcAiuc;
+ setPbcAiuc(pbc.ndim_ePBC, pbc.box, &pbcAiuc);
- allocateDeviceBuffer(&d_x, numAtoms, nullptr);
- allocateDeviceBuffer(&d_xp, numAtoms, nullptr);
- allocateDeviceBuffer(&d_v, numAtoms, nullptr);
+ allocateDeviceBuffer(&d_x, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_xp, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_v, numAtoms, deviceContext);
- copyToDeviceBuffer(&d_x, (float3*)(testData->x_.data()), 0, numAtoms, nullptr,
+ copyToDeviceBuffer(&d_x, (float3*)(testData->x_.data()), 0, numAtoms, deviceStream,
GpuApiCallBehavior::Sync, nullptr);
- copyToDeviceBuffer(&d_xp, (float3*)(testData->xPrime_.data()), 0, numAtoms, nullptr,
+ copyToDeviceBuffer(&d_xp, (float3*)(testData->xPrime_.data()), 0, numAtoms, deviceStream,
GpuApiCallBehavior::Sync, nullptr);
if (updateVelocities)
{
- copyToDeviceBuffer(&d_v, (float3*)(testData->v_.data()), 0, numAtoms, nullptr,
+ copyToDeviceBuffer(&d_v, (float3*)(testData->v_.data()), 0, numAtoms, deviceStream,
GpuApiCallBehavior::Sync, nullptr);
}
- lincsCuda->apply(d_x, d_xp, updateVelocities, d_v, testData->invdt_, testData->computeVirial_,
- testData->virialScaled_);
+ lincsGpu->apply(d_x, d_xp, updateVelocities, d_v, testData->invdt_, testData->computeVirial_,
+ testData->virialScaled_, pbcAiuc);
- copyFromDeviceBuffer((float3*)(testData->xPrime_.data()), &d_xp, 0, numAtoms, nullptr,
+ copyFromDeviceBuffer((float3*)(testData->xPrime_.data()), &d_xp, 0, numAtoms, deviceStream,
GpuApiCallBehavior::Sync, nullptr);
if (updateVelocities)
{
- copyFromDeviceBuffer((float3*)(testData->v_.data()), &d_v, 0, numAtoms, nullptr,
+ copyFromDeviceBuffer((float3*)(testData->v_.data()), &d_v, 0, numAtoms, deviceStream,
GpuApiCallBehavior::Sync, nullptr);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief Apply LINCS constraints to the test data.
*/
void applyLincs(ConstraintsTestData* testData, t_pbc pbc);
-/*! \brief Apply CUDA version of LINCS constraints to the test data.
+/*! \brief Apply GPU version of LINCS constraints to the test data.
*
* All the data is copied to the GPU device, then LINCS is applied and
* the resulting coordinates are copied back.
*/
-void applyLincsCuda(ConstraintsTestData* testData, t_pbc pbc);
+void applyLincsGpu(ConstraintsTestData* testData, t_pbc pbc);
} // namespace test
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \param[in] testData Test data object
* \param[in] totalTime Total numerical integration time
*/
- void testAgainstAnalyticalSolution(FloatingPointTolerance tolerance,
- const LeapFrogTestData& testData,
- const real totalTime)
+ static void testAgainstAnalyticalSolution(FloatingPointTolerance tolerance,
+ const LeapFrogTestData& testData,
+ const real totalTime)
{
for (int i = 0; i < testData.numAtoms_; i++)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
testData->velocityScalingMatrix_, testData->update_.get(), etrtNONE, nullptr,
nullptr);
finish_update(&testData->inputRecord_, &testData->mdAtoms_, &testData->state_, nullptr,
- nullptr, nullptr, testData->update_.get(), nullptr);
+ testData->update_.get(), nullptr);
}
auto xp = makeArrayRef(*testData->update_->xp()).subArray(0, testData->numAtoms_);
for (int i = 0; i < testData->numAtoms_; i++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "leapfrogtestrunners.h"
-#include "config.h"
-
#include <assert.h>
#include <cmath>
#include "gromacs/gpu_utils/devicebuffer.cuh"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/math/vec.h"
-#include "gromacs/mdlib/leapfrog_cuda.cuh"
+#include "gromacs/mdlib/leapfrog_gpu.cuh"
#include "gromacs/mdlib/stat.h"
#include "gromacs/mdtypes/group.h"
namespace test
{
-#if GMX_GPU == GMX_GPU_CUDA
-
void integrateLeapFrogGpu(LeapFrogTestData* testData, int numSteps)
{
+ DeviceInformation deviceInfo;
+ const DeviceContext deviceContext(deviceInfo);
+ const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+
int numAtoms = testData->numAtoms_;
float3* h_x = reinterpret_cast<float3*>(testData->x_.data());
float3 *d_x, *d_xp, *d_v, *d_f;
- allocateDeviceBuffer(&d_x, numAtoms, nullptr);
- allocateDeviceBuffer(&d_xp, numAtoms, nullptr);
- allocateDeviceBuffer(&d_v, numAtoms, nullptr);
- allocateDeviceBuffer(&d_f, numAtoms, nullptr);
+ allocateDeviceBuffer(&d_x, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_xp, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_v, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_f, numAtoms, deviceContext);
- copyToDeviceBuffer(&d_x, h_x, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
- copyToDeviceBuffer(&d_xp, h_xp, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
- copyToDeviceBuffer(&d_v, h_v, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
- copyToDeviceBuffer(&d_f, h_f, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_x, h_x, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_xp, h_xp, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_v, h_v, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_f, h_f, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
- auto integrator = std::make_unique<LeapFrogCuda>(nullptr);
+ auto integrator = std::make_unique<LeapFrogGpu>(deviceContext, deviceStream);
integrator->set(testData->mdAtoms_, testData->numTCoupleGroups_, testData->mdAtoms_.cTC);
testData->dtPressureCouple_, testData->velocityScalingMatrix_);
}
- copyFromDeviceBuffer(h_xp, &d_x, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
- copyFromDeviceBuffer(h_v, &d_v, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyFromDeviceBuffer(h_xp, &d_x, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
+ copyFromDeviceBuffer(h_v, &d_v, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
freeDeviceBuffer(&d_x);
freeDeviceBuffer(&d_xp);
freeDeviceBuffer(&d_f);
}
-#endif // GMX_GPU == GMX_GPU_CUDA
-
} // namespace test
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
void integrateLeapFrogSimple(LeapFrogTestData* testData, int numSteps);
-/*! \brief Integrate using CUDA version of Leap-Frog
+/*! \brief Integrate using GPU version of Leap-Frog
*
* Copies data from CPU to GPU, integrates the equation of motion
* for requested number of steps using Leap-Frog algorithm, copies
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Infinitely small box
matrix boxNone = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
- set_pbc(&pbc, epbcNONE, boxNone);
+ set_pbc(&pbc, PbcType::No, boxNone);
pbcs_["PBCNone"] = pbc;
// Rectangular box
matrix boxXyz = { { real(1.86206), 0, 0 }, { 0, real(1.86206), 0 }, { 0, 0, real(1.86206) } };
- set_pbc(&pbc, epbcXYZ, boxXyz);
+ set_pbc(&pbc, PbcType::Xyz, boxXyz);
pbcs_["PBCXYZ"] = pbc;
//
* \param[in] tolerance Tolerance to compare floating point numbers.
* \param[in] testData An object, containing all the data structures needed by SETTLE.
*/
- void checkConstrainsSatisfied(const int numSettles,
- const FloatingPointTolerance tolerance,
- const SettleTestData& testData)
+ static void checkConstrainsSatisfied(const int numSettles,
+ const FloatingPointTolerance tolerance,
+ const SettleTestData& testData)
{
for (int i = 0; i < numSettles; ++i)
{
* \param[in] tolerance Tolerance to compare floating point numbers.
* \param[in] testData An object, containing all the data structures needed by SETTLE.
*/
- void checkVirialSymmetric(const bool calcVirial,
- const FloatingPointTolerance tolerance,
- const SettleTestData& testData)
+ static void checkVirialSymmetric(const bool calcVirial,
+ const FloatingPointTolerance tolerance,
+ const SettleTestData& testData)
{
for (int d = 0; d < DIM; ++d)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
mtop_.moltype[0].atoms.atom[i * atomsPerSettle_ + 2].m = hydrogenMass_;
}
- // Reshape some data so it can be directly used by the SETTLE constraints
- ilist_ = { mtop_.moltype[0].ilist[F_SETTLE].size(), 0,
- mtop_.moltype[0].ilist[F_SETTLE].iatoms.data(), 0 };
- idef_.il[F_SETTLE] = ilist_;
+ idef_ = std::make_unique<InteractionDefinitions>(mtop_.ffparams);
+ idef_->il[F_SETTLE] = mtop_.moltype[0].ilist[F_SETTLE];
}
SettleTestData::~SettleTestData()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_mtop_t mtop_;
//! Atoms data
t_mdatoms mdatoms_;
- //! Interactions list
- t_ilist ilist_;
//! Local topology
- t_idef idef_;
+ std::unique_ptr<InteractionDefinitions> idef_;
//! Inverse timestep
const real reciprocalTimeStep_ = 1.0 / 0.002;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
settledata* settled = settle_init(testData->mtop_);
- settle_set_constraints(settled, &testData->ilist_, testData->mdatoms_);
+ settle_set_constraints(settled, testData->idef_->il[F_SETTLE], testData->mdatoms_);
bool errorOccured;
int numThreads = 1;
int threadIndex = 0;
- csettle(settled, numThreads, threadIndex, &pbc,
- reinterpret_cast<real*>(as_rvec_array(testData->x_.data())),
- reinterpret_cast<real*>(as_rvec_array(testData->xPrime_.data())), testData->reciprocalTimeStep_,
- updateVelocities ? reinterpret_cast<real*>(as_rvec_array(testData->v_.data())) : nullptr,
+ csettle(settled, numThreads, threadIndex, &pbc, testData->x_.arrayRefWithPadding(),
+ testData->xPrime_.arrayRefWithPadding(), testData->reciprocalTimeStep_,
+ updateVelocities ? testData->v_.arrayRefWithPadding() : ArrayRefWithPadding<RVec>(),
calcVirial, testData->virial_, &errorOccured);
settle_free(settled);
EXPECT_FALSE(errorOccured) << testDescription;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/devicebuffer.cuh"
#include "gromacs/gpu_utils/gpu_utils.h"
-#include "gromacs/mdlib/settle_cuda.cuh"
+#include "gromacs/mdlib/settle_gpu.cuh"
#include "gromacs/utility/unique_cptr.h"
namespace gmx
// TODO: Here we should check that at least 1 suitable GPU is available
GMX_RELEASE_ASSERT(canPerformGpuDetection(), "Can't detect CUDA-capable GPUs.");
- auto settleCuda = std::make_unique<SettleCuda>(testData->mtop_, nullptr);
- settleCuda->setPbc(&pbc);
- settleCuda->set(testData->idef_, testData->mdatoms_);
+ DeviceInformation deviceInfo;
+ const DeviceContext deviceContext(deviceInfo);
+ const DeviceStream deviceStream(deviceContext, DeviceStreamPriority::Normal, false);
+
+ auto settleGpu = std::make_unique<SettleGpu>(testData->mtop_, deviceContext, deviceStream);
+
+ settleGpu->set(*testData->idef_, testData->mdatoms_);
+ PbcAiuc pbcAiuc;
+ setPbcAiuc(pbc.ndim_ePBC, pbc.box, &pbcAiuc);
int numAtoms = testData->mdatoms_.homenr;
float3* h_xp = (float3*)(as_rvec_array(testData->xPrime_.data()));
float3* h_v = (float3*)(as_rvec_array(testData->v_.data()));
- allocateDeviceBuffer(&d_x, numAtoms, nullptr);
- allocateDeviceBuffer(&d_xp, numAtoms, nullptr);
- allocateDeviceBuffer(&d_v, numAtoms, nullptr);
+ allocateDeviceBuffer(&d_x, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_xp, numAtoms, deviceContext);
+ allocateDeviceBuffer(&d_v, numAtoms, deviceContext);
- copyToDeviceBuffer(&d_x, (float3*)h_x, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
- copyToDeviceBuffer(&d_xp, (float3*)h_xp, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_x, (float3*)h_x, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_xp, (float3*)h_xp, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
if (updateVelocities)
{
- copyToDeviceBuffer(&d_v, (float3*)h_v, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyToDeviceBuffer(&d_v, (float3*)h_v, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
}
- settleCuda->apply(d_x, d_xp, updateVelocities, d_v, testData->reciprocalTimeStep_, calcVirial,
- testData->virial_);
+ settleGpu->apply(d_x, d_xp, updateVelocities, d_v, testData->reciprocalTimeStep_, calcVirial,
+ testData->virial_, pbcAiuc);
- copyFromDeviceBuffer((float3*)h_xp, &d_xp, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyFromDeviceBuffer((float3*)h_xp, &d_xp, 0, numAtoms, deviceStream, GpuApiCallBehavior::Sync, nullptr);
if (updateVelocities)
{
- copyFromDeviceBuffer((float3*)h_v, &d_v, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
+ copyFromDeviceBuffer((float3*)h_v, &d_v, 0, numAtoms, deviceStream,
+ GpuApiCallBehavior::Sync, nullptr);
}
freeDeviceBuffer(&d_x);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <gtest/gtest.h>
+#include "gromacs/utility/arrayref.h"
+
#include "testutils/refdata.h"
#include "testutils/testasserts.h"
/*! \brief Compute the displacements between pairs of constrained
* atoms described in the iatom "topology". */
-std::vector<real> computeDisplacements(const std::vector<int>& iatom, const std::vector<real>& positions)
+std::vector<RVec> computeDisplacements(ArrayRef<const int> iatom, const std::vector<RVec>& positions)
{
assert(0 == iatom.size() % constraintStride);
int numConstraints = iatom.size() / constraintStride;
- std::vector<real> displacements;
+ std::vector<RVec> displacements;
for (int ll = 0; ll != numConstraints; ++ll)
{
int atom_i = iatom[ll * constraintStride + 1];
int atom_j = iatom[ll * constraintStride + 2];
- for (int d = 0; d != DIM; d++)
- {
- displacements.push_back(positions[atom_i * DIM + d] - positions[atom_j * DIM + d]);
- }
+ displacements.push_back(positions[atom_i] - positions[atom_j]);
}
return displacements;
}
/*! \brief Compute the distances corresponding to the vector of displacements components */
-std::vector<real> computeDistancesSquared(const std::vector<real>& displacements)
+std::vector<real> computeDistancesSquared(ArrayRef<const RVec> displacements)
{
- assert(0 == displacements.size() % DIM);
- int numDistancesSquared = displacements.size() / DIM;
+ int numDistancesSquared = displacements.size();
std::vector<real> distanceSquared;
for (int i = 0; i != numDistancesSquared; ++i)
distanceSquared.push_back(0.0);
for (int d = 0; d != DIM; ++d)
{
- real displacement = displacements[i * DIM + d];
+ real displacement = displacements[i][d];
distanceSquared.back() += displacement * displacement;
}
}
inverseMassesDatabase_.push_back(4.0);
inverseMassesDatabase_.push_back(1.0);
- positionsDatabase_.push_back(2.5);
- positionsDatabase_.push_back(-3.1);
- positionsDatabase_.push_back(15.7);
+ positionsDatabase_.emplace_back(2.5, -3.1, 15.7);
- positionsDatabase_.push_back(0.51);
- positionsDatabase_.push_back(-3.02);
- positionsDatabase_.push_back(15.55);
+ positionsDatabase_.emplace_back(0.51, -3.02, 15.55);
- positionsDatabase_.push_back(-0.5);
- positionsDatabase_.push_back(-3.0);
- positionsDatabase_.push_back(15.2);
+ positionsDatabase_.emplace_back(-0.5, -3.0, 15.2);
- positionsDatabase_.push_back(-1.51);
- positionsDatabase_.push_back(-2.95);
- positionsDatabase_.push_back(15.05);
+ positionsDatabase_.emplace_back(-1.51, -2.95, 15.05);
}
//! Run the test
- void runTest(size_t gmx_unused numAtoms,
- size_t numConstraints,
- const std::vector<int>& iatom,
- const std::vector<real>& constrainedDistances,
- const std::vector<real>& inverseMasses,
- const std::vector<real>& positions)
+ static void runTest(size_t gmx_unused numAtoms,
+ size_t numConstraints,
+ const std::vector<int>& iatom,
+ const std::vector<real>& constrainedDistances,
+ const std::vector<real>& inverseMasses,
+ const std::vector<RVec>& positions)
{
// Check the test input is consistent
assert(numConstraints * constraintStride == iatom.size());
assert(numConstraints == constrainedDistances.size());
assert(numAtoms == inverseMasses.size());
- assert(numAtoms * DIM == positions.size());
+ assert(numAtoms == positions.size());
for (size_t i = 0; i != numConstraints; ++i)
{
for (size_t j = 1; j < 3; j++)
{
for (int d = 0; d < DIM; d++)
{
- coordMax = std::max(
- coordMax, std::abs(positions[iatom[i * constraintStride + j] * DIM + d]));
+ coordMax = std::max(coordMax, std::abs(positions[iatom[i * constraintStride + j]][d]));
}
}
}
std::vector<real> halfOfReducedMasses = computeHalfOfReducedMasses(iatom, inverseMasses);
- std::vector<real> initialDisplacements = computeDisplacements(iatom, positions);
+ std::vector<RVec> initialDisplacements = computeDisplacements(iatom, positions);
- std::vector<real> finalPositions = positions;
+ std::vector<RVec> finalPositions = positions;
int numIterations = 0;
int numErrors = 0;
cshake(iatom.data(), numConstraints, &numIterations, ShakeTest::maxNumIterations_,
- constrainedDistancesSquared.data(), finalPositions.data(),
- initialDisplacements.data(), halfOfReducedMasses.data(), omega_, inverseMasses.data(),
- distanceSquaredTolerances.data(), lagrangianValues.data(), &numErrors);
+ constrainedDistancesSquared, finalPositions, nullptr, initialDisplacements,
+ halfOfReducedMasses, omega_, inverseMasses.data(), distanceSquaredTolerances,
+ lagrangianValues, &numErrors);
- std::vector<real> finalDisplacements = computeDisplacements(iatom, finalPositions);
+ std::vector<RVec> finalDisplacements = computeDisplacements(iatom, finalPositions);
std::vector<real> finalDistancesSquared = computeDistancesSquared(finalDisplacements);
assert(numConstraints == finalDistancesSquared.size());
//! Database of inverse masses of atoms in the topology
std::vector<real> inverseMassesDatabase_;
//! Database of atom positions (three reals per atom)
- std::vector<real> positionsDatabase_;
+ std::vector<RVec> positionsDatabase_;
};
const real ShakeTest::tolerance_ = 1e-5;
std::vector<real> inverseMasses(inverseMassesDatabase_.begin(),
inverseMassesDatabase_.begin() + numAtoms);
- std::vector<real> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms * DIM);
+ std::vector<RVec> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms);
runTest(numAtoms, numConstraints, iatom, constrainedDistances, inverseMasses, positions);
}
std::vector<real> inverseMasses(inverseMassesDatabase_.begin(),
inverseMassesDatabase_.begin() + numAtoms);
- std::vector<real> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms * DIM);
+ std::vector<RVec> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms);
runTest(numAtoms, numConstraints, iatom, constrainedDistances, inverseMasses, positions);
}
std::vector<real> inverseMasses(inverseMassesDatabase_.begin(),
inverseMassesDatabase_.begin() + numAtoms);
- std::vector<real> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms * DIM);
+ std::vector<RVec> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms);
runTest(numAtoms, numConstraints, iatom, constrainedDistances, inverseMasses, positions);
}
std::vector<real> inverseMasses(inverseMassesDatabase_.begin(),
inverseMassesDatabase_.begin() + numAtoms);
- std::vector<real> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms * DIM);
+ std::vector<RVec> positions(positionsDatabase_.begin(), positionsDatabase_.begin() + numAtoms);
runTest(numAtoms, numConstraints, iatom, constrainedDistances, inverseMasses, positions);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
if (fr->bMolPBC && !ir->bPeriodicMols)
{
/* Make molecules whole only for confout writing */
- do_pbc_mtop(ir->ePBC, state->box, top_global, x_for_confout);
+ do_pbc_mtop(ir->pbcType, state->box, top_global, x_for_confout);
}
write_sto_conf_mtop(ftp2fn(efSTO, nfile, fnm), *top_global->name, top_global,
- x_for_confout, state_global->v.rvec_array(), ir->ePBC, state->box);
+ x_for_confout, state_global->v.rvec_array(), ir->pbcType, state->box);
if (fr->bMolPBC && state == state_global)
{
sfree(x_for_confout);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/pbcutil/boxutilities.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/random/tabulatednormaldistribution.h"
}
}
-static void calc_ke_part_normal(const rvec v[],
- const t_grpopts* opts,
- const t_mdatoms* md,
- gmx_ekindata_t* ekind,
- t_nrnb* nrnb,
- gmx_bool bEkinAveVel)
+static void calc_ke_part_normal(ArrayRef<const RVec> v,
+ const t_grpopts* opts,
+ const t_mdatoms* md,
+ gmx_ekindata_t* ekind,
+ t_nrnb* nrnb,
+ gmx_bool bEkinAveVel)
{
int g;
gmx::ArrayRef<t_grp_tcstat> tcstat = ekind->tcstat;
inc_nrnb(nrnb, eNR_EKIN, md->homenr);
}
-static void calc_ke_part_visc(const matrix box,
- const rvec x[],
- const rvec v[],
- const t_grpopts* opts,
- const t_mdatoms* md,
- gmx_ekindata_t* ekind,
- t_nrnb* nrnb,
- gmx_bool bEkinAveVel)
+static void calc_ke_part_visc(const matrix box,
+ ArrayRef<const RVec> x,
+ ArrayRef<const RVec> v,
+ const t_grpopts* opts,
+ const t_mdatoms* md,
+ gmx_ekindata_t* ekind,
+ t_nrnb* nrnb,
+ gmx_bool bEkinAveVel)
{
int start = 0, homenr = md->homenr;
int g, d, n, m, gt = 0;
inc_nrnb(nrnb, eNR_EKIN, homenr);
}
-void calc_ke_part(const rvec* x,
- const rvec* v,
- const matrix box,
- const t_grpopts* opts,
- const t_mdatoms* md,
- gmx_ekindata_t* ekind,
- t_nrnb* nrnb,
- gmx_bool bEkinAveVel)
+void calc_ke_part(ArrayRef<const RVec> x,
+ ArrayRef<const RVec> v,
+ const matrix box,
+ const t_grpopts* opts,
+ const t_mdatoms* md,
+ gmx_ekindata_t* ekind,
+ t_nrnb* nrnb,
+ gmx_bool bEkinAveVel)
{
if (ekind->cosacc.cos_accel == 0)
{
if (PAR(cr))
{
- gmx_bcast(sizeof(n), &n, cr);
+ gmx_bcast(sizeof(n), &n, cr->mpi_comm_mygroup);
for (i = 0; i < n; i++)
{
- gmx_bcast(DIM * DIM * sizeof(ekind->tcstat[i].ekinh[0][0]), ekind->tcstat[i].ekinh[0], cr);
- gmx_bcast(DIM * DIM * sizeof(ekind->tcstat[i].ekinf[0][0]), ekind->tcstat[i].ekinf[0], cr);
+ gmx_bcast(DIM * DIM * sizeof(ekind->tcstat[i].ekinh[0][0]), ekind->tcstat[i].ekinh[0],
+ cr->mpi_comm_mygroup);
+ gmx_bcast(DIM * DIM * sizeof(ekind->tcstat[i].ekinf[0][0]), ekind->tcstat[i].ekinf[0],
+ cr->mpi_comm_mygroup);
gmx_bcast(DIM * DIM * sizeof(ekind->tcstat[i].ekinh_old[0][0]),
- ekind->tcstat[i].ekinh_old[0], cr);
-
- gmx_bcast(sizeof(ekind->tcstat[i].ekinscalef_nhc), &(ekind->tcstat[i].ekinscalef_nhc), cr);
- gmx_bcast(sizeof(ekind->tcstat[i].ekinscaleh_nhc), &(ekind->tcstat[i].ekinscaleh_nhc), cr);
- gmx_bcast(sizeof(ekind->tcstat[i].vscale_nhc), &(ekind->tcstat[i].vscale_nhc), cr);
+ ekind->tcstat[i].ekinh_old[0], cr->mpi_comm_mygroup);
+
+ gmx_bcast(sizeof(ekind->tcstat[i].ekinscalef_nhc), &(ekind->tcstat[i].ekinscalef_nhc),
+ cr->mpi_comm_mygroup);
+ gmx_bcast(sizeof(ekind->tcstat[i].ekinscaleh_nhc), &(ekind->tcstat[i].ekinscaleh_nhc),
+ cr->mpi_comm_mygroup);
+ gmx_bcast(sizeof(ekind->tcstat[i].vscale_nhc), &(ekind->tcstat[i].vscale_nhc),
+ cr->mpi_comm_mygroup);
}
- gmx_bcast(DIM * DIM * sizeof(ekind->ekin[0][0]), ekind->ekin[0], cr);
+ gmx_bcast(DIM * DIM * sizeof(ekind->ekin[0][0]), ekind->ekin[0], cr->mpi_comm_mygroup);
- gmx_bcast(sizeof(ekind->dekindl), &ekind->dekindl, cr);
- gmx_bcast(sizeof(ekind->cosacc.mvcos), &ekind->cosacc.mvcos, cr);
+ gmx_bcast(sizeof(ekind->dekindl), &ekind->dekindl, cr->mpi_comm_mygroup);
+ gmx_bcast(sizeof(ekind->cosacc.mvcos), &ekind->cosacc.mvcos, cr->mpi_comm_mygroup);
}
}
clear_mat(vir_part);
/* Constrain the coordinates upd->xp */
- constr->apply(do_log, do_ene, step, 1, 1.0, state->x.rvec_array(), state->v.rvec_array(),
- state->v.rvec_array(), state->box, state->lambda[efptBONDED], dvdlambda,
- nullptr, bCalcVir ? &vir_con : nullptr, ConstraintVariable::Velocities);
+ constr->apply(do_log, do_ene, step, 1, 1.0, state->x.arrayRefWithPadding(),
+ state->v.arrayRefWithPadding(), state->v.arrayRefWithPadding().unpaddedArrayRef(),
+ state->box, state->lambda[efptBONDED], dvdlambda, ArrayRefWithPadding<RVec>(),
+ bCalcVir ? &vir_con : nullptr, ConstraintVariable::Velocities);
if (bCalcVir)
{
clear_mat(vir_part);
/* Constrain the coordinates upd->xp */
- constr->apply(do_log, do_ene, step, 1, 1.0, state->x.rvec_array(), upd->xp()->rvec_array(),
- nullptr, state->box, state->lambda[efptBONDED], dvdlambda,
- as_rvec_array(state->v.data()), bCalcVir ? &vir_con : nullptr,
- ConstraintVariable::Positions);
+ constr->apply(do_log, do_ene, step, 1, 1.0, state->x.arrayRefWithPadding(),
+ upd->xp()->arrayRefWithPadding(), ArrayRef<RVec>(), state->box,
+ state->lambda[efptBONDED], dvdlambda, state->v.arrayRefWithPadding(),
+ bCalcVir ? &vir_con : nullptr, ConstraintVariable::Positions);
if (bCalcVir)
{
wallcycle_stop(wcycle, ewcUPDATE);
/* Constrain the coordinates upd->xp for half a time step */
- constr->apply(do_log, do_ene, step, 1, 0.5, state->x.rvec_array(), upd->xp()->rvec_array(),
- nullptr, state->box, state->lambda[efptBONDED], dvdlambda,
- as_rvec_array(state->v.data()), nullptr, ConstraintVariable::Positions);
+ constr->apply(do_log, do_ene, step, 1, 0.5, state->x.arrayRefWithPadding(),
+ upd->xp()->arrayRefWithPadding(), ArrayRef<RVec>(), state->box,
+ state->lambda[efptBONDED], dvdlambda, state->v.arrayRefWithPadding(), nullptr,
+ ConstraintVariable::Positions);
}
}
void finish_update(const t_inputrec* inputrec, /* input record and box stuff */
const t_mdatoms* md,
t_state* state,
- const t_graph* graph,
- t_nrnb* nrnb,
gmx_wallcycle_t wcycle,
Update* upd,
const gmx::Constraints* constr)
{
- int homenr = md->homenr;
+ /* NOTE: Currently we always integrate to a temporary buffer and
+ * then copy the results back here.
+ */
- /* We must always unshift after updating coordinates; if we did not shake
- x was shifted in do_force */
+ wallcycle_start_nocount(wcycle, ewcUPDATE);
- /* NOTE Currently we always integrate to a temporary buffer and
- * then copy the results back. */
+ const int homenr = md->homenr;
+ auto xp = makeConstArrayRef(*upd->xp()).subArray(0, homenr);
+ auto x = makeArrayRef(state->x).subArray(0, homenr);
+
+ if (md->havePartiallyFrozenAtoms && constr != nullptr)
{
- wallcycle_start_nocount(wcycle, ewcUPDATE);
+ /* We have atoms that are frozen along some, but not all dimensions,
+ * then constraints will have moved them also along the frozen dimensions.
+ * To freeze such degrees of freedom we do not copy them back here.
+ */
+ const ivec* nFreeze = inputrec->opts.nFreeze;
- if (md->cFREEZE != nullptr && constr != nullptr)
+ for (int i = 0; i < homenr; i++)
{
- /* If we have atoms that are frozen along some, but not all
- * dimensions, then any constraints will have moved them also along
- * the frozen dimensions. To freeze such degrees of freedom
- * we copy them back here to later copy them forward. It would
- * be more elegant and slightly more efficient to copies zero
- * times instead of twice, but the graph case below prevents this.
- */
- const ivec* nFreeze = inputrec->opts.nFreeze;
- bool partialFreezeAndConstraints = false;
- for (int g = 0; g < inputrec->opts.ngfrz; g++)
- {
- int numFreezeDim = nFreeze[g][XX] + nFreeze[g][YY] + nFreeze[g][ZZ];
- if (numFreezeDim > 0 && numFreezeDim < 3)
- {
- partialFreezeAndConstraints = true;
- }
- }
- if (partialFreezeAndConstraints)
+ const int g = md->cFREEZE[i];
+
+ for (int d = 0; d < DIM; d++)
{
- auto xp = makeArrayRef(*upd->xp()).subArray(0, homenr);
- auto x = makeConstArrayRef(state->x).subArray(0, homenr);
- for (int i = 0; i < homenr; i++)
+ if (nFreeze[g][d] == 0)
{
- int g = md->cFREEZE[i];
-
- for (int d = 0; d < DIM; d++)
- {
- if (nFreeze[g][d])
- {
- xp[i][d] = x[i][d];
- }
- }
+ x[i][d] = xp[i][d];
}
}
}
-
- if (graph && (graph->nnodes > 0))
- {
- unshift_x(graph, state->box, state->x.rvec_array(), upd->xp()->rvec_array());
- if (TRICLINIC(state->box))
- {
- inc_nrnb(nrnb, eNR_SHIFTX, 2 * graph->nnodes);
- }
- else
- {
- inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
- }
- }
- else
- {
- auto xp = makeConstArrayRef(*upd->xp()).subArray(0, homenr);
- auto x = makeArrayRef(state->x).subArray(0, homenr);
-
-
- int gmx_unused nth = gmx_omp_nthreads_get(emntUpdate);
+ }
+ else
+ {
+ /* We have no frozen atoms or fully frozen atoms which have not
+ * been moved by the update, so we can simply copy all coordinates.
+ */
+ int gmx_unused nth = gmx_omp_nthreads_get(emntUpdate);
#pragma omp parallel for num_threads(nth) schedule(static)
- for (int i = 0; i < homenr; i++)
- {
- // Trivial statement, does not throw
- x[i] = xp[i];
- }
+ for (int i = 0; i < homenr; i++)
+ {
+ // Trivial statement, does not throw
+ x[i] = xp[i];
}
- wallcycle_stop(wcycle, ewcUPDATE);
}
- /* ############# END the update of velocities and positions ######### */
+
+ wallcycle_stop(wcycle, ewcUPDATE);
}
void update_pcouple_after_coordinates(FILE* fplog,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class ekinstate_t;
struct gmx_ekindata_t;
struct gmx_enerdata_t;
+enum class PbcType;
struct t_extmass;
struct t_fcdata;
struct t_graph;
void finish_update(const t_inputrec* inputrec,
const t_mdatoms* md,
t_state* state,
- const t_graph* graph,
- t_nrnb* nrnb,
gmx_wallcycle_t wcycle,
gmx::Update* upd,
const gmx::Constraints* constr);
/* Return TRUE if OK, FALSE in case of Shake Error */
-void calc_ke_part(const rvec* x,
- const rvec* v,
- const matrix box,
- const t_grpopts* opts,
- const t_mdatoms* md,
- gmx_ekindata_t* ekind,
- t_nrnb* nrnb,
- gmx_bool bEkinAveVel);
+void calc_ke_part(gmx::ArrayRef<const gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> v,
+ const matrix box,
+ const t_grpopts* opts,
+ const t_mdatoms* md,
+ gmx_ekindata_t* ekind,
+ t_nrnb* nrnb,
+ gmx_bool bEkinAveVel);
/*
* Compute the partial kinetic energy for home particles;
* will be accumulated in the calling routine.
real calc_temp(real ekin, real nrdf);
/* Calculate the temperature */
-real calc_pres(int ePBC, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres);
+real calc_pres(PbcType pbcType, int nwall, const matrix box, const tensor ekin, const tensor vir, tensor pres);
/* Calculate the pressure tensor, returns the scalar pressure.
* The unit of pressure is bar.
*/
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \libinternal \file
*
- * \brief Declaration of high-level functions of CUDA implementation of update and constrain class.
- *
- * \todo Change "cuda" suffix to "gpu"
+ * \brief Declaration of high-level functions of GPU implementation of update and constrain class.
*
* \author Artem Zhmurov <zhmurov@gmail.com>
*
* \ingroup module_mdlib
* \inlibraryapi
*/
-#ifndef GMX_MDLIB_UPDATE_CONSTRAIN_CUDA_H
-#define GMX_MDLIB_UPDATE_CONSTRAIN_CUDA_H
+#ifndef GMX_MDLIB_UPDATE_CONSTRAIN_GPU_H
+#define GMX_MDLIB_UPDATE_CONSTRAIN_GPU_H
#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/mdtypes/group.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/classhelpers.h"
+class DeviceContext;
+class DeviceStream;
class GpuEventSynchronizer;
-
struct gmx_mtop_t;
-struct t_idef;
+enum class PbcType : int;
+class InteractionDefinitions;
struct t_inputrec;
struct t_mdatoms;
struct t_pbc;
namespace gmx
{
-class UpdateConstrainCuda
+class UpdateConstrainGpu
{
public:
/*! \brief Create Update-Constrain object.
*
- * The constructor is given a non-nullptr \p commandStream, in which all the update and constrain
+ * The constructor is given a non-nullptr \p deviceStream, in which all the update and constrain
* routines are executed. \p xUpdatedOnDevice should mark the completion of all kernels that modify
* coordinates. The event is maintained outside this class and also passed to all (if any) consumers
* of the updated coordinates. The \p xUpdatedOnDevice also can not be a nullptr because the
* projection from it.
* \param[in] mtop Topology of the system: SETTLE gets the masses for O and H atoms
* and target O-H and H-H distances from this object.
- * \param[in] commandStream GPU stream to use. Can be nullptr.
+ * \param[in] deviceContext GPU device context.
+ * \param[in] deviceStream GPU stream to use.
* \param[in] xUpdatedOnDevice The event synchronizer to use to mark that update is done on the GPU.
*/
- UpdateConstrainCuda(const t_inputrec& ir,
- const gmx_mtop_t& mtop,
- const void* commandStream,
- GpuEventSynchronizer* xUpdatedOnDevice);
+ UpdateConstrainGpu(const t_inputrec& ir,
+ const gmx_mtop_t& mtop,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ GpuEventSynchronizer* xUpdatedOnDevice);
- ~UpdateConstrainCuda();
+ ~UpdateConstrainGpu();
/*! \brief Integrate
*
* \param[in] md Atoms data.
* \param[in] numTempScaleValues Number of temperature scaling groups. Zero for no temperature scaling.
*/
- void set(DeviceBuffer<float> d_x,
- DeviceBuffer<float> d_v,
- DeviceBuffer<float> d_f,
- const t_idef& idef,
- const t_mdatoms& md,
- int numTempScaleValues);
+ void set(DeviceBuffer<RVec> d_x,
+ DeviceBuffer<RVec> d_v,
+ DeviceBuffer<RVec> d_f,
+ const InteractionDefinitions& idef,
+ const t_mdatoms& md,
+ int numTempScaleValues);
/*! \brief
* Update PBC data.
*
* Converts PBC data from t_pbc into the PbcAiuc format and stores the latter.
*
- * \param[in] pbc The PBC data in t_pbc format.
+ * \param[in] pbcType The type of the periodic boundary (Xyz, NO, XY or Screw).
+ * \param[in] box The periodic boundary box matrix.
*/
- void setPbc(const t_pbc* pbc);
+ void setPbc(PbcType pbcType, const matrix box);
/*! \brief Return the synchronizer associated with the event indicated that the coordinates are ready on the device.
*/
/*! \brief
* Returns whether the maximum number of coupled constraints is supported
- * by the CUDA LINCS code.
+ * by the GPU LINCS code.
*
* \param[in] mtop The molecular topology
*/
} // namespace gmx
-#endif
+#endif // GMX_MDLIB_UPDATE_CONSTRAIN_GPU_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
-#include "gromacs/mdlib/update_constrain_cuda.h"
+#include "gromacs/mdlib/update_constrain_gpu.h"
#if GMX_GPU != GMX_GPU_CUDA
namespace gmx
{
-class UpdateConstrainCuda::Impl
+class UpdateConstrainGpu::Impl
{
};
-UpdateConstrainCuda::UpdateConstrainCuda(const t_inputrec& /* ir */,
- const gmx_mtop_t& /* mtop */,
- const void* /* commandStream */,
- GpuEventSynchronizer* /* xUpdatedOnDevice */) :
+UpdateConstrainGpu::UpdateConstrainGpu(const t_inputrec& /* ir */,
+ const gmx_mtop_t& /* mtop */,
+ const DeviceContext& /* deviceContext */,
+ const DeviceStream& /* deviceStream */,
+ GpuEventSynchronizer* /* xUpdatedOnDevice */) :
impl_(nullptr)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
}
-UpdateConstrainCuda::~UpdateConstrainCuda() = default;
+UpdateConstrainGpu::~UpdateConstrainGpu() = default;
-void UpdateConstrainCuda::integrate(GpuEventSynchronizer* /* fReadyOnDevice */,
- const real /* dt */,
- const bool /* updateVelocities */,
- const bool /* computeVirial */,
- tensor /* virialScaled */,
- const bool /* doTemperatureScaling */,
- gmx::ArrayRef<const t_grp_tcstat> /* tcstat */,
- const bool /* doParrinelloRahman */,
- const float /* dtPressureCouple */,
- const matrix /* prVelocityScalingMatrix*/)
+void UpdateConstrainGpu::integrate(GpuEventSynchronizer* /* fReadyOnDevice */,
+ const real /* dt */,
+ const bool /* updateVelocities */,
+ const bool /* computeVirial */,
+ tensor /* virialScaled */,
+ const bool /* doTemperatureScaling */,
+ gmx::ArrayRef<const t_grp_tcstat> /* tcstat */,
+ const bool /* doParrinelloRahman */,
+ const float /* dtPressureCouple */,
+ const matrix /* prVelocityScalingMatrix*/)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
}
-void UpdateConstrainCuda::scaleCoordinates(const matrix /* scalingMatrix */)
+void UpdateConstrainGpu::scaleCoordinates(const matrix /* scalingMatrix */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
}
-void UpdateConstrainCuda::set(DeviceBuffer<float> /* d_x */,
- DeviceBuffer<float> /* d_v */,
- const DeviceBuffer<float> /* d_f */,
- const t_idef& /* idef */,
- const t_mdatoms& /* md */,
- const int /* numTempScaleValues */)
+void UpdateConstrainGpu::set(DeviceBuffer<RVec> /* d_x */,
+ DeviceBuffer<RVec> /* d_v */,
+ const DeviceBuffer<RVec> /* d_f */,
+ const InteractionDefinitions& /* idef */,
+ const t_mdatoms& /* md */,
+ const int /* numTempScaleValues */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
}
-void UpdateConstrainCuda::setPbc(const t_pbc* /* pbc */)
+void UpdateConstrainGpu::setPbc(const PbcType /* pbcType */, const matrix /* box */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
}
-GpuEventSynchronizer* UpdateConstrainCuda::getCoordinatesReadySync()
+GpuEventSynchronizer* UpdateConstrainGpu::getCoordinatesReadySync()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub for UpdateConstrain was called instead of the correct implementation.");
return nullptr;
}
-bool UpdateConstrainCuda::isNumCoupledConstraintsSupported(const gmx_mtop_t& /* mtop */)
+bool UpdateConstrainGpu::isNumCoupledConstraintsSupported(const gmx_mtop_t& /* mtop */)
{
return false;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
#include "gmxpre.h"
-#include "update_constrain_cuda_impl.h"
+#include "update_constrain_gpu_impl.h"
#include <assert.h>
#include <stdio.h>
#include <algorithm>
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream.h"
#include "gromacs/gpu_utils/devicebuffer.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/gpu_utils/vectype_ops.cuh"
-#include "gromacs/mdlib/leapfrog_cuda.cuh"
-#include "gromacs/mdlib/lincs_cuda.cuh"
-#include "gromacs/mdlib/settle_cuda.cuh"
-#include "gromacs/mdlib/update_constrain_cuda.h"
+#include "gromacs/mdlib/leapfrog_gpu.cuh"
+#include "gromacs/mdlib/lincs_gpu.cuh"
+#include "gromacs/mdlib/settle_gpu.cuh"
+#include "gromacs/mdlib/update_constrain_gpu.h"
namespace gmx
{
}
}
-void UpdateConstrainCuda::Impl::integrate(GpuEventSynchronizer* fReadyOnDevice,
- const real dt,
- const bool updateVelocities,
- const bool computeVirial,
- tensor virial,
- const bool doTemperatureScaling,
- gmx::ArrayRef<const t_grp_tcstat> tcstat,
- const bool doParrinelloRahman,
- const float dtPressureCouple,
- const matrix prVelocityScalingMatrix)
+void UpdateConstrainGpu::Impl::integrate(GpuEventSynchronizer* fReadyOnDevice,
+ const real dt,
+ const bool updateVelocities,
+ const bool computeVirial,
+ tensor virial,
+ const bool doTemperatureScaling,
+ gmx::ArrayRef<const t_grp_tcstat> tcstat,
+ const bool doParrinelloRahman,
+ const float dtPressureCouple,
+ const matrix prVelocityScalingMatrix)
{
// Clearing virial matrix
// TODO There is no point in having separate virial matrix for constraints
clear_mat(virial);
// Make sure that the forces are ready on device before proceeding with the update.
- fReadyOnDevice->enqueueWaitEvent(commandStream_);
+ fReadyOnDevice->enqueueWaitEvent(deviceStream_);
- // The integrate should save a copy of the current coordinates in d_xp_ and write updated once
- // into d_x_. The d_xp_ is only needed by constraints.
+ // The integrate should save a copy of the current coordinates in d_xp_ and write updated
+ // once into d_x_. The d_xp_ is only needed by constraints.
integrator_->integrate(d_x_, d_xp_, d_v_, d_f_, dt, doTemperatureScaling, tcstat,
doParrinelloRahman, dtPressureCouple, prVelocityScalingMatrix);
// Constraints need both coordinates before (d_x_) and after (d_xp_) update. However, after constraints
// are applied, the d_x_ can be discarded. So we intentionally swap the d_x_ and d_xp_ here to avoid the
// d_xp_ -> d_x_ copy after constraints. Note that the integrate saves them in the wrong order as well.
- lincsCuda_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial);
- settleCuda_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial);
+ lincsGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
+ settleGpu_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
// scaledVirial -> virial (methods above returns scaled values)
float scaleFactor = 0.5f / (dt * dt);
}
}
- coordinatesReady_->markEvent(commandStream_);
+ coordinatesReady_->markEvent(deviceStream_);
return;
}
-void UpdateConstrainCuda::Impl::scaleCoordinates(const matrix scalingMatrix)
+void UpdateConstrainGpu::Impl::scaleCoordinates(const matrix scalingMatrix)
{
ScalingMatrix mu;
mu.xx = scalingMatrix[XX][XX];
const auto kernelArgs = prepareGpuKernelArguments(
scaleCoordinates_kernel, coordinateScalingKernelLaunchConfig_, &numAtoms_, &d_x_, &mu);
- launchGpuKernel(scaleCoordinates_kernel, coordinateScalingKernelLaunchConfig_, nullptr,
- "scaleCoordinates_kernel", kernelArgs);
+ launchGpuKernel(scaleCoordinates_kernel, coordinateScalingKernelLaunchConfig_, deviceStream_,
+ nullptr, "scaleCoordinates_kernel", kernelArgs);
// TODO: Although this only happens on the pressure coupling steps, this synchronization
// can affect the perfornamce if nstpcouple is small.
- gpuStreamSynchronize(commandStream_);
+ deviceStream_.synchronize();
}
-UpdateConstrainCuda::Impl::Impl(const t_inputrec& ir,
- const gmx_mtop_t& mtop,
- const void* commandStream,
- GpuEventSynchronizer* xUpdatedOnDevice) :
+UpdateConstrainGpu::Impl::Impl(const t_inputrec& ir,
+ const gmx_mtop_t& mtop,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ GpuEventSynchronizer* xUpdatedOnDevice) :
+ deviceContext_(deviceContext),
+ deviceStream_(deviceStream),
coordinatesReady_(xUpdatedOnDevice)
{
GMX_ASSERT(xUpdatedOnDevice != nullptr, "The event synchronizer can not be nullptr.");
- commandStream != nullptr ? commandStream_ = *static_cast<const CommandStream*>(commandStream)
- : commandStream_ = nullptr;
- integrator_ = std::make_unique<LeapFrogCuda>(commandStream_);
- lincsCuda_ = std::make_unique<LincsCuda>(ir.nLincsIter, ir.nProjOrder, commandStream_);
- settleCuda_ = std::make_unique<SettleCuda>(mtop, commandStream_);
+ integrator_ = std::make_unique<LeapFrogGpu>(deviceContext_, deviceStream_);
+ lincsGpu_ = std::make_unique<LincsGpu>(ir.nLincsIter, ir.nProjOrder, deviceContext_, deviceStream_);
+ settleGpu_ = std::make_unique<SettleGpu>(mtop, deviceContext_, deviceStream_);
coordinateScalingKernelLaunchConfig_.blockSize[0] = c_threadsPerBlock;
coordinateScalingKernelLaunchConfig_.blockSize[1] = 1;
coordinateScalingKernelLaunchConfig_.blockSize[2] = 1;
coordinateScalingKernelLaunchConfig_.sharedMemorySize = 0;
- coordinateScalingKernelLaunchConfig_.stream = commandStream_;
}
-UpdateConstrainCuda::Impl::~Impl() {}
+UpdateConstrainGpu::Impl::~Impl() {}
-void UpdateConstrainCuda::Impl::set(DeviceBuffer<float> d_x,
- DeviceBuffer<float> d_v,
- const DeviceBuffer<float> d_f,
- const t_idef& idef,
- const t_mdatoms& md,
- const int numTempScaleValues)
+void UpdateConstrainGpu::Impl::set(DeviceBuffer<RVec> d_x,
+ DeviceBuffer<RVec> d_v,
+ const DeviceBuffer<RVec> d_f,
+ const InteractionDefinitions& idef,
+ const t_mdatoms& md,
+ const int numTempScaleValues)
{
GMX_ASSERT(d_x != nullptr, "Coordinates device buffer should not be null.");
GMX_ASSERT(d_v != nullptr, "Velocities device buffer should not be null.");
numAtoms_ = md.nr;
- reallocateDeviceBuffer(&d_xp_, numAtoms_, &numXp_, &numXpAlloc_, nullptr);
+ reallocateDeviceBuffer(&d_xp_, numAtoms_, &numXp_, &numXpAlloc_, deviceContext_);
reallocateDeviceBuffer(&d_inverseMasses_, numAtoms_, &numInverseMasses_,
- &numInverseMassesAlloc_, nullptr);
+ &numInverseMassesAlloc_, deviceContext_);
// Integrator should also update something, but it does not even have a method yet
integrator_->set(md, numTempScaleValues, md.cTC);
- lincsCuda_->set(idef, md);
- settleCuda_->set(idef, md);
+ lincsGpu_->set(idef, md);
+ settleGpu_->set(idef, md);
coordinateScalingKernelLaunchConfig_.gridSize[0] =
(numAtoms_ + c_threadsPerBlock - 1) / c_threadsPerBlock;
}
-void UpdateConstrainCuda::Impl::setPbc(const t_pbc* pbc)
+void UpdateConstrainGpu::Impl::setPbc(const PbcType pbcType, const matrix box)
{
- setPbcAiuc(pbc->ndim_ePBC, pbc->box, &pbcAiuc_);
- integrator_->setPbc(pbc);
- lincsCuda_->setPbc(pbc);
- settleCuda_->setPbc(pbc);
+ setPbcAiuc(numPbcDimensions(pbcType), box, &pbcAiuc_);
}
-GpuEventSynchronizer* UpdateConstrainCuda::Impl::getCoordinatesReadySync()
+GpuEventSynchronizer* UpdateConstrainGpu::Impl::getCoordinatesReadySync()
{
return coordinatesReady_;
}
-UpdateConstrainCuda::UpdateConstrainCuda(const t_inputrec& ir,
- const gmx_mtop_t& mtop,
- const void* commandStream,
- GpuEventSynchronizer* xUpdatedOnDevice) :
- impl_(new Impl(ir, mtop, commandStream, xUpdatedOnDevice))
+UpdateConstrainGpu::UpdateConstrainGpu(const t_inputrec& ir,
+ const gmx_mtop_t& mtop,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ GpuEventSynchronizer* xUpdatedOnDevice) :
+ impl_(new Impl(ir, mtop, deviceContext, deviceStream, xUpdatedOnDevice))
{
}
-UpdateConstrainCuda::~UpdateConstrainCuda() = default;
-
-void UpdateConstrainCuda::integrate(GpuEventSynchronizer* fReadyOnDevice,
- const real dt,
- const bool updateVelocities,
- const bool computeVirial,
- tensor virialScaled,
- const bool doTemperatureScaling,
- gmx::ArrayRef<const t_grp_tcstat> tcstat,
- const bool doParrinelloRahman,
- const float dtPressureCouple,
- const matrix prVelocityScalingMatrix)
+UpdateConstrainGpu::~UpdateConstrainGpu() = default;
+
+void UpdateConstrainGpu::integrate(GpuEventSynchronizer* fReadyOnDevice,
+ const real dt,
+ const bool updateVelocities,
+ const bool computeVirial,
+ tensor virialScaled,
+ const bool doTemperatureScaling,
+ gmx::ArrayRef<const t_grp_tcstat> tcstat,
+ const bool doParrinelloRahman,
+ const float dtPressureCouple,
+ const matrix prVelocityScalingMatrix)
{
impl_->integrate(fReadyOnDevice, dt, updateVelocities, computeVirial, virialScaled, doTemperatureScaling,
tcstat, doParrinelloRahman, dtPressureCouple, prVelocityScalingMatrix);
}
-void UpdateConstrainCuda::scaleCoordinates(const matrix scalingMatrix)
+void UpdateConstrainGpu::scaleCoordinates(const matrix scalingMatrix)
{
impl_->scaleCoordinates(scalingMatrix);
}
-void UpdateConstrainCuda::set(DeviceBuffer<float> d_x,
- DeviceBuffer<float> d_v,
- const DeviceBuffer<float> d_f,
- const t_idef& idef,
- const t_mdatoms& md,
- const int numTempScaleValues)
+void UpdateConstrainGpu::set(DeviceBuffer<RVec> d_x,
+ DeviceBuffer<RVec> d_v,
+ const DeviceBuffer<RVec> d_f,
+ const InteractionDefinitions& idef,
+ const t_mdatoms& md,
+ const int numTempScaleValues)
{
impl_->set(d_x, d_v, d_f, idef, md, numTempScaleValues);
}
-void UpdateConstrainCuda::setPbc(const t_pbc* pbc)
+void UpdateConstrainGpu::setPbc(const PbcType pbcType, const matrix box)
{
- impl_->setPbc(pbc);
+ impl_->setPbc(pbcType, box);
}
-GpuEventSynchronizer* UpdateConstrainCuda::getCoordinatesReadySync()
+GpuEventSynchronizer* UpdateConstrainGpu::getCoordinatesReadySync()
{
return impl_->getCoordinatesReadySync();
}
-bool UpdateConstrainCuda::isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop)
+bool UpdateConstrainGpu::isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop)
{
- return LincsCuda::isNumCoupledConstraintsSupported(mtop);
+ return LincsGpu::isNumCoupledConstraintsSupported(mtop);
}
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \internal \file
*
- * \brief Declares CUDA implementation class for update and constraints.
+ * \brief Declares GPU implementation class for update and constraints.
*
* This header file is needed to include from both the device-side
* kernels file, and the host-side management code.
*
* \ingroup module_mdlib
*/
-#ifndef GMX_MDLIB_UPDATE_CONSTRAIN_CUDA_IMPL_H
-#define GMX_MDLIB_UPDATE_CONSTRAIN_CUDA_IMPL_H
+#ifndef GMX_MDLIB_UPDATE_CONSTRAIN_GPU_IMPL_H
+#define GMX_MDLIB_UPDATE_CONSTRAIN_GPU_IMPL_H
#include "gmxpre.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
-#include "gromacs/mdlib/leapfrog_cuda.cuh"
-#include "gromacs/mdlib/lincs_cuda.cuh"
-#include "gromacs/mdlib/settle_cuda.cuh"
-#include "gromacs/mdlib/update_constrain_cuda.h"
+#include "gromacs/mdlib/leapfrog_gpu.cuh"
+#include "gromacs/mdlib/lincs_gpu.cuh"
+#include "gromacs/mdlib/settle_gpu.cuh"
+#include "gromacs/mdlib/update_constrain_gpu.h"
#include "gromacs/mdtypes/inputrec.h"
namespace gmx
{
-/*! \internal \brief Class with interfaces and data for CUDA version of Update-Constraint. */
-class UpdateConstrainCuda::Impl
+/*! \internal \brief Class with interfaces and data for GPU version of Update-Constraint. */
+class UpdateConstrainGpu::Impl
{
public:
/*! \brief Create Update-Constrain object.
*
- * The constructor is given a non-nullptr \p commandStream, in which all the update and constrain
+ * The constructor is given a non-nullptr \p deviceStream, in which all the update and constrain
* routines are executed. \p xUpdatedOnDevice should mark the completion of all kernels that modify
* coordinates. The event is maintained outside this class and also passed to all (if any) consumers
* of the updated coordinates. The \p xUpdatedOnDevice also can not be a nullptr because the
* projection from it.
* \param[in] mtop Topology of the system: SETTLE gets the masses for O and H atoms
* and target O-H and H-H distances from this object.
- * \param[in] commandStream GPU stream to use. Can be nullptr.
+ * \param[in] deviceContext GPU device context.
+ * \param[in] deviceStream GPU stream to use.
* \param[in] xUpdatedOnDevice The event synchronizer to use to mark that update is done on the GPU.
*/
- Impl(const t_inputrec& ir, const gmx_mtop_t& mtop, const void* commandStream, GpuEventSynchronizer* xUpdatedOnDevice);
+ Impl(const t_inputrec& ir,
+ const gmx_mtop_t& mtop,
+ const DeviceContext& deviceContext,
+ const DeviceStream& deviceStream,
+ GpuEventSynchronizer* xUpdatedOnDevice);
~Impl();
* \param[in] md Atoms data.
* \param[in] numTempScaleValues Number of temperature scaling groups. Set zero for no temperature coupling.
*/
- void set(DeviceBuffer<float> d_x,
- DeviceBuffer<float> d_v,
- const DeviceBuffer<float> d_f,
- const t_idef& idef,
- const t_mdatoms& md,
- const int numTempScaleValues);
+ void set(DeviceBuffer<RVec> d_x,
+ DeviceBuffer<RVec> d_v,
+ const DeviceBuffer<RVec> d_f,
+ const InteractionDefinitions& idef,
+ const t_mdatoms& md,
+ const int numTempScaleValues);
/*! \brief
* Update PBC data.
*
* Converts PBC data from t_pbc into the PbcAiuc format and stores the latter.
*
- * \param[in] pbc The PBC data in t_pbc format.
+ * \param[in] pbcType The type of the periodic boundary.
+ * \param[in] box The periodic boundary box matrix.
*/
- void setPbc(const t_pbc* pbc);
+ void setPbc(PbcType pbcType, const matrix box);
/*! \brief Return the synchronizer associated with the event indicated that the coordinates are ready on the device.
*/
/*! \brief
* Returns whether the maximum number of coupled constraints is supported
- * by the CUDA LINCS code.
+ * by the GPU LINCS code.
*
* \param[in] mtop The molecular topology
*/
static bool isNumCoupledConstraintsSupported(const gmx_mtop_t& mtop);
private:
- //! CUDA stream
- CommandStream commandStream_ = nullptr;
- //! CUDA kernel launch config
+ //! GPU context object
+ const DeviceContext& deviceContext_;
+ //! GPU stream
+ const DeviceStream& deviceStream_;
+ //! GPU kernel launch config
KernelLaunchConfig coordinateScalingKernelLaunchConfig_;
//! Periodic boundary data
int numInverseMassesAlloc_ = -1;
//! Leap-Frog integrator
- std::unique_ptr<LeapFrogCuda> integrator_;
- //! LINCS CUDA object to use for non-water constraints
- std::unique_ptr<LincsCuda> lincsCuda_;
- //! SETTLE CUDA object for water constrains
- std::unique_ptr<SettleCuda> settleCuda_;
+ std::unique_ptr<LeapFrogGpu> integrator_;
+ //! LINCS GPU object to use for non-water constraints
+ std::unique_ptr<LincsGpu> lincsGpu_;
+ //! SETTLE GPU object for water constrains
+ std::unique_ptr<SettleGpu> settleGpu_;
//! An pointer to the event to indicate when the update of coordinates is complete
GpuEventSynchronizer* coordinatesReady_;
} // namespace gmx
-#endif
+#endif // GMX_MDLIB_UPDATE_CONSTRAIN_GPU_IMPL_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/units.h"
#include "gromacs/mdlib/constr.h"
#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/topology/block.h"
#include "gromacs/topology/idef.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/topology.h"
+#include "gromacs/utility/listoflists.h"
namespace gmx
{
{
for (size_t i = 0; i < ilist.iatoms.size(); i += ilistStride(ilist))
{
- if (isConstraintFlexible(iparams.data(), ilist.iatoms[i]))
+ if (isConstraintFlexible(iparams, ilist.iatoms[i]))
{
return true;
}
}
/*! \brief Returns the range of atoms constrained to atom \p a (including \p a itself) */
-static AtomIndexExtremes constraintAtomRange(int a, const t_blocka& at2con, const InteractionList& ilistConstraints)
+static AtomIndexExtremes constraintAtomRange(int a,
+ const ListOfLists<int>& at2con,
+ const InteractionList& ilistConstraints)
{
AtomIndexExtremes extremes = { a, a };
- for (int i = at2con.index[a]; i < at2con.index[a + 1]; i++)
+ for (const int constraint : at2con[a])
{
for (int j = 0; j < 2; j++)
{
- int atomJ = ilistConstraints.iatoms[at2con.a[i] * 3 + 1 + j];
+ int atomJ = ilistConstraints.iatoms[constraint * 3 + 1 + j];
extremes.minAtom = std::min(extremes.minAtom, atomJ);
extremes.maxAtom = std::max(extremes.maxAtom, atomJ);
}
}
/*! \brief Returns the size of the update group starting at \p firstAtom or 0 when criteria (see updategroups.h) are not met */
-static int detectGroup(int firstAtom,
- const gmx_moltype_t& moltype,
- const t_blocka& at2con,
- const InteractionList& ilistConstraints)
+static int detectGroup(int firstAtom,
+ const gmx_moltype_t& moltype,
+ const ListOfLists<int>& at2con,
+ const InteractionList& ilistConstraints)
{
/* We should be using moltype.atoms.atom[].ptype for checking whether
* a particle is a vsite. But the test code can't fill t_atoms,
std::vector<bool> isParticleVsite = buildIsParticleVsite(moltype);
/* A non-vsite atom without constraints is an update group by itself */
- if (!isParticleVsite[firstAtom] && at2con.index[firstAtom + 1] - at2con.index[firstAtom] == 0)
+ if (!isParticleVsite[firstAtom] && at2con[firstAtom].empty())
{
return 1;
}
}
else
{
- int numConstraints = at2con.index[a + 1] - at2con.index[a];
+ const int numConstraints = at2con[a].ssize();
if (numConstraints == 0)
{
/* We can not have unconstrained atoms in an update group */
{
AtomIndexExtremes extremes = vsiteConstructRange(lastAtom + 1, moltype);
if (extremes.minAtom < firstAtom)
- {
+ { // NOLINT bugprone-branch-clone
/* Constructing atom precedes the group */
return 0;
}
}
/* Combine all constraint ilists into a single one */
- InteractionList constraintsCombined = jointConstraintList(moltype);
- t_ilist ilistsCombined[F_NRE];
- ilistsCombined[F_CONSTR].nr = constraintsCombined.iatoms.size();
- ilistsCombined[F_CONSTR].iatoms = constraintsCombined.iatoms.data();
- ilistsCombined[F_CONSTRNC].nr = 0;
+ std::array<InteractionList, F_NRE> ilistsCombined;
+ ilistsCombined[F_CONSTR] = jointConstraintList(moltype);
/* We "include" flexible constraints, but none are present (checked above) */
- t_blocka at2con = make_at2con(moltype.atoms.nr, ilistsCombined, iparams.data(),
- FlexibleConstraintTreatment::Include);
+ const ListOfLists<int> at2con = make_at2con(moltype.atoms.nr, ilistsCombined, iparams,
+ FlexibleConstraintTreatment::Include);
bool satisfiesCriteria = true;
int firstAtom = 0;
while (satisfiesCriteria && firstAtom < moltype.atoms.nr)
{
- int numAtomsInGroup = detectGroup(firstAtom, moltype, at2con, constraintsCombined);
+ int numAtomsInGroup = detectGroup(firstAtom, moltype, at2con, ilistsCombined[F_CONSTR]);
if (numAtomsInGroup == 0)
{
groups.clear();
}
- done_blocka(&at2con);
-
return groups;
}
static real constraintGroupRadius(const gmx_moltype_t& moltype,
gmx::ArrayRef<const t_iparams> iparams,
const int centralAtom,
- const t_blocka& at2con,
+ const ListOfLists<int>& at2con,
const std::unordered_multimap<int, int>& angleIndices,
const real constraintLength,
const real temperature)
{
- const int numConstraints = at2con.index[centralAtom + 1] - at2con.index[centralAtom];
+ const int numConstraints = at2con[centralAtom].ssize();
GMX_RELEASE_ASSERT(numConstraints == numPartnerAtoms,
"We expect as many constraints as partner atoms here");
std::array<int, numPartnerAtoms> partnerAtoms;
for (int i = 0; i < numPartnerAtoms; i++)
{
- const int ind = at2con.a[at2con.index[centralAtom] + i] * 3;
+ const int ind = at2con[centralAtom][i] * 3;
if (ind >= moltype.ilist[F_CONSTR].size())
{
/* This is a flexible constraint, we don't optimize for that */
const InteractionList& settles = moltype.ilist[F_SETTLE];
- t_blocka at2con = make_at2con(moltype, iparams, FlexibleConstraintTreatment::Include);
+ const ListOfLists<int> at2con = make_at2con(moltype, iparams, FlexibleConstraintTreatment::Include);
const auto angleIndices = getAngleIndices(moltype);
int maxAtom = -1;
for (int a : updateGroups.block(group))
{
- int numConstraints = at2con.index[a + 1] - at2con.index[a];
+ const int numConstraints = at2con[a].ssize();
if (numConstraints > maxNumConstraints)
{
maxNumConstraints = numConstraints;
maxAtom = a;
}
}
- GMX_ASSERT(maxAtom >= 0 || settles.size() > 0,
+ GMX_ASSERT(maxAtom >= 0 || !settles.empty(),
"We should have at least two atoms in the group with constraints");
if (maxAtom < 0)
{
int constraintType = -1;
real maxConstraintLength = 0;
real sumConstraintLengths = 0;
- for (int i = at2con.index[maxAtom]; i < at2con.index[maxAtom + 1]; i++)
+ bool isFirstConstraint = true;
+ for (const int constraint : at2con[maxAtom])
{
- int conIndex = at2con.a[i] * (1 + NRAL(F_CONSTR));
+ int conIndex = constraint * (1 + NRAL(F_CONSTR));
int iparamsIndex;
if (conIndex < moltype.ilist[F_CONSTR].size())
{
iparamsIndex =
moltype.ilist[F_CONSTRNC].iatoms[conIndex - moltype.ilist[F_CONSTR].size()];
}
- if (i == at2con.index[maxAtom])
+ if (isFirstConstraint)
{
- constraintType = iparamsIndex;
+ constraintType = iparamsIndex;
+ isFirstConstraint = false;
}
else if (iparamsIndex != constraintType)
{
sumConstraintLengths += constraintLength;
}
- int numConstraints = at2con.index[maxAtom + 1] - at2con.index[maxAtom];
+ int numConstraints = at2con[maxAtom].ssize();
real radius;
if (numConstraints == 1)
{
maxRadius = std::max(maxRadius, dCAny);
}
- done_blocka(&at2con);
-
return maxRadius;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "vcm.h"
-#include "gromacs/gmxlib/network.h"
#include "gromacs/math/functions.h"
#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/fatalerror.h"
if (mode == ecmANGULAR && ndim < 3)
{
- gmx_fatal(FARGS, "Can not have angular comm removal with pbc=%s", epbc_names[ir.ePBC]);
+ gmx_fatal(FARGS, "Can not have angular comm removal with pbc=%s",
+ c_pbcTypeNames[ir.pbcType].c_str());
}
if (mode != ecmNO)
}
/* Center of mass code for groups */
-void calc_vcm_grp(const t_mdatoms& md, const rvec x[], const rvec v[], t_vcm* vcm)
+void calc_vcm_grp(const t_mdatoms& md,
+ gmx::ArrayRef<const gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> v,
+ t_vcm* vcm)
{
+ if (vcm->mode == ecmNO)
+ {
+ return;
+ }
int nthreads = gmx_omp_nthreads_get(emntDefault);
- if (vcm->mode != ecmNO)
+
{
-#pragma omp parallel num_threads(nthreads)
+#pragma omp parallel num_threads(nthreads) default(none) shared(x, v, vcm, md)
{
int t = gmx_omp_get_thread_num();
for (int g = 0; g < vcm->size; g++)
* \param[in] vcm VCM data
*/
template<int numDimensions>
-static void doStopComMotionLinear(const t_mdatoms& mdatoms, rvec* v, const t_vcm& vcm)
+static void doStopComMotionLinear(const t_mdatoms& mdatoms, gmx::ArrayRef<gmx::RVec> v, const t_vcm& vcm)
{
const int homenr = mdatoms.homenr;
const unsigned short* group_id = mdatoms.cVCM;
}
}
else if (group_id == nullptr)
- {
+ { // NOLINT bugprone-branch-clone This is actually a clang-tidy bug
#pragma omp for schedule(static)
for (int i = 0; i < homenr; i++)
{
* \param[in] vcm VCM data
*/
template<int numDimensions>
-static void doStopComMotionAccelerationCorrection(int homenr,
- const unsigned short* group_id,
- rvec* gmx_restrict x,
- rvec* gmx_restrict v,
- const t_vcm& vcm)
+static void doStopComMotionAccelerationCorrection(int homenr,
+ const unsigned short* group_id,
+ gmx::ArrayRef<gmx::RVec> x,
+ gmx::ArrayRef<gmx::RVec> v,
+ const t_vcm& vcm)
{
const real xCorrectionFactor = 0.5 * vcm.timeStep;
+ // NOLINTNEXTLINE bugprone-branch-clone This is actually a clang-tidy bug
if (group_id == nullptr)
{
#pragma omp for schedule(static)
}
}
-static void do_stopcm_grp(const t_mdatoms& mdatoms, rvec x[], rvec v[], const t_vcm& vcm)
+static void do_stopcm_grp(const t_mdatoms& mdatoms,
+ gmx::ArrayRef<gmx::RVec> x,
+ gmx::ArrayRef<gmx::RVec> v,
+ const t_vcm& vcm)
{
- if (vcm.mode != ecmNO)
+ if (vcm.mode == ecmNO)
+ {
+ return;
+ }
{
const int homenr = mdatoms.homenr;
const unsigned short* group_id = mdatoms.cVCM;
int gmx_unused nth = gmx_omp_nthreads_get(emntDefault);
-#pragma omp parallel num_threads(nth)
+ // homenr could be shared, but gcc-8 & gcc-9 don't agree how to write that...
+ // https://www.gnu.org/software/gcc/gcc-9/porting_to.html -> OpenMP data sharing
+#pragma omp parallel num_threads(nth) default(none) shared(x, v, vcm, group_id, mdatoms) \
+ firstprivate(homenr)
{
if (vcm.mode == ecmLINEAR || vcm.mode == ecmANGULAR
- || (vcm.mode == ecmLINEAR_ACCELERATION_CORRECTION && x == nullptr))
+ || (vcm.mode == ecmLINEAR_ACCELERATION_CORRECTION && x.empty()))
{
/* Subtract linear momentum for v */
switch (vcm.ndim)
if (vcm.mode == ecmANGULAR)
{
/* Subtract angular momentum */
- GMX_ASSERT(x, "Need x to compute angular momentum correction");
+ GMX_ASSERT(!x.empty(), "Need x to compute angular momentum correction");
int g = 0;
#pragma omp for schedule(static)
}
}
-void process_and_stopcm_grp(FILE* fplog, t_vcm* vcm, const t_mdatoms& mdatoms, rvec x[], rvec v[])
+void process_and_stopcm_grp(FILE* fplog,
+ t_vcm* vcm,
+ const t_mdatoms& mdatoms,
+ gmx::ArrayRef<gmx::RVec> x,
+ gmx::ArrayRef<gmx::RVec> v)
{
if (vcm->mode != ecmNO)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
struct t_inputrec;
struct t_mdatoms;
+namespace gmx
+{
+template<typename T>
+class ArrayRef;
+}
+
struct t_vcm_thread
{
//! Linear momentum
/* Do a per group center of mass things */
-void calc_vcm_grp(const t_mdatoms& md, const rvec x[], const rvec v[], t_vcm* vcm);
+void calc_vcm_grp(const t_mdatoms& md,
+ gmx::ArrayRef<const gmx::RVec> x,
+ gmx::ArrayRef<const gmx::RVec> v,
+ t_vcm* vcm);
/* Set the COM velocity to zero and potentially correct the COM position.
*
* and a pointer to the coordinates at normal MD steps.
* When fplog != nullptr, a warning is printed to fplog with high COM velocity.
*/
-void process_and_stopcm_grp(FILE* fplog, t_vcm* vcm, const t_mdatoms& mdatoms, rvec x[], rvec v[]);
+void process_and_stopcm_grp(FILE* fplog,
+ t_vcm* vcm,
+ const t_mdatoms& mdatoms,
+ gmx::ArrayRef<gmx::RVec> x,
+ gmx::ArrayRef<gmx::RVec> v);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/ishift.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/topology/ifunc.h"
* Any remaining vsites are assigned to a separate master thread task.
*/
+using gmx::ArrayRef;
using gmx::RVec;
-static void init_ilist(t_ilist* ilist)
-{
- for (int i = 0; i < F_NRE; i++)
- {
- ilist[i].nr = 0;
- ilist[i].nalloc = 0;
- ilist[i].iatoms = nullptr;
- }
-}
-
/*! \brief List of atom indices belonging to a task */
struct AtomIndex
{
struct InterdependentTask
{
//! The interaction lists, only vsite entries are used
- t_ilist ilist[F_NRE];
+ InteractionLists ilist;
//! Thread/task-local force buffer
std::vector<RVec> force;
//! The atom indices of the vsites of our task
//! Flags if elements in force are spread to or not
std::vector<bool> use;
//! The number of entries set to true in use
- int nuse;
+ int nuse = 0;
//! Array of atoms indices, size nthreads, covering all nuse set elements in use
std::vector<AtomIndex> atomIndex;
//! List of tasks (force blocks) this task spread forces to
std::vector<int> spreadTask;
//! List of tasks that write to this tasks force block range
std::vector<int> reduceTask;
-
- InterdependentTask()
- {
- init_ilist(ilist);
- nuse = 0;
- }
};
/*! \brief Vsite thread task data structure */
//! End of atom range of this task
int rangeEnd;
//! The interaction lists, only vsite entries are used
- t_ilist ilist[F_NRE];
+ std::array<InteractionList, F_NRE> ilist;
//! Local fshift accumulation buffer
rvec fshift[SHIFTS];
//! Local virial dx*df accumulation buffer
{
rangeStart = -1;
rangeEnd = -1;
- init_ilist(ilist);
clear_rvecs(SHIFTS, fshift);
clear_mat(dxdf);
useInterdependentTask = false;
*
* \param[in] ilist The interaction list
*/
-template<typename T>
-static int vsiteIlistNrCount(const T* ilist)
+static int vsiteIlistNrCount(ArrayRef<const InteractionList> ilist)
{
int nr = 0;
for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
}
-static int constr_vsiten(const t_iatom* ia, const t_iparams ip[], rvec* x, const t_pbc* pbc)
+static int constr_vsiten(const t_iatom* ia, ArrayRef<const t_iparams> ip, rvec* x, const t_pbc* pbc)
{
rvec x1, dx;
dvec dsum;
}
}
-static void construct_vsites_thread(rvec x[],
- real dt,
- rvec* v,
- const t_iparams ip[],
- const t_ilist ilist[],
- const t_pbc* pbc_null)
+static void construct_vsites_thread(rvec x[],
+ real dt,
+ rvec* v,
+ ArrayRef<const t_iparams> ip,
+ ArrayRef<const InteractionList> ilist,
+ const t_pbc* pbc_null)
{
real inv_dt;
if (v != nullptr)
for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
{
- if (ilist[ftype].nr == 0)
+ if (ilist[ftype].empty())
{
continue;
}
{ // TODO remove me
int nra = interaction_function[ftype].nratoms;
int inc = 1 + nra;
- int nr = ilist[ftype].nr;
+ int nr = ilist[ftype].size();
- const t_iatom* ia = ilist[ftype].iatoms;
+ const t_iatom* ia = ilist[ftype].iatoms.data();
for (int i = 0; i < nr;)
{
}
}
-void construct_vsites(const gmx_vsite_t* vsite,
- rvec x[],
- real dt,
- rvec* v,
- const t_iparams ip[],
- const t_ilist ilist[],
- int ePBC,
- gmx_bool bMolPBC,
- const t_commrec* cr,
- const matrix box)
+void construct_vsites(const gmx_vsite_t* vsite,
+ rvec x[],
+ real dt,
+ rvec* v,
+ ArrayRef<const t_iparams> ip,
+ ArrayRef<const InteractionList> ilist,
+ PbcType pbcType,
+ gmx_bool bMolPBC,
+ const t_commrec* cr,
+ const matrix box)
{
const bool useDomdec = (vsite != nullptr && vsite->useDomdec);
GMX_ASSERT(!useDomdec || (cr != nullptr && DOMAINDECOMP(cr)),
"When vsites are set up with domain decomposition, we need a valid commrec");
// TODO: Remove this assertion when we remove charge groups
- GMX_ASSERT(vsite != nullptr || ePBC == epbcNONE,
+ GMX_ASSERT(vsite != nullptr || pbcType == PbcType::No,
"Without a vsite struct we can not do PBC (in case we have charge groups)");
t_pbc pbc, *pbc_null;
* when we have at least 3 domains along each dimension. Currently we
* do not optimize this case.
*/
- if (ePBC != epbcNONE && (useDomdec || bMolPBC)
+ if (pbcType != PbcType::No && (useDomdec || bMolPBC)
&& !(vsite != nullptr && vsite->numInterUpdategroupVsites == 0))
{
/* This is wasting some CPU time as we now do this multiple times
*/
ivec null_ivec;
clear_ivec(null_ivec);
- pbc_null = set_pbc_dd(&pbc, ePBC, useDomdec ? cr->dd->nc : null_ivec, FALSE, box);
+ pbc_null = set_pbc_dd(&pbc, pbcType, useDomdec ? cr->dd->numCells : null_ivec, FALSE, box);
}
else
{
}
}
-static void spread_vsite2(const t_iatom ia[],
- real a,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite2(const t_iatom ia[], real a, const rvec x[], rvec f[], rvec fshift[], const t_pbc* pbc)
{
rvec fi, fj, dx;
t_iatom av, ai, aj;
- ivec di;
int siv, sij;
av = ia[1];
rvec_inc(f[aj], fj);
/* 6 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, av), di);
- siv = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), di);
- sij = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
siv = pbc_dx_aiuc(pbc, x[ai], x[av], dx);
sij = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
{
const gmx_molblock_t& molb = mtop.molblock[mb];
const gmx_moltype_t& molt = mtop.moltype[molb.type];
- if (vsiteIlistNrCount(molt.ilist.data()) > 0)
+ if (vsiteIlistNrCount(molt.ilist) > 0)
{
int atomOffset = mtop.moleculeBlockIndices[mb].globalAtomStart;
for (int mol = 0; mol < molb.nmol; mol++)
{
- t_ilist ilist[F_NRE];
- for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
- {
- ilist[ftype].nr = molt.ilist[ftype].size();
- ilist[ftype].iatoms = const_cast<t_iatom*>(molt.ilist[ftype].iatoms.data());
- }
-
construct_vsites(nullptr, as_rvec_array(x.data()) + atomOffset, 0.0, nullptr,
- mtop.ffparams.iparams.data(), ilist, epbcNONE, TRUE, nullptr, nullptr);
+ mtop.ffparams.iparams, molt.ilist, PbcType::No, TRUE, nullptr, nullptr);
atomOffset += molt.atoms.nr;
}
}
}
}
-static void spread_vsite2FD(const t_iatom ia[],
- real a,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite2FD(const t_iatom ia[],
+ real a,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
const int av = ia[1];
const int ai = ia[2];
if (fshift)
{
int svi;
- if (g)
- {
- ivec di;
- ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sji = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
rvec xvi;
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
/* TOTAL: 38 flops */
}
-static void spread_vsite3(const t_iatom ia[],
- real a,
- real b,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite3(const t_iatom ia[], real a, real b, const rvec x[], rvec f[], rvec fshift[], const t_pbc* pbc)
{
rvec fi, fj, fk, dx;
int av, ai, aj, ak;
- ivec di;
int siv, sij, sik;
av = ia[1];
rvec_inc(f[ak], fk);
/* 9 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ia[1]), di);
- siv = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), di);
- sij = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, ak), di);
- sik = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
siv = pbc_dx_aiuc(pbc, x[ai], x[av], dx);
sij = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
/* TOTAL: 20 flops */
}
-static void spread_vsite3FD(const t_iatom ia[],
- real a,
- real b,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite3FD(const t_iatom ia[],
+ real a,
+ real b,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
real fproj, a1;
rvec xvi, xij, xjk, xix, fv, temp;
t_iatom av, ai, aj, ak;
int svi, sji, skj;
- ivec di;
av = ia[1];
ai = ia[2];
f[ak][ZZ] += a * temp[ZZ];
/* 19 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sji = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
- skj = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
}
/* TOTAL: 61 flops */
}
-static void spread_vsite3FAD(const t_iatom ia[],
- real a,
- real b,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite3FAD(const t_iatom ia[],
+ real a,
+ real b,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
rvec xvi, xij, xjk, xperp, Fpij, Fppp, fv, f1, f2, f3;
real a1, b1, c1, c2, invdij, invdij2, invdp, fproj;
t_iatom av, ai, aj, ak;
int svi, sji, skj, d;
- ivec di;
av = ia[1];
ai = ia[2];
f[ak][ZZ] += f2[ZZ];
/* 30 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sji = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
- skj = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
}
/* TOTAL: 113 flops */
}
-static void spread_vsite3OUT(const t_iatom ia[],
- real a,
- real b,
- real c,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite3OUT(const t_iatom ia[],
+ real a,
+ real b,
+ real c,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
rvec xvi, xij, xik, fv, fj, fk;
real cfx, cfy, cfz;
int av, ai, aj, ak;
- ivec di;
int svi, sji, ski;
av = ia[1];
rvec_inc(f[ak], fk);
/* 15 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sji = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, ai), di);
- ski = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
}
/* TOTAL: 54 flops */
}
-static void spread_vsite4FD(const t_iatom ia[],
- real a,
- real b,
- real c,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite4FD(const t_iatom ia[],
+ real a,
+ real b,
+ real c,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
real fproj, a1;
rvec xvi, xij, xjk, xjl, xix, fv, temp;
int av, ai, aj, ak, al;
- ivec di;
int svi, sji, skj, slj, m;
av = ia[1];
}
/* 26 Flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ia[1]), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sji = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, aj), di);
- skj = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, al), SHIFT_IVEC(g, aj), di);
- slj = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
}
}
-static void spread_vsite4FDN(const t_iatom ia[],
- real a,
- real b,
- real c,
- const rvec x[],
- rvec f[],
- rvec fshift[],
- gmx_bool VirCorr,
- matrix dxdf,
- const t_pbc* pbc,
- const t_graph* g)
+static void spread_vsite4FDN(const t_iatom ia[],
+ real a,
+ real b,
+ real c,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ gmx_bool VirCorr,
+ matrix dxdf,
+ const t_pbc* pbc)
{
rvec xvi, xij, xik, xil, ra, rb, rja, rjb, rab, rm, rt;
rvec fv, fj, fk, fl;
real invrm, denom;
real cfx, cfy, cfz;
- ivec di;
int av, ai, aj, ak, al;
int svi, sij, sik, sil;
rvec_inc(f[al], fl);
/* 21 flops */
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, av), SHIFT_IVEC(g, ai), di);
- svi = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, aj), SHIFT_IVEC(g, ai), di);
- sij = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, ak), SHIFT_IVEC(g, ai), di);
- sik = IVEC2IS(di);
- ivec_sub(SHIFT_IVEC(g, al), SHIFT_IVEC(g, ai), di);
- sil = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
svi = pbc_rvec_sub(pbc, x[av], x[ai], xvi);
}
}
-static int spread_vsiten(const t_iatom ia[],
- const t_iparams ip[],
- const rvec x[],
- rvec f[],
- rvec fshift[],
- const t_pbc* pbc,
- const t_graph* g)
+static int spread_vsiten(const t_iatom ia[],
+ ArrayRef<const t_iparams> ip,
+ const rvec x[],
+ rvec f[],
+ rvec fshift[],
+ const t_pbc* pbc)
{
rvec xv, dx, fi;
int n3, av, i, ai;
real a;
- ivec di;
int siv;
n3 = 3 * ip[ia[0]].vsiten.n;
for (i = 0; i < n3; i += 3)
{
ai = ia[i + 2];
- if (g)
- {
- ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, av), di);
- siv = IVEC2IS(di);
- }
- else if (pbc)
+ if (pbc)
{
siv = pbc_dx_aiuc(pbc, x[ai], xv, dx);
}
}
-static int vsite_count(const t_ilist* ilist, int ftype)
+static int vsite_count(ArrayRef<const InteractionList> ilist, int ftype)
{
if (ftype == F_VSITEN)
{
- return ilist[ftype].nr / 3;
+ return ilist[ftype].size() / 3;
}
else
{
- return ilist[ftype].nr / (1 + interaction_function[ftype].nratoms);
+ return ilist[ftype].size() / (1 + interaction_function[ftype].nratoms);
}
}
-static void spread_vsite_f_thread(const rvec x[],
- rvec f[],
- rvec* fshift,
- gmx_bool VirCorr,
- matrix dxdf,
- t_iparams ip[],
- const t_ilist ilist[],
- const t_graph* g,
- const t_pbc* pbc_null)
+static void spread_vsite_f_thread(const rvec x[],
+ rvec f[],
+ rvec* fshift,
+ gmx_bool VirCorr,
+ matrix dxdf,
+ ArrayRef<const t_iparams> ip,
+ ArrayRef<const InteractionList> ilist,
+ const t_pbc* pbc_null)
{
const PbcMode pbcMode = getPbcMode(pbc_null);
/* We need another pbc pointer, as with charge groups we switch per vsite */
* higher type vsites from lower types */
for (int ftype = c_ftypeVsiteEnd - 1; ftype >= c_ftypeVsiteStart; ftype--)
{
- if (ilist[ftype].nr == 0)
+ if (ilist[ftype].empty())
{
continue;
}
{ // TODO remove me
int nra = interaction_function[ftype].nratoms;
int inc = 1 + nra;
- int nr = ilist[ftype].nr;
+ int nr = ilist[ftype].size();
- const t_iatom* ia = ilist[ftype].iatoms;
+ const t_iatom* ia = ilist[ftype].iatoms.data();
if (pbcMode == PbcMode::all)
{
/* Construct the vsite depending on type */
switch (ftype)
{
- case F_VSITE2: spread_vsite2(ia, a1, x, f, fshift, pbc_null2, g); break;
+ case F_VSITE2: spread_vsite2(ia, a1, x, f, fshift, pbc_null2); break;
case F_VSITE2FD:
- spread_vsite2FD(ia, a1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite2FD(ia, a1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
case F_VSITE3:
b1 = ip[tp].vsite.b;
- spread_vsite3(ia, a1, b1, x, f, fshift, pbc_null2, g);
+ spread_vsite3(ia, a1, b1, x, f, fshift, pbc_null2);
break;
case F_VSITE3FD:
b1 = ip[tp].vsite.b;
- spread_vsite3FD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite3FD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
case F_VSITE3FAD:
b1 = ip[tp].vsite.b;
- spread_vsite3FAD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite3FAD(ia, a1, b1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
case F_VSITE3OUT:
b1 = ip[tp].vsite.b;
c1 = ip[tp].vsite.c;
- spread_vsite3OUT(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite3OUT(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
case F_VSITE4FD:
b1 = ip[tp].vsite.b;
c1 = ip[tp].vsite.c;
- spread_vsite4FD(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite4FD(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
case F_VSITE4FDN:
b1 = ip[tp].vsite.b;
c1 = ip[tp].vsite.c;
- spread_vsite4FDN(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2, g);
+ spread_vsite4FDN(ia, a1, b1, c1, x, f, fshift, VirCorr, dxdf, pbc_null2);
break;
- case F_VSITEN: inc = spread_vsiten(ia, ip, x, f, fshift, pbc_null2, g); break;
+ case F_VSITEN: inc = spread_vsiten(ia, ip, x, f, fshift, pbc_null2); break;
default:
gmx_fatal(FARGS, "No such vsite type %d in %s, line %d", ftype, __FILE__, __LINE__);
}
void spread_vsite_f(const gmx_vsite_t* vsite,
const rvec* gmx_restrict x,
rvec* gmx_restrict f,
- rvec* gmx_restrict fshift,
- gmx_bool VirCorr,
- matrix vir,
- t_nrnb* nrnb,
- const t_idef* idef,
- int ePBC,
- gmx_bool bMolPBC,
- const t_graph* g,
- const matrix box,
- const t_commrec* cr,
- gmx_wallcycle* wcycle)
+ rvec* gmx_restrict fshift,
+ gmx_bool VirCorr,
+ matrix vir,
+ t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ PbcType pbcType,
+ gmx_bool bMolPBC,
+ const matrix box,
+ const t_commrec* cr,
+ gmx_wallcycle* wcycle)
{
wallcycle_start(wcycle, ewcVSITESPREAD);
const bool useDomdec = vsite->useDomdec;
/* This is wasting some CPU time as we now do this multiple times
* per MD step.
*/
- pbc_null = set_pbc_dd(&pbc, ePBC, useDomdec ? cr->dd->nc : nullptr, FALSE, box);
+ pbc_null = set_pbc_dd(&pbc, pbcType, useDomdec ? cr->dd->numCells : nullptr, FALSE, box);
}
else
{
{
clear_mat(dxdf);
}
- spread_vsite_f_thread(x, f, fshift, VirCorr, dxdf, idef->iparams, idef->il, g, pbc_null);
+ spread_vsite_f_thread(x, f, fshift, VirCorr, dxdf, idef.iparams, idef.il, pbc_null);
if (VirCorr)
{
clear_mat(vsite->tData[vsite->nthreads]->dxdf);
}
spread_vsite_f_thread(x, f, fshift, VirCorr, vsite->tData[vsite->nthreads]->dxdf,
- idef->iparams, vsite->tData[vsite->nthreads]->ilist, g, pbc_null);
+ idef.iparams, vsite->tData[vsite->nthreads]->ilist, pbc_null);
#pragma omp parallel num_threads(vsite->nthreads)
{
copy_rvec(f[idTask->vsite[i]], idTask->force[idTask->vsite[i]]);
}
spread_vsite_f_thread(x, as_rvec_array(idTask->force.data()), fshift_t, VirCorr,
- tData.dxdf, idef->iparams, tData.idTask.ilist, g, pbc_null);
+ tData.dxdf, idef.iparams, tData.idTask.ilist, pbc_null);
/* We need a barrier before reducing forces below
* that have been produced by a different thread above.
}
/* Spread the vsites that spread locally only */
- spread_vsite_f_thread(x, f, fshift_t, VirCorr, tData.dxdf, idef->iparams,
- tData.ilist, g, pbc_null);
+ spread_vsite_f_thread(x, f, fshift_t, VirCorr, tData.dxdf, idef.iparams,
+ tData.ilist, pbc_null);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
dd_move_f_vsites(cr->dd, f, fshift);
}
- inc_nrnb(nrnb, eNR_VSITE2, vsite_count(idef->il, F_VSITE2));
- inc_nrnb(nrnb, eNR_VSITE2FD, vsite_count(idef->il, F_VSITE2FD));
- inc_nrnb(nrnb, eNR_VSITE3, vsite_count(idef->il, F_VSITE3));
- inc_nrnb(nrnb, eNR_VSITE3FD, vsite_count(idef->il, F_VSITE3FD));
- inc_nrnb(nrnb, eNR_VSITE3FAD, vsite_count(idef->il, F_VSITE3FAD));
- inc_nrnb(nrnb, eNR_VSITE3OUT, vsite_count(idef->il, F_VSITE3OUT));
- inc_nrnb(nrnb, eNR_VSITE4FD, vsite_count(idef->il, F_VSITE4FD));
- inc_nrnb(nrnb, eNR_VSITE4FDN, vsite_count(idef->il, F_VSITE4FDN));
- inc_nrnb(nrnb, eNR_VSITEN, vsite_count(idef->il, F_VSITEN));
+ inc_nrnb(nrnb, eNR_VSITE2, vsite_count(idef.il, F_VSITE2));
+ inc_nrnb(nrnb, eNR_VSITE2FD, vsite_count(idef.il, F_VSITE2FD));
+ inc_nrnb(nrnb, eNR_VSITE3, vsite_count(idef.il, F_VSITE3));
+ inc_nrnb(nrnb, eNR_VSITE3FD, vsite_count(idef.il, F_VSITE3FD));
+ inc_nrnb(nrnb, eNR_VSITE3FAD, vsite_count(idef.il, F_VSITE3FAD));
+ inc_nrnb(nrnb, eNR_VSITE3OUT, vsite_count(idef.il, F_VSITE3OUT));
+ inc_nrnb(nrnb, eNR_VSITE4FD, vsite_count(idef.il, F_VSITE4FD));
+ inc_nrnb(nrnb, eNR_VSITE4FDN, vsite_count(idef.il, F_VSITE4FDN));
+ inc_nrnb(nrnb, eNR_VSITEN, vsite_count(idef.il, F_VSITEN));
wallcycle_stop(wcycle, ewcVSITESPREAD);
}
* taskIndex[] is set for all vsites in our range, either to our local tasks
* or to the single last task as taskIndex[]=2*nthreads.
*/
-static void assignVsitesToThread(VsiteThread* tData,
- int thread,
- int nthread,
- int natperthread,
- gmx::ArrayRef<int> taskIndex,
- const t_ilist* ilist,
- const t_iparams* ip,
- const unsigned short* ptype)
+static void assignVsitesToThread(VsiteThread* tData,
+ int thread,
+ int nthread,
+ int natperthread,
+ gmx::ArrayRef<int> taskIndex,
+ ArrayRef<const InteractionList> ilist,
+ ArrayRef<const t_iparams> ip,
+ const unsigned short* ptype)
{
for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
{
- tData->ilist[ftype].nr = 0;
- tData->idTask.ilist[ftype].nr = 0;
+ tData->ilist[ftype].clear();
+ tData->idTask.ilist[ftype].clear();
- int nral1 = 1 + NRAL(ftype);
- int inc = nral1;
- t_iatom* iat = ilist[ftype].iatoms;
- for (int i = 0; i < ilist[ftype].nr;)
+ int nral1 = 1 + NRAL(ftype);
+ int inc = nral1;
+ const int* iat = ilist[ftype].iatoms.data();
+ for (int i = 0; i < ilist[ftype].size();)
{
if (ftype == F_VSITEN)
{
if (task == thread || task == nthread + thread)
{
/* Copy this vsite to the thread data struct of thread */
- t_ilist* il_task;
+ InteractionList* il_task;
if (task == thread)
{
il_task = &tData->ilist[ftype];
{
il_task = &tData->idTask.ilist[ftype];
}
- /* Ensure we have sufficient memory allocated */
- if (il_task->nr + inc > il_task->nalloc)
- {
- il_task->nalloc = over_alloc_large(il_task->nr + inc);
- srenew(il_task->iatoms, il_task->nalloc);
- }
/* Copy the vsite data to the thread-task local array */
- for (int j = i; j < i + inc; j++)
- {
- il_task->iatoms[il_task->nr++] = iat[j];
- }
+ il_task->push_back(iat[i], nral1 - 1, iat + i + 1);
if (task == nthread + thread)
{
/* This vsite write outside our own task force block.
}
/*! \brief Assign all vsites with taskIndex[]==task to task tData */
-static void assignVsitesToSingleTask(VsiteThread* tData,
- int task,
- gmx::ArrayRef<const int> taskIndex,
- const t_ilist* ilist,
- const t_iparams* ip)
+static void assignVsitesToSingleTask(VsiteThread* tData,
+ int task,
+ gmx::ArrayRef<const int> taskIndex,
+ ArrayRef<const InteractionList> ilist,
+ ArrayRef<const t_iparams> ip)
{
for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
{
- tData->ilist[ftype].nr = 0;
- tData->idTask.ilist[ftype].nr = 0;
+ tData->ilist[ftype].clear();
+ tData->idTask.ilist[ftype].clear();
- int nral1 = 1 + NRAL(ftype);
- int inc = nral1;
- t_iatom* iat = ilist[ftype].iatoms;
- t_ilist* il_task = &tData->ilist[ftype];
+ int nral1 = 1 + NRAL(ftype);
+ int inc = nral1;
+ const int* iat = ilist[ftype].iatoms.data();
+ InteractionList* il_task = &tData->ilist[ftype];
- for (int i = 0; i < ilist[ftype].nr;)
+ for (int i = 0; i < ilist[ftype].size();)
{
if (ftype == F_VSITEN)
{
/* Check if the vsite is assigned to our task */
if (taskIndex[iat[1 + i]] == task)
{
- /* Ensure we have sufficient memory allocated */
- if (il_task->nr + inc > il_task->nalloc)
- {
- il_task->nalloc = over_alloc_large(il_task->nr + inc);
- srenew(il_task->iatoms, il_task->nalloc);
- }
/* Copy the vsite data to the thread-task local array */
- for (int j = i; j < i + inc; j++)
- {
- il_task->iatoms[il_task->nr++] = iat[j];
- }
+ il_task->push_back(iat[i], inc - 1, iat + i + 1);
}
i += inc;
}
}
-void split_vsites_over_threads(const t_ilist* ilist, const t_iparams* ip, const t_mdatoms* mdatoms, gmx_vsite_t* vsite)
+void split_vsites_over_threads(ArrayRef<const InteractionList> ilist,
+ ArrayRef<const t_iparams> ip,
+ const t_mdatoms* mdatoms,
+ gmx_vsite_t* vsite)
{
int vsite_atom_range, natperthread;
{ // TODO remove me
if (ftype != F_VSITEN)
{
- int nral1 = 1 + NRAL(ftype);
- const t_iatom* iat = ilist[ftype].iatoms;
- for (int i = 0; i < ilist[ftype].nr; i += nral1)
+ int nral1 = 1 + NRAL(ftype);
+ ArrayRef<const int> iat = ilist[ftype].iatoms;
+ for (int i = 0; i < ilist[ftype].size(); i += nral1)
{
for (int j = i + 1; j < i + nral1; j++)
{
{
int vs_ind_end;
- const t_iatom* iat = ilist[ftype].iatoms;
+ ArrayRef<const int> iat = ilist[ftype].iatoms;
int i = 0;
- while (i < ilist[ftype].nr)
+ while (i < ilist[ftype].size())
{
/* The 3 below is from 1+NRAL(ftype)=3 */
vs_ind_end = i + ip[iat[i]].vsiten.n * 3;
for (int ftype = c_ftypeVsiteStart; ftype < c_ftypeVsiteEnd; ftype++)
{
- if (ilist[ftype].nr > 0)
+ if (!ilist[ftype].empty())
{
fprintf(debug, "%-20s thread dist:", interaction_function[ftype].longname);
for (int th = 0; th < vsite->nthreads + 1; th++)
{
- fprintf(debug, " %4d %4d ", vsite->tData[th]->ilist[ftype].nr,
- vsite->tData[th]->idTask.ilist[ftype].nr);
+ fprintf(debug, " %4d %4d ", vsite->tData[th]->ilist[ftype].size(),
+ vsite->tData[th]->idTask.ilist[ftype].size());
}
fprintf(debug, "\n");
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_localtop_t;
struct gmx_mtop_t;
struct t_commrec;
-struct t_graph;
-struct t_ilist;
+struct InteractionList;
struct t_mdatoms;
struct t_nrnb;
struct gmx_wallcycle;
struct VsiteThread;
+enum class PbcType : int;
namespace gmx
{
/*! \brief Create positions of vsite atoms based for the local system
*
* \param[in] vsite The vsite struct, when nullptr is passed, no MPI and no multi-threading
- * is used \param[in,out] x The coordinates \param[in] dt The time step \param[in,out]
- * v When != nullptr, velocities for vsites are set as displacement/dt \param[in] ip
- * Interaction parameters \param[in] ilist The interaction list \param[in] ePBC The
- * type of periodic boundary conditions \param[in] bMolPBC When true, molecules are broken over
- * PBC \param[in] cr The communication record \param[in] box The box
+ * is used
+ * \param[in,out] x The coordinates
+ * \param[in] dt The time step
+ * \param[in,out] v When != nullptr, velocities for vsites are set as displacement/dt
+ * \param[in] ip Interaction parameters
+ * \param[in] ilist The interaction list
+ * \param[in] pbcType The type of periodic boundary conditions
+ * \param[in] bMolPBC When true, molecules are broken over PBC
+ * \param[in] cr The communication record
+ * \param[in] box The box
*/
-void construct_vsites(const gmx_vsite_t* vsite,
- rvec x[],
- real dt,
- rvec v[],
- const t_iparams ip[],
- const t_ilist ilist[],
- int ePBC,
- gmx_bool bMolPBC,
- const t_commrec* cr,
- const matrix box);
+void construct_vsites(const gmx_vsite_t* vsite,
+ rvec x[],
+ real dt,
+ rvec v[],
+ gmx::ArrayRef<const t_iparams> ip,
+ gmx::ArrayRef<const InteractionList> ilist,
+ PbcType pbcType,
+ gmx_bool bMolPBC,
+ const t_commrec* cr,
+ const matrix box);
/*! \brief Create positions of vsite atoms for the whole system assuming all molecules are wholex
*
*/
void constructVsitesGlobal(const gmx_mtop_t& mtop, gmx::ArrayRef<gmx::RVec> x);
-void spread_vsite_f(const gmx_vsite_t* vsite,
- const rvec x[],
- rvec f[],
- rvec* fshift,
- gmx_bool VirCorr,
- matrix vir,
- t_nrnb* nrnb,
- const t_idef* idef,
- int ePBC,
- gmx_bool bMolPBC,
- const t_graph* g,
- const matrix box,
- const t_commrec* cr,
- gmx_wallcycle* wcycle);
+void spread_vsite_f(const gmx_vsite_t* vsite,
+ const rvec x[],
+ rvec f[],
+ rvec* fshift,
+ gmx_bool VirCorr,
+ matrix vir,
+ t_nrnb* nrnb,
+ const InteractionDefinitions& idef,
+ PbcType pbcType,
+ gmx_bool bMolPBC,
+ const matrix box,
+ const t_commrec* cr,
+ gmx_wallcycle* wcycle);
/* Spread the force operating on the vsite atoms on the surrounding atoms.
* If fshift!=NULL also update the shift forces.
* If VirCorr=TRUE add the virial correction for non-linear vsite constructs
*/
std::unique_ptr<gmx_vsite_t> initVsite(const gmx_mtop_t& mtop, const t_commrec* cr);
-void split_vsites_over_threads(const t_ilist* ilist,
- const t_iparams* ip,
- const t_mdatoms* mdatoms,
- gmx_vsite_t* vsite);
+void split_vsites_over_threads(gmx::ArrayRef<const InteractionList> ilist,
+ gmx::ArrayRef<const t_iparams> ip,
+ const t_mdatoms* mdatoms,
+ gmx_vsite_t* vsite);
/* Divide the vsite work-load over the threads.
* Should be called at the end of the domain decomposition.
*/
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdtypes/forceoutput.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/mdatom.h"
const int nwall = ir.nwall;
const int ngid = ir.opts.ngener;
const int ntype = fr.ntype;
- const real* nbfp = fr.nbfp;
+ const real* nbfp = fr.nbfp.data();
const int* egp_flags = fr.egp_flags;
for (int w = 0; w < nwall; w++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct SimulationGroups;
struct t_forcerec;
-struct t_idef;
struct t_inputrec;
struct t_mdatoms;
struct t_nrnb;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#ifndef GMX_MDLIB_QMMOPAC_H
-#define GMX_MDLIB_QMMOPAC_H
-#include "gromacs/mdlib/qmmm.h"
+#include "gmxpre.h"
-/*! \brief
- * Initialize mopac datastructures.
- *
- * \param[in] qm QM forcerec.
- */
-void init_mopac(t_QMrec* qm);
+#include "wholemoleculetransform.h"
-/*! \brief
- * Run calculation with MOPAC.
- *
- * \param[in] qm QM part of forcerec.
- * \param[in] mm MM part of forcerec.
- * \param[in] f Force vector.
- * \param[in] fshift Force shift vector.
- */
-real call_mopac(t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+#include "gromacs/topology/mtop_util.h"
-/*! \brief
- * Run surface-hopping calculation with MOPAC.
- *
- * \param[in] qm QM part of forcerec.
- * \param[in] mm MM part of forcerec.
- * \param[in] f Force vector.
- * \param[in] fshift Force shift vector.
- */
-real call_mopac_SH(t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+namespace gmx
+{
+
+WholeMoleculeTransform::WholeMoleculeTransform(const gmx_mtop_t& mtop, const PbcType pbcType) :
+ pbcType_(pbcType)
+{
+ gmx_localtop_t localTop(mtop.ffparams);
+
+ gmx_mtop_generate_local_top(mtop, &localTop, false);
+
+ graph_ = mk_graph(localTop.idef, mtop.natoms);
+
+ wholeMoleculeCoordinates_.resize(mtop.natoms);
+}
+
+void WholeMoleculeTransform::updateForAtomPbcJumps(ArrayRef<const RVec> x, const matrix box)
+{
+ mk_mshift(nullptr, &graph_, pbcType_, box, as_rvec_array(x.data()));
+}
+
+ArrayRef<const RVec> WholeMoleculeTransform::wholeMoleculeCoordinates(ArrayRef<const RVec> x, const matrix box)
+{
+ shift_x(&graph_, box, as_rvec_array(x.data()), as_rvec_array(wholeMoleculeCoordinates_.data()));
+
+ return wholeMoleculeCoordinates_;
+}
-#endif
+} // namespace gmx
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ *
+ * \brief Declares the WholeMolecules class for generating whole molecules
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_mdlib
+ * \inlibraryapi
+ */
+#ifndef GMX_MDLIB_WHOLEMOLECULETRANSFORM_H
+#define GMX_MDLIB_WHOLEMOLECULETRANSFORM_H
+
+#include <vector>
+
+#include "gromacs/math/vectypes.h"
+#include "gromacs/pbcutil/mshift.h"
+#include "gromacs/utility/arrayref.h"
+
+struct gmx_mtop_t;
+enum class PbcType : int;
+
+namespace gmx
+{
+
+/*! \libinternal
+ * \brief This class manages a coordinate buffer with molecules not split
+ * over periodic boundary conditions for use in force calculations
+ * which require whole molecules.
+ *
+ * Note: This class should not be used for computation of forces which
+ * have virial contributions through shift forces.
+ */
+class WholeMoleculeTransform
+{
+public:
+ /*! \brief Constructor */
+ WholeMoleculeTransform(const gmx_mtop_t& mtop, PbcType pbcType);
+
+ /*! \brief Updates the graph when atoms have been shifted by periodic vectors */
+ void updateForAtomPbcJumps(ArrayRef<const RVec> x, const matrix box);
+
+ /*! \brief Create and return coordinates with whole molecules for input coordinates \p x
+ *
+ * \param[in] x Input coordinates, should not have periodic displacement compared
+ * with the coordinates passed in the last call to \p updateForAtomPbcJumps().
+ * \param[in] box The current periodic image vectors
+ *
+ * Note: this operation is not free. If you need whole molecules coordinates
+ * more than once during the force calculation, store the result and reuse it.
+ */
+ ArrayRef<const RVec> wholeMoleculeCoordinates(ArrayRef<const RVec> x, const matrix box);
+
+private:
+ //! The type of PBC
+ PbcType pbcType_;
+ //! The graph
+ t_graph graph_;
+ //! Buffer for storing coordinates for whole molecules
+ std::vector<RVec> wholeMoleculeCoordinates_;
+};
+
+} // namespace gmx
+
+#endif
//! The coordinate-swapping session.
t_swap* swap;
//! Full system topology.
- gmx_mtop_t* top_global;
+ const gmx_mtop_t* top_global;
//! Helper struct for force calculations.
t_fcdata* fcd;
//! Full simulation state (only non-nullptr on master rank).
#include "gromacs/domdec/domdec.h"
#include "gromacs/domdec/domdec_network.h"
#include "gromacs/domdec/domdec_struct.h"
+#include "gromacs/domdec/gpuhaloexchange.h"
#include "gromacs/domdec/mdsetup.h"
#include "gromacs/domdec/partition.h"
#include "gromacs/essentialdynamics/edsam.h"
-#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/fileio/trxio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/imd/imd.h"
#include "gromacs/listed_forces/manage_threading.h"
#include "gromacs/mdlib/tgroup.h"
#include "gromacs/mdlib/trajectory_writing.h"
#include "gromacs/mdlib/update.h"
-#include "gromacs/mdlib/update_constrain_cuda.h"
+#include "gromacs/mdlib/update_constrain_gpu.h"
#include "gromacs/mdlib/vcm.h"
#include "gromacs/mdlib/vsite.h"
#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/modularsimulator/energyelement.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/nbnxm/nbnxm.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/output.h"
#include "gromacs/pulling/pull.h"
rvec mu_tot;
matrix pressureCouplingMu, M;
gmx_repl_ex_t repl_ex = nullptr;
- gmx_localtop_t top;
PaddedHostVector<gmx::RVec> f{};
gmx_global_stat_t gstat;
- t_graph* graph = nullptr;
gmx_shellfc_t* shellfc;
gmx_bool bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
gmx_bool bTemp, bPres, bTrotter;
int nstglobalcomm = computeGlobalCommunicationPeriod(mdlog, ir, cr);
bGStatEveryStep = (nstglobalcomm == 1);
- SimulationGroups* groups = &top_global->groups;
+ const SimulationGroups* groups = &top_global->groups;
std::unique_ptr<EssentialDynamics> ed = nullptr;
if (opt2bSet("-ei", nfile, fnm))
t_state* state;
+ gmx_localtop_t top(top_global->ffparams);
+
auto mdatoms = mdAtoms->mdatoms();
- std::unique_ptr<UpdateConstrainCuda> integrator;
+ std::unique_ptr<UpdateConstrainGpu> integrator;
if (DOMAINDECOMP(cr))
{
- dd_init_local_top(*top_global, &top);
-
stateInstance = std::make_unique<t_state>();
state = stateInstance.get();
dd_init_local_state(cr->dd, state_global, state);
else
{
state_change_natoms(state_global, state_global->natoms);
- f.resizeWithPadding(state_global->natoms);
/* Copy the pointer to the global state */
state = state_global;
/* Generate and initialize new topology */
- mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &graph, mdAtoms, constr, vsite, shellfc);
+ mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &f, mdAtoms, constr, vsite, shellfc);
upd.setNumAtoms(state->natoms);
}
StatePropagatorDataGpu* stateGpu = fr->stateGpu;
+ // TODO: the assertions below should be handled by UpdateConstraintsBuilder.
if (useGpuForUpdate)
{
GMX_RELEASE_ASSERT(!DOMAINDECOMP(cr) || ddUsesUpdateGroups(*cr->dd) || constr == nullptr
"Constraints pulling is not supported with the GPU update.\n");
GMX_RELEASE_ASSERT(fcd->orires.nr == 0,
"Orientation restraints are not supported with the GPU update.\n");
- GMX_RELEASE_ASSERT(ir->efep == efepNO,
- "Free energy perturbations are not supported with the GPU update.");
- GMX_RELEASE_ASSERT(graph == nullptr, "The graph is not supported with GPU update.");
+ GMX_RELEASE_ASSERT(
+ ir->efep == efepNO
+ || (!haveFreeEnergyType(*ir, efptBONDED) && !haveFreeEnergyType(*ir, efptMASS)),
+ "Free energy perturbation of masses and constraints are not supported with the GPU "
+ "update.");
if (constr != nullptr && constr->numConstraintsTotal() > 0)
{
{
GMX_LOG(mdlog.info).asParagraph().appendText("Updating coordinates on the GPU.");
}
- integrator = std::make_unique<UpdateConstrainCuda>(
- *ir, *top_global, stateGpu->getUpdateStream(), stateGpu->xUpdatedOnDevice());
-
- t_pbc pbc;
- set_pbc(&pbc, epbcXYZ, state->box);
- integrator->setPbc(&pbc);
+ GMX_RELEASE_ASSERT(fr->deviceStreamManager != nullptr,
+ "Device stream manager should be initialized in order to use GPU "
+ "update-constraints.");
+ GMX_RELEASE_ASSERT(
+ fr->deviceStreamManager->streamIsValid(gmx::DeviceStreamType::UpdateAndConstraints),
+ "Update stream should be initialized in order to use GPU "
+ "update-constraints.");
+ integrator = std::make_unique<UpdateConstrainGpu>(
+ *ir, *top_global, fr->deviceStreamManager->context(),
+ fr->deviceStreamManager->stream(gmx::DeviceStreamType::UpdateAndConstraints),
+ stateGpu->xUpdatedOnDevice());
+
+ integrator->setPbc(PbcType::Xyz, state->box);
}
if (useGpuForPme || (useGpuForNonbonded && useGpuForBufferOps) || useGpuForUpdate)
{
/* Construct the virtual sites for the initial configuration */
construct_vsites(vsite, state->x.rvec_array(), ir->delta_t, nullptr, top.idef.iparams,
- top.idef.il, fr->ePBC, fr->bMolPBC, cr, state->box);
+ top.idef.il, fr->pbcType, fr->bMolPBC, cr, state->box);
}
}
bool hasReadEkinState = MASTER(cr) ? state_global->ekinstate.hasReadEkinState : false;
if (PAR(cr))
{
- gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr);
+ gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr->mpi_comm_mygroup);
}
if (hasReadEkinState)
{
cglo_flags_iteration |= CGLO_STOPCM;
cglo_flags_iteration &= ~CGLO_TEMPERATURE;
}
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, nullptr, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller,
- state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, &vcm, nullptr, enerd, force_vir, shake_vir, total_vir, pres, constr,
+ &nullSignaller, state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
cglo_flags_iteration
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
: 0));
/* At initialization, do not pass x with acceleration-correction mode
* to avoid (incorrect) correction of the initial coordinates.
*/
- rvec* xPtr = nullptr;
- if (vcm.mode != ecmLINEAR_ACCELERATION_CORRECTION)
- {
- xPtr = state->x.rvec_array();
- }
- process_and_stopcm_grp(fplog, &vcm, *mdatoms, xPtr, state->v.rvec_array());
+ auto x = (vcm.mode == ecmLINEAR_ACCELERATION_CORRECTION) ? ArrayRef<RVec>()
+ : makeArrayRef(state->x);
+ process_and_stopcm_grp(fplog, &vcm, *mdatoms, x, makeArrayRef(state->v));
inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
}
}
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global, &top,
- state->x.rvec_array(), state->box,
+ makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
if (ir->eI == eiVVAK)
{
kinetic energy calculation. This minimized excess variables, but
perhaps loses some logic?*/
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, nullptr, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller,
- state->box, nullptr, &bSumEkinhOld, cglo_flags & ~CGLO_PRESSURE);
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, &vcm, nullptr, enerd, force_vir, shake_vir, total_vir, pres, constr,
+ &nullSignaller, state->box, nullptr, &bSumEkinhOld, cglo_flags & ~CGLO_PRESSURE);
}
/* Calculate the initial half step temperature, and save the ekinh_old */
"The initial step is not consistent across multi simulations which "
"share the state");
}
- gmx_barrier(cr);
+ gmx_barrier(cr->mpi_comm_mygroup);
}
else
{
/* Correct the new box if it is too skewed */
if (inputrecDynamicBox(ir))
{
- if (correct_box(fplog, step, state->box, graph))
+ if (correct_box(fplog, step, state->box))
{
bMasterState = TRUE;
// If update is offloaded, it should be informed about the box size change
if (useGpuForUpdate)
{
- t_pbc pbc;
- set_pbc(&pbc, epbcXYZ, state->box);
- integrator->setPbc(&pbc);
+ integrator->setPbc(PbcType::Xyz, state->box);
}
}
}
fr, vsite, constr, nrnb, wcycle, do_verbose && !bPMETunePrinting);
shouldCheckNumberOfBondedInteractions = true;
upd.setNumAtoms(state->natoms);
+
+ // Allocate or re-size GPU halo exchange object, if necessary
+ if (havePPDomainDecomposition(cr) && simulationWork.useGpuHaloExchange
+ && useGpuForNonbonded && is1D(*cr->dd))
+ {
+ GMX_RELEASE_ASSERT(fr->deviceStreamManager != nullptr,
+ "GPU device manager has to be initialized to use GPU "
+ "version of halo exchange.");
+ // TODO remove need to pass local stream into GPU halo exchange - Issue #3093
+ constructGpuHaloExchange(mdlog, *cr, *fr->deviceStreamManager);
+ }
}
}
if (MASTER(cr) && do_log)
{
- energyOutput.printHeader(fplog, step, t); /* can we improve the information printed here? */
+ gmx::EnergyOutput::printHeader(fplog, step,
+ t); /* can we improve the information printed here? */
}
if (ir->efep != efepNO)
/* We need the kinetic energy at minus the half step for determining
* the full step kinetic energy and possibly for T-coupling.*/
/* This may not be quite working correctly yet . . . . */
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, wcycle, enerd,
- nullptr, nullptr, nullptr, nullptr, mu_tot, constr, &nullSignaller,
- state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, &vcm, wcycle, enerd, nullptr, nullptr, nullptr, nullptr, constr,
+ &nullSignaller, state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
CGLO_GSTAT | CGLO_TEMPERATURE | CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS);
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global,
- &top, state->x.rvec_array(), state->box,
+ &top, makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
}
clear_mat(force_vir);
imdSession, pull_work, bNS, force_flags, &top, constr, enerd, fcd,
state->natoms, state->x.arrayRefWithPadding(),
state->v.arrayRefWithPadding(), state->box, state->lambda, &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, graph,
- shellfc, fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
+ f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, shellfc,
+ fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
}
else
{
*/
do_force(fplog, cr, ms, ir, awh.get(), enforcedRotation, imdSession, pull_work, step,
nrnb, wcycle, &top, state->box, state->x.arrayRefWithPadding(), &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, graph,
- fr, runScheduleWork, vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
+ f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, fr,
+ runScheduleWork, vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
(bNS ? GMX_FORCE_NS : 0) | force_flags, ddBalanceRegionHandler);
}
if (bGStat || do_per_step(step - 1, nstglobalcomm))
{
wallcycle_stop(wcycle, ewcUPDATE);
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, wcycle, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller,
- state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
- (bGStat ? CGLO_GSTAT : 0) | (bCalcEner ? CGLO_ENERGY : 0)
- | (bTemp ? CGLO_TEMPERATURE : 0) | (bPres ? CGLO_PRESSURE : 0)
- | (bPres ? CGLO_CONSTRAINT : 0) | (bStopCM ? CGLO_STOPCM : 0)
- | (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
- : 0)
- | CGLO_SCALEEKIN);
+ compute_globals(
+ gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, &vcm, wcycle, enerd, force_vir, shake_vir, total_vir, pres, constr,
+ &nullSignaller, state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ (bGStat ? CGLO_GSTAT : 0) | (bCalcEner ? CGLO_ENERGY : 0)
+ | (bTemp ? CGLO_TEMPERATURE : 0) | (bPres ? CGLO_PRESSURE : 0)
+ | (bPres ? CGLO_CONSTRAINT : 0) | (bStopCM ? CGLO_STOPCM : 0)
+ | (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
+ : 0)
+ | CGLO_SCALEEKIN);
/* explanation of above:
a) We compute Ekin at the full time step
if 1) we are using the AveVel Ekin, and it's not the
b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
EkinAveVel because it's needed for the pressure */
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions,
- top_global, &top, state->x.rvec_array(), state->box,
- &shouldCheckNumberOfBondedInteractions);
+ top_global, &top, makeConstArrayRef(state->x),
+ state->box, &shouldCheckNumberOfBondedInteractions);
if (bStopCM)
{
- process_and_stopcm_grp(fplog, &vcm, *mdatoms, state->x.rvec_array(),
- state->v.rvec_array());
+ process_and_stopcm_grp(fplog, &vcm, *mdatoms, makeArrayRef(state->x),
+ makeArrayRef(state->v));
inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
}
wallcycle_start(wcycle, ewcUPDATE);
/* We need the kinetic energy at minus the half step for determining
* the full step kinetic energy and possibly for T-coupling.*/
/* This may not be quite working correctly yet . . . . */
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(),
- state->v.rvec_array(), state->box, state->lambda[efptVDW],
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW],
mdatoms, nrnb, &vcm, wcycle, enerd, nullptr, nullptr, nullptr,
- nullptr, mu_tot, constr, &nullSignaller, state->box, nullptr,
+ nullptr, constr, &nullSignaller, state->box, nullptr,
&bSumEkinhOld, CGLO_GSTAT | CGLO_TEMPERATURE);
wallcycle_start(wcycle, ewcUPDATE);
}
update_sd_second_half(step, &dvdl_constr, ir, mdatoms, state, cr, nrnb, wcycle, &upd,
constr, do_log, do_ene);
- finish_update(ir, mdatoms, state, graph, nrnb, wcycle, &upd, constr);
+ finish_update(ir, mdatoms, state, wcycle, &upd, constr);
}
if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
{
/* erase F_EKIN and F_TEMP here? */
/* just compute the kinetic energy at the half step to perform a trotter step */
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, wcycle, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller, lastbox,
- nullptr, &bSumEkinhOld, (bGStat ? CGLO_GSTAT : 0) | CGLO_TEMPERATURE);
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW],
+ mdatoms, nrnb, &vcm, wcycle, enerd, force_vir, shake_vir, total_vir,
+ pres, constr, &nullSignaller, lastbox, nullptr, &bSumEkinhOld,
+ (bGStat ? CGLO_GSTAT : 0) | CGLO_TEMPERATURE);
wallcycle_start(wcycle, ewcUPDATE);
trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ4);
/* now we know the scaling, we can compute the positions again */
* to numerical errors, or are they important
* physically? I'm thinking they are just errors, but not completely sure.
* For now, will call without actually constraining, constr=NULL*/
- finish_update(ir, mdatoms, state, graph, nrnb, wcycle, &upd, nullptr);
+ finish_update(ir, mdatoms, state, wcycle, &upd, nullptr);
}
if (EI_VV(ir->eI))
{
/* this factor or 2 correction is necessary
because half of the constraint force is removed
in the vv step, so we have to double it. See
- the Redmine issue #1255. It is not yet clear
+ the Issue #1255. It is not yet clear
if the factor of 2 is exact, or just a very
good approximation, and this will be
investigated. The next step is to see if this
if (vsite != nullptr)
{
wallcycle_start(wcycle, ewcVSITECONSTR);
- if (graph != nullptr)
- {
- shift_self(graph, state->box, state->x.rvec_array());
- }
construct_vsites(vsite, state->x.rvec_array(), ir->delta_t, state->v.rvec_array(),
- top.idef.iparams, top.idef.il, fr->ePBC, fr->bMolPBC, cr, state->box);
-
- if (graph != nullptr)
- {
- unshift_self(graph, state->box, state->x.rvec_array());
- }
+ top.idef.iparams, top.idef.il, fr->pbcType, fr->bMolPBC, cr, state->box);
wallcycle_stop(wcycle, ewcVSITECONSTR);
}
SimulationSignaller signaller(&signals, cr, ms, doInterSimSignal, doIntraSimSignal);
compute_globals(
- gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, &vcm, wcycle, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &signaller, lastbox,
- &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, &vcm, wcycle, enerd, force_vir, shake_vir, total_vir, pres, constr,
+ &signaller, lastbox, &totalNumberOfBondedInteractions, &bSumEkinhOld,
(bGStat ? CGLO_GSTAT : 0) | (!EI_VV(ir->eI) && bCalcEner ? CGLO_ENERGY : 0)
| (!EI_VV(ir->eI) && bStopCM ? CGLO_STOPCM : 0)
| (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0)
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
: 0));
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions,
- top_global, &top, state->x.rvec_array(), state->box,
- &shouldCheckNumberOfBondedInteractions);
+ top_global, &top, makeConstArrayRef(state->x),
+ state->box, &shouldCheckNumberOfBondedInteractions);
if (!EI_VV(ir->eI) && bStopCM)
{
- process_and_stopcm_grp(fplog, &vcm, *mdatoms, state->x.rvec_array(),
- state->v.rvec_array());
+ process_and_stopcm_grp(fplog, &vcm, *mdatoms, makeArrayRef(state->x),
+ makeArrayRef(state->v));
inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
// TODO: The special case of removing CM motion should be dealt more gracefully
if (useGpuForUpdate && (doBerendsenPressureCoupling || doParrinelloRahman))
{
integrator->scaleCoordinates(pressureCouplingMu);
- t_pbc pbc;
- set_pbc(&pbc, epbcXYZ, state->box);
- integrator->setPbc(&pbc);
+ integrator->setPbc(PbcType::Xyz, state->box);
}
/* ################# END UPDATE STEP 2 ################# */
if (doSimulatedAnnealing)
{
- energyOutput.printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts));
+ gmx::EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups,
+ &(ir->opts));
}
if (do_log || do_ene || do_dr || do_or)
{
{
if (ir->nstcalcenergy > 0)
{
- energyOutput.printAnnealingTemperatures(fplog, groups, &(ir->opts));
+ gmx::EnergyOutput::printAnnealingTemperatures(fplog, groups, &(ir->opts));
energyOutput.printAverages(fplog, groups);
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
public:
Impl() :
- densityFitting_(DensityFittingModuleInfo::create(¬ifier_)),
+ densityFitting_(DensityFittingModuleInfo::create()),
field_(createElectricFieldModule()),
imd_(createInteractiveMolecularDynamicsModule()),
swapCoordinates_(createSwapCoordinatesModule())
return impl_->forceProviders_.get();
}
+void MDModules::subscribeToPreProcessingNotifications()
+{
+ impl_->densityFitting_->subscribeToPreProcessingNotifications(&impl_->notifier_);
+}
+
+void MDModules::subscribeToSimulationSetupNotifications()
+{
+ impl_->densityFitting_->subscribeToSimulationSetupNotifications(&impl_->notifier_);
+}
+
void MDModules::add(std::shared_ptr<gmx::IMDModule> module)
{
impl_->modules_.emplace_back(std::move(module));
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
ForceProviders* initForceProviders();
+ /*! \brief Subscribe MdModules to simulation setup notifications.
+ *
+ * Allows MdModules to subscribe to notifications that are called back
+ * during the set up of an MD simulation, after the options were
+ * assigned to the modules.
+ */
+ void subscribeToSimulationSetupNotifications();
+
+ /*! \brief Subscribe MdModules to notifications during pre-processing.
+ *
+ * Allows MdModules to subscribe to notifications that are called back
+ * during pre processing an MD simulation, after the options were
+ * assigned to the modules.
+ */
+ void subscribeToPreProcessingNotifications();
+
/*!
* \brief Add a module to the container.
*
#include "gromacs/domdec/mdsetup.h"
#include "gromacs/domdec/partition.h"
#include "gromacs/essentialdynamics/edsam.h"
-#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/fileio/trxio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/mimic/communicator.h"
#include "gromacs/mimic/utilities.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/timing/wallcycle.h"
unsigned int force_flags;
tensor force_vir, shake_vir, total_vir, pres;
rvec mu_tot;
- gmx_localtop_t top;
PaddedHostVector<gmx::RVec> f{};
gmx_global_stat_t gstat;
- t_graph* graph = nullptr;
gmx_shellfc_t* shellfc;
double cycles;
int nstglobalcomm = 1;
const bool bNS = true;
- // Communicator to interact with MiMiC
- MimicCommunicator mimicCommunicator{};
if (MASTER(cr))
{
- mimicCommunicator.init();
- mimicCommunicator.sendInitData(top_global, state_global->x);
- ir->nsteps = mimicCommunicator.getStepNumber();
+ MimicCommunicator::init();
+ auto nonConstGlobalTopology = const_cast<gmx_mtop_t*>(top_global);
+ MimicCommunicator::sendInitData(nonConstGlobalTopology, state_global->x);
+ ir->nsteps = MimicCommunicator::getStepNumber();
}
- ir->nstxout_compressed = 0;
- SimulationGroups* groups = &top_global->groups;
- top_global->intermolecularExclusionGroup = genQmmmIndices(*top_global);
+ ir->nstxout_compressed = 0;
+ const SimulationGroups* groups = &top_global->groups;
+ {
+ auto nonConstGlobalTopology = const_cast<gmx_mtop_t*>(top_global);
+ nonConstGlobalTopology->intermolecularExclusionGroup = genQmmmIndices(*top_global);
+ }
initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
std::unique_ptr<t_state> stateInstance;
t_state* state;
+ gmx_localtop_t top(top_global->ffparams);
+
if (DOMAINDECOMP(cr))
{
- dd_init_local_top(*top_global, &top);
-
stateInstance = std::make_unique<t_state>();
state = stateInstance.get();
dd_init_local_state(cr->dd, state_global, state);
imdSession, pull_work, state, &f, mdAtoms, &top, fr, vsite, constr,
nrnb, nullptr, FALSE);
shouldCheckNumberOfBondedInteractions = true;
- gmx_bcast(sizeof(ir->nsteps), &ir->nsteps, cr);
+ gmx_bcast(sizeof(ir->nsteps), &ir->nsteps, cr->mpi_comm_mygroup);
}
else
{
state_change_natoms(state_global, state_global->natoms);
- /* We need to allocate one element extra, since we might use
- * (unaligned) 4-wide SIMD loads to access rvec entries.
- */
- f.resizeWithPadding(state_global->natoms);
/* Copy the pointer to the global state */
state = state_global;
- mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &graph, mdAtoms, constr, vsite, shellfc);
+ mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &f, mdAtoms, constr, vsite, shellfc);
}
auto mdatoms = mdAtoms->mdatoms();
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0));
bool bSumEkinhOld = false;
t_vcm* vcm = nullptr;
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, vcm, nullptr, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms, nrnb,
+ vcm, nullptr, enerd, force_vir, shake_vir, total_vir, pres, constr, &nullSignaller,
state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld, cglo_flags);
}
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global, &top,
- state->x.rvec_array(), state->box,
+ makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
if (MASTER(cr))
if (MASTER(cr))
{
- mimicCommunicator.getCoords(&state_global->x, state_global->natoms);
+ MimicCommunicator::getCoords(&state_global->x, state_global->natoms);
}
if (ir->efep != efepNO)
if (MASTER(cr))
{
- energyOutput.printHeader(fplog, step, t); /* can we improve the information printed here? */
+ EnergyOutput::printHeader(fplog, step, t); /* can we improve the information printed here? */
}
if (ir->efep != efepNO)
imdSession, pull_work, bNS, force_flags, &top, constr, enerd, fcd,
state->natoms, state->x.arrayRefWithPadding(),
state->v.arrayRefWithPadding(), state->box, state->lambda, &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, graph,
- shellfc, fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
+ f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, shellfc,
+ fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
}
else
{
gmx_edsam* ed = nullptr;
do_force(fplog, cr, ms, ir, awh, enforcedRotation, imdSession, pull_work, step, nrnb,
wcycle, &top, state->box, state->x.arrayRefWithPadding(), &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, graph,
- fr, runScheduleWork, vsite, mu_tot, t, ed, GMX_FORCE_NS | force_flags,
+ f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, fr,
+ runScheduleWork, vsite, mu_tot, t, ed, GMX_FORCE_NS | force_flags,
ddBalanceRegionHandler);
}
stopHandler->setSignal();
- if (graph)
- {
- /* Need to unshift here */
- unshift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
-
if (vsite != nullptr)
{
wallcycle_start(wcycle, ewcVSITECONSTR);
- if (graph != nullptr)
- {
- shift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
construct_vsites(vsite, as_rvec_array(state->x.data()), ir->delta_t,
as_rvec_array(state->v.data()), top.idef.iparams, top.idef.il,
- fr->ePBC, fr->bMolPBC, cr, state->box);
-
- if (graph != nullptr)
- {
- unshift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
+ fr->pbcType, fr->bMolPBC, cr, state->box);
wallcycle_stop(wcycle, ewcVSITECONSTR);
}
t_vcm* vcm = nullptr;
SimulationSignaller signaller(&signals, cr, ms, doInterSimSignal, doIntraSimSignal);
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, vcm, wcycle, enerd,
- nullptr, nullptr, nullptr, nullptr, mu_tot, constr, &signaller,
- state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, vcm, wcycle, enerd, nullptr, nullptr, nullptr, nullptr, constr,
+ &signaller, state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
CGLO_GSTAT | CGLO_ENERGY
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
: 0));
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global,
- &top, state->x.rvec_array(), state->box,
+ &top, makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
}
if (MASTER(cr))
{
- mimicCommunicator.sendEnergies(enerd->term[F_EPOT]);
- mimicCommunicator.sendForces(ftemp, state_global->natoms);
+ MimicCommunicator::sendEnergies(enerd->term[F_EPOT]);
+ MimicCommunicator::sendForces(ftemp, state_global->natoms);
}
}
const bool do_dr = ir->nstdisreout != 0;
const bool do_or = ir->nstorireout != 0;
- energyOutput.printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts));
+ EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts));
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or,
do_log ? fplog : nullptr, step, t, fcd, awh);
if (MASTER(cr))
{
- mimicCommunicator.finalize();
+ MimicCommunicator::finalize();
}
if (!thisRankHasDuty(cr, DUTY_PME))
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/domdec/mdsetup.h"
#include "gromacs/domdec/partition.h"
-#include "gromacs/ewald/pme.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/fileio/confio.h"
#include "gromacs/fileio/mtxio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/mdlib/enerdata_utils.h"
#include "gromacs/mdlib/energyoutput.h"
#include "gromacs/mdlib/force.h"
+#include "gromacs/mdlib/force_flags.h"
#include "gromacs/mdlib/forcerec.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/md_support.h"
#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/state.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/timing/walltime_accounting.h"
#include "legacysimulator.h"
#include "shellfc.h"
+using gmx::ArrayRef;
using gmx::MdrunScheduleWorkload;
+using gmx::RVec;
//! Utility structure for manipulating states during EM
typedef struct
gmx::ImdSession* imdSession,
pull_t* pull_work,
t_state* state_global,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
em_state_t* ems,
gmx_localtop_t* top,
t_nrnb* nrnb,
t_forcerec* fr,
- t_graph** graph,
gmx::MDAtoms* mdAtoms,
gmx_global_stat_t* gstat,
gmx_vsite_t* vsite,
auto mdatoms = mdAtoms->mdatoms();
if (DOMAINDECOMP(cr))
{
- top->useInDomainDecomp_ = true;
- dd_init_local_top(*top_global, top);
-
dd_init_local_state(cr->dd, state_global, &ems->s);
/* Distribute the charge groups over the nodes from the master node */
imdSession, pull_work, &ems->s, &ems->f, mdAtoms, top, fr, vsite,
constr, nrnb, nullptr, FALSE);
dd_store_state(cr->dd, &ems->s);
-
- *graph = nullptr;
}
else
{
/* Just copy the state */
ems->s = *state_global;
state_change_natoms(&ems->s, ems->s.natoms);
- ems->f.resizeWithPadding(ems->s.natoms);
- mdAlgorithmsSetupAtomData(cr, ir, *top_global, top, fr, graph, mdAtoms, constr, vsite,
+ mdAlgorithmsSetupAtomData(cr, ir, *top_global, top, fr, &ems->f, mdAtoms, constr, vsite,
shellfc ? *shellfc : nullptr);
if (vsite)
{
/* Constrain the starting coordinates */
dvdl_constr = 0;
- constr->apply(TRUE, TRUE, -1, 0, 1.0, ems->s.x.rvec_array(), ems->s.x.rvec_array(),
- nullptr, ems->s.box, ems->s.lambda[efptFEP], &dvdl_constr, nullptr,
+ constr->apply(TRUE, TRUE, -1, 0, 1.0, ems->s.x.arrayRefWithPadding(),
+ ems->s.x.arrayRefWithPadding(), ArrayRef<RVec>(), ems->s.box,
+ ems->s.lambda[efptFEP], &dvdl_constr, gmx::ArrayRefWithPadding<RVec>(),
nullptr, gmx::ConstraintVariable::Positions);
}
}
gmx_bool bX,
gmx_bool bF,
const char* confout,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
t_inputrec* ir,
int64_t step,
em_state_t* state,
if (MASTER(cr))
{
- if (ir->ePBC != epbcNONE && !ir->bPeriodicMols && DOMAINDECOMP(cr))
+ if (ir->pbcType != PbcType::No && !ir->bPeriodicMols && DOMAINDECOMP(cr))
{
/* Make molecules whole only for confout writing */
- do_pbc_mtop(ir->ePBC, state->s.box, top_global, state_global->x.rvec_array());
+ do_pbc_mtop(ir->pbcType, state->s.box, top_global, state_global->x.rvec_array());
}
write_sto_conf_mtop(confout, *top_global->name, top_global,
- state_global->x.rvec_array(), nullptr, ir->ePBC, state->s.box);
+ state_global->x.rvec_array(), nullptr, ir->pbcType, state->s.box);
}
}
}
if (constr)
{
dvdl_constr = 0;
- validStep = constr->apply(TRUE, TRUE, count, 0, 1.0, s1->x.rvec_array(), s2->x.rvec_array(),
- nullptr, s2->box, s2->lambda[efptBONDED], &dvdl_constr, nullptr,
- nullptr, gmx::ConstraintVariable::Positions);
+ validStep = constr->apply(
+ TRUE, TRUE, count, 0, 1.0, s1->x.arrayRefWithPadding(), s2->x.arrayRefWithPadding(),
+ ArrayRef<RVec>(), s2->box, s2->lambda[efptBONDED], &dvdl_constr,
+ gmx::ArrayRefWithPadding<RVec>(), nullptr, gmx::ConstraintVariable::Positions);
if (cr->nnodes > 1)
{
const gmx::MDLogger& mdlog,
int step,
const t_commrec* cr,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
t_inputrec* ir,
gmx::ImdSession* imdSession,
pull_t* pull_work,
//! Coordinates multi-simulations.
const gmx_multisim_t* ms;
//! Holds the simulation topology.
- gmx_mtop_t* top_global;
+ const gmx_mtop_t* top_global;
//! Holds the domain topology.
gmx_localtop_t* top;
//! User input options.
gmx::Constraints* constr;
//! Handles strange things.
t_fcdata* fcd;
- //! Molecular graph for SHAKE.
- t_graph* graph;
//! Per-atom data for this domain.
gmx::MDAtoms* mdAtoms;
//! Handles how to calculate the forces.
if (vsite)
{
construct_vsites(vsite, ems->s.x.rvec_array(), 1, nullptr, top->idef.iparams, top->idef.il,
- fr->ePBC, fr->bMolPBC, cr, ems->s.box);
+ fr->pbcType, fr->bMolPBC, cr, ems->s.box);
}
if (DOMAINDECOMP(cr) && bNS)
do_force(fplog, cr, ms, inputrec, nullptr, nullptr, imdSession, pull_work, count, nrnb, wcycle,
top, ems->s.box, ems->s.x.arrayRefWithPadding(), &ems->s.hist,
ems->f.arrayRefWithPadding(), force_vir, mdAtoms->mdatoms(), enerd, fcd, ems->s.lambda,
- graph, fr, runScheduleWork, vsite, mu_tot, t, nullptr,
+ fr, runScheduleWork, vsite, mu_tot, t, nullptr,
GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES | GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY
| (bNS ? GMX_FORCE_NS : 0),
DDBalanceRegionHandler(cr));
{
wallcycle_start(wcycle, ewcMoveE);
- global_stat(gstat, cr, enerd, force_vir, shake_vir, mu_tot, inputrec, nullptr, nullptr, nullptr,
- 1, &terminate, nullptr, FALSE, CGLO_ENERGY | CGLO_PRESSURE | CGLO_CONSTRAINT);
+ global_stat(gstat, cr, enerd, force_vir, shake_vir, inputrec, nullptr, nullptr, nullptr, 1,
+ &terminate, nullptr, FALSE, CGLO_ENERGY | CGLO_PRESSURE | CGLO_CONSTRAINT);
wallcycle_stop(wcycle, ewcMoveE);
}
if (constr)
{
/* Project out the constraint components of the force */
- dvdl_constr = 0;
- rvec* f_rvec = ems->f.rvec_array();
- constr->apply(FALSE, FALSE, count, 0, 1.0, ems->s.x.rvec_array(), f_rvec, f_rvec,
- ems->s.box, ems->s.lambda[efptBONDED], &dvdl_constr, nullptr, &shake_vir,
- gmx::ConstraintVariable::ForceDispl);
+ dvdl_constr = 0;
+ auto f = ems->f.arrayRefWithPadding();
+ constr->apply(FALSE, FALSE, count, 0, 1.0, ems->s.x.arrayRefWithPadding(), f,
+ f.unpaddedArrayRef(), ems->s.box, ems->s.lambda[efptBONDED], &dvdl_constr,
+ gmx::ArrayRefWithPadding<RVec>(), &shake_vir, gmx::ConstraintVariable::ForceDispl);
enerd->term[F_DVDL_CONSTR] += dvdl_constr;
m_add(force_vir, shake_vir, vir);
}
}
clear_mat(ekin);
- enerd->term[F_PRES] = calc_pres(fr->ePBC, inputrec->nwall, ems->s.box, ekin, vir, pres);
+ enerd->term[F_PRES] = calc_pres(fr->pbcType, inputrec->nwall, ems->s.box, ekin, vir, pres);
sum_dhdl(enerd, ems->s.lambda, *inputrec->fepvals);
} // namespace
//! Parallel utility summing energies and forces
-static double reorder_partsum(const t_commrec* cr,
- t_grpopts* opts,
- gmx_mtop_t* top_global,
- em_state_t* s_min,
- em_state_t* s_b)
+static double reorder_partsum(const t_commrec* cr,
+ t_grpopts* opts,
+ const gmx_mtop_t* top_global,
+ em_state_t* s_min,
+ em_state_t* s_b)
{
if (debug)
{
/* Now we will determine the part of the sum for the cgs in state s_b */
gmx::ArrayRef<const int> indicesB = s_b->s.cg_gl;
- double partsum = 0;
- i = 0;
- int gf = 0;
- gmx::ArrayRef<unsigned char> grpnrFREEZE =
+ double partsum = 0;
+ i = 0;
+ int gf = 0;
+ gmx::ArrayRef<const unsigned char> grpnrFREEZE =
top_global->groups.groupNumbers[SimulationAtomGroupType::Freeze];
for (int a : indicesB)
{
}
//! Print some stuff, like beta, whatever that means.
-static real pr_beta(const t_commrec* cr,
- t_grpopts* opts,
- t_mdatoms* mdatoms,
- gmx_mtop_t* top_global,
- em_state_t* s_min,
- em_state_t* s_b)
+static real pr_beta(const t_commrec* cr,
+ t_grpopts* opts,
+ t_mdatoms* mdatoms,
+ const gmx_mtop_t* top_global,
+ em_state_t* s_min,
+ em_state_t* s_b)
{
double sum;
{
const char* CG = "Polak-Ribiere Conjugate Gradients";
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
gmx_global_stat_t gstat;
- t_graph* graph;
double tmp, minstep;
real stepsize;
real a, b, c, beta = 0.0;
/* Init em and store the local state in s_min */
init_em(fplog, mdlog, CG, cr, inputrec, imdSession, pull_work, state_global, top_global, s_min,
- &top, nrnb, fr, &graph, mdAtoms, &gstat, vsite, constr, nullptr);
+ &top, nrnb, fr, mdAtoms, &gstat, vsite, constr, nullptr);
const bool simulationsShareState = false;
gmx_mdoutf* outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider,
mdModulesNotifier, inputrec, top_global, nullptr, wcycle,
}
EnergyEvaluator energyEvaluator{
- fplog, mdlog, cr, ms, top_global, &top, inputrec,
- imdSession, pull_work, nrnb, wcycle, gstat, vsite, constr,
- fcd, graph, mdAtoms, fr, runScheduleWork, enerd
+ fplog, mdlog, cr, ms, top_global, &top, inputrec, imdSession, pull_work,
+ nrnb, wcycle, gstat, vsite, constr, fcd, mdAtoms, fr, runScheduleWork,
+ enerd
};
/* Call the force routine and some auxiliary (neighboursearching etc.) */
/* do_force always puts the charge groups in the box and shifts again
enerd, nullptr, nullptr, nullptr, nullBox, nullptr,
nullptr, vir, pres, nullptr, mu_tot, constr);
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, FALSE, FALSE, fplog, step,
step, fcd, nullptr);
}
if (do_log)
{
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
}
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, FALSE, FALSE,
do_log ? fplog : nullptr, step, step, fcd, nullptr);
if (!do_log)
{
/* Write final value to log since we didn't do anything the last step */
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
}
if (!do_ene || !do_log)
{
{
static const char* LBFGS = "Low-Memory BFGS Minimizer";
em_state_t ems;
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
gmx_global_stat_t gstat;
- t_graph* graph;
int ncorr, nmaxcorr, point, cp, neval, nminstep;
double stepsize, step_taken, gpa, gpb, gpc, tmp, minstep;
real * rho, *alpha, *p, *s, **dx, **dg;
/* Init em */
init_em(fplog, mdlog, LBFGS, cr, inputrec, imdSession, pull_work, state_global, top_global,
- &ems, &top, nrnb, fr, &graph, mdAtoms, &gstat, vsite, constr, nullptr);
+ &ems, &top, nrnb, fr, mdAtoms, &gstat, vsite, constr, nullptr);
const bool simulationsShareState = false;
gmx_mdoutf* outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider,
mdModulesNotifier, inputrec, top_global, nullptr, wcycle,
if (vsite)
{
construct_vsites(vsite, state_global->x.rvec_array(), 1, nullptr, top.idef.iparams,
- top.idef.il, fr->ePBC, fr->bMolPBC, cr, state_global->box);
+ top.idef.il, fr->pbcType, fr->bMolPBC, cr, state_global->box);
}
/* Call the force routine and some auxiliary (neighboursearching etc.) */
*/
neval++;
EnergyEvaluator energyEvaluator{
- fplog, mdlog, cr, ms, top_global, &top, inputrec,
- imdSession, pull_work, nrnb, wcycle, gstat, vsite, constr,
- fcd, graph, mdAtoms, fr, runScheduleWork, enerd
+ fplog, mdlog, cr, ms, top_global, &top, inputrec, imdSession, pull_work,
+ nrnb, wcycle, gstat, vsite, constr, fcd, mdAtoms, fr, runScheduleWork,
+ enerd
};
energyEvaluator.run(&ems, mu_tot, vir, pres, -1, TRUE);
enerd, nullptr, nullptr, nullptr, nullBox, nullptr,
nullptr, vir, pres, nullptr, mu_tot, constr);
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), TRUE, FALSE, FALSE, fplog, step,
step, fcd, nullptr);
}
if (do_log)
{
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
}
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, FALSE, FALSE,
do_log ? fplog : nullptr, step, step, fcd, nullptr);
*/
if (!do_log) /* Write final value to log since we didn't do anythin last step */
{
- energyOutput.printHeader(fplog, step, step);
+ EnergyOutput::printHeader(fplog, step, step);
}
if (!do_ene || !do_log) /* Write final energy file entries */
{
void LegacySimulator::do_steep()
{
const char* SD = "Steepest Descents";
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
gmx_global_stat_t gstat;
- t_graph* graph;
real stepsize;
real ustep;
gmx_bool bDone, bAbort, do_x, do_f;
/* Init em and store the local state in s_try */
init_em(fplog, mdlog, SD, cr, inputrec, imdSession, pull_work, state_global, top_global, s_try,
- &top, nrnb, fr, &graph, mdAtoms, &gstat, vsite, constr, nullptr);
+ &top, nrnb, fr, mdAtoms, &gstat, vsite, constr, nullptr);
const bool simulationsShareState = false;
gmx_mdoutf* outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider,
mdModulesNotifier, inputrec, top_global, nullptr, wcycle,
sp_header(fplog, SD, inputrec->em_tol, nsteps);
}
EnergyEvaluator energyEvaluator{
- fplog, mdlog, cr, ms, top_global, &top, inputrec,
- imdSession, pull_work, nrnb, wcycle, gstat, vsite, constr,
- fcd, graph, mdAtoms, fr, runScheduleWork, enerd
+ fplog, mdlog, cr, ms, top_global, &top, inputrec, imdSession, pull_work,
+ nrnb, wcycle, gstat, vsite, constr, fcd, mdAtoms, fr, runScheduleWork,
+ enerd
};
/**** HERE STARTS THE LOOP ****
if (MASTER(cr))
{
- energyOutput.printHeader(fplog, count, count);
+ EnergyOutput::printHeader(fplog, count, count);
}
if (count == 0)
{
const char* NM = "Normal Mode Analysis";
int nnodes;
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
gmx_global_stat_t gstat;
- t_graph* graph;
tensor vir, pres;
rvec mu_tot = { 0 };
rvec* dfdx;
/* Init em and store the local state in state_minimum */
init_em(fplog, mdlog, NM, cr, inputrec, imdSession, pull_work, state_global, top_global,
- &state_work, &top, nrnb, fr, &graph, mdAtoms, &gstat, vsite, constr, &shellfc);
+ &state_work, &top, nrnb, fr, mdAtoms, &gstat, vsite, constr, &shellfc);
const bool simulationsShareState = false;
gmx_mdoutf* outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider,
mdModulesNotifier, inputrec, top_global, nullptr, wcycle,
/* Make evaluate_energy do a single node force calculation */
cr->nnodes = 1;
EnergyEvaluator energyEvaluator{
- fplog, mdlog, cr, ms, top_global, &top, inputrec,
- imdSession, pull_work, nrnb, wcycle, gstat, vsite, constr,
- fcd, graph, mdAtoms, fr, runScheduleWork, enerd
+ fplog, mdlog, cr, ms, top_global, &top, inputrec, imdSession, pull_work,
+ nrnb, wcycle, gstat, vsite, constr, fcd, mdAtoms, fr, runScheduleWork,
+ enerd
};
energyEvaluator.run(&state_work, mu_tot, vir, pres, -1, TRUE);
cr->nnodes = nnodes;
if (shellfc)
{
/* Now is the time to relax the shells */
- relax_shell_flexcon(fplog, cr, ms, mdrunOptions.verbose, nullptr, step, inputrec,
- imdSession, pull_work, bNS, force_flags, &top, constr, enerd,
- fcd, state_work.s.natoms, state_work.s.x.arrayRefWithPadding(),
- state_work.s.v.arrayRefWithPadding(), state_work.s.box,
- state_work.s.lambda, &state_work.s.hist,
- state_work.f.arrayRefWithPadding(), vir, mdatoms, nrnb,
- wcycle, graph, shellfc, fr, runScheduleWork, t, mu_tot,
- vsite, DDBalanceRegionHandler(nullptr));
+ relax_shell_flexcon(
+ fplog, cr, ms, mdrunOptions.verbose, nullptr, step, inputrec, imdSession,
+ pull_work, bNS, force_flags, &top, constr, enerd, fcd, state_work.s.natoms,
+ state_work.s.x.arrayRefWithPadding(), state_work.s.v.arrayRefWithPadding(),
+ state_work.s.box, state_work.s.lambda, &state_work.s.hist,
+ state_work.f.arrayRefWithPadding(), vir, mdatoms, nrnb, wcycle, shellfc,
+ fr, runScheduleWork, t, mu_tot, vsite, DDBalanceRegionHandler(nullptr));
bNS = false;
step++;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/mdsetup.h"
#include "gromacs/domdec/partition.h"
#include "gromacs/essentialdynamics/edsam.h"
-#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/fileio/trxio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/mimic/utilities.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pulling/pull.h"
#include "gromacs/swap/swapcoords.h"
* \param[in] idef Topology parameters, used for constructing vsites
* \param[in] timeStep Time step, used for constructing vsites
* \param[in] forceRec Force record, used for constructing vsites
- * \param[in,out] graph The molecular graph, used for constructing vsites when != nullptr
*/
-static void prepareRerunState(const t_trxframe& rerunFrame,
- t_state* globalState,
- bool constructVsites,
- const gmx_vsite_t* vsite,
- const t_idef& idef,
- double timeStep,
- const t_forcerec& forceRec,
- t_graph* graph)
+static void prepareRerunState(const t_trxframe& rerunFrame,
+ t_state* globalState,
+ bool constructVsites,
+ const gmx_vsite_t* vsite,
+ const InteractionDefinitions& idef,
+ double timeStep,
+ const t_forcerec& forceRec)
{
auto x = makeArrayRef(globalState->x);
auto rerunX = arrayRefFromArray(reinterpret_cast<gmx::RVec*>(rerunFrame.x), globalState->natoms);
{
GMX_ASSERT(vsite, "Need valid vsite for constructing vsites");
- if (graph)
- {
- /* Following is necessary because the graph may get out of sync
- * with the coordinates if we only have every N'th coordinate set
- */
- mk_mshift(nullptr, graph, forceRec.ePBC, globalState->box, globalState->x.rvec_array());
- shift_self(graph, globalState->box, as_rvec_array(globalState->x.data()));
- }
construct_vsites(vsite, globalState->x.rvec_array(), timeStep, globalState->v.rvec_array(),
- idef.iparams, idef.il, forceRec.ePBC, forceRec.bMolPBC, nullptr,
+ idef.iparams, idef.il, forceRec.pbcType, forceRec.bMolPBC, nullptr,
globalState->box);
- if (graph)
- {
- unshift_self(graph, globalState->box, globalState->x.rvec_array());
- }
}
}
t_trxstatus* status = nullptr;
rvec mu_tot;
t_trxframe rerun_fr;
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
PaddedHostVector<gmx::RVec> f{};
gmx_global_stat_t gstat;
- t_graph* graph = nullptr;
gmx_shellfc_t* shellfc;
double cycles;
int nstglobalcomm = 1;
const bool bNS = true;
- ir->nstxout_compressed = 0;
- SimulationGroups* groups = &top_global->groups;
+ ir->nstxout_compressed = 0;
+ const SimulationGroups* groups = &top_global->groups;
if (ir->eI == eiMimic)
{
- top_global->intermolecularExclusionGroup = genQmmmIndices(*top_global);
+ auto nonConstGlobalTopology = const_cast<gmx_mtop_t*>(top_global);
+ nonConstGlobalTopology->intermolecularExclusionGroup = genQmmmIndices(*top_global);
}
initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
if (DOMAINDECOMP(cr))
{
- dd_init_local_top(*top_global, &top);
-
stateInstance = std::make_unique<t_state>();
state = stateInstance.get();
dd_init_local_state(cr->dd, state_global, state);
else
{
state_change_natoms(state_global, state_global->natoms);
- /* We need to allocate one element extra, since we might use
- * (unaligned) 4-wide SIMD loads to access rvec entries.
- */
- f.resizeWithPadding(state_global->natoms);
/* Copy the pointer to the global state */
state = state_global;
- mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &graph, mdAtoms, constr, vsite, shellfc);
+ mdAlgorithmsSetupAtomData(cr, ir, *top_global, &top, fr, &f, mdAtoms, constr, vsite, shellfc);
}
auto mdatoms = mdAtoms->mdatoms();
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0));
bool bSumEkinhOld = false;
t_vcm* vcm = nullptr;
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, vcm, nullptr, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &nullSignaller,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms, nrnb,
+ vcm, nullptr, enerd, force_vir, shake_vir, total_vir, pres, constr, &nullSignaller,
state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld, cglo_flags);
}
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global, &top,
- state->x.rvec_array(), state->box,
+ makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
if (MASTER(cr))
rerun_fr.natoms, top_global->natoms);
}
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
if (!rerun_fr.bBox)
{
"does not contain a box, while pbc is used",
rerun_fr.step, rerun_fr.time);
}
- if (max_cutoff2(ir->ePBC, rerun_fr.box) < gmx::square(fr->rlist))
+ if (max_cutoff2(ir->pbcType, rerun_fr.box) < gmx::square(fr->rlist))
{
gmx_fatal(FARGS,
"Rerun trajectory frame step %" PRId64
rerun_parallel_comm(cr, &rerun_fr, &isLastStep);
}
- if (ir->ePBC != epbcNONE)
+ if (ir->pbcType != PbcType::No)
{
/* Set the shift vectors.
* Necessary here when have a static box different from the tpr box.
"decomposition, "
"use a single rank");
}
- prepareRerunState(rerun_fr, state_global, constructVsites, vsite, top.idef, ir->delta_t,
- *fr, graph);
+ prepareRerunState(rerun_fr, state_global, constructVsites, vsite, top.idef, ir->delta_t, *fr);
}
isLastStep = isLastStep || stopHandler->stoppingAfterCurrentStep(bNS);
if (MASTER(cr))
{
- energyOutput.printHeader(fplog, step, t); /* can we improve the information printed here? */
+ EnergyOutput::printHeader(fplog, step, t); /* can we improve the information printed here? */
}
if (ir->efep != efepNO)
imdSession, pull_work, bNS, force_flags, &top, constr, enerd, fcd,
state->natoms, state->x.arrayRefWithPadding(),
state->v.arrayRefWithPadding(), state->box, state->lambda, &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, graph,
- shellfc, fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
+ f.arrayRefWithPadding(), force_vir, mdatoms, nrnb, wcycle, shellfc,
+ fr, runScheduleWork, t, mu_tot, vsite, ddBalanceRegionHandler);
}
else
{
gmx_edsam* ed = nullptr;
do_force(fplog, cr, ms, ir, awh, enforcedRotation, imdSession, pull_work, step, nrnb,
wcycle, &top, state->box, state->x.arrayRefWithPadding(), &state->hist,
- f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, graph,
- fr, runScheduleWork, vsite, mu_tot, t, ed, GMX_FORCE_NS | force_flags,
+ f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd, state->lambda, fr,
+ runScheduleWork, vsite, mu_tot, t, ed, GMX_FORCE_NS | force_flags,
ddBalanceRegionHandler);
}
stopHandler->setSignal();
- if (graph)
- {
- /* Need to unshift here */
- unshift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
-
if (vsite != nullptr)
{
wallcycle_start(wcycle, ewcVSITECONSTR);
- if (graph != nullptr)
- {
- shift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
construct_vsites(vsite, as_rvec_array(state->x.data()), ir->delta_t,
as_rvec_array(state->v.data()), top.idef.iparams, top.idef.il,
- fr->ePBC, fr->bMolPBC, cr, state->box);
-
- if (graph != nullptr)
- {
- unshift_self(graph, state->box, as_rvec_array(state->x.data()));
- }
+ fr->pbcType, fr->bMolPBC, cr, state->box);
wallcycle_stop(wcycle, ewcVSITECONSTR);
}
t_vcm* vcm = nullptr;
SimulationSignaller signaller(&signals, cr, ms, doInterSimSignal, doIntraSimSignal);
- compute_globals(gstat, cr, ir, fr, ekind, state->x.rvec_array(), state->v.rvec_array(),
- state->box, state->lambda[efptVDW], mdatoms, nrnb, vcm, wcycle, enerd,
- force_vir, shake_vir, total_vir, pres, mu_tot, constr, &signaller,
- state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
+ compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
+ makeConstArrayRef(state->v), state->box, state->lambda[efptVDW], mdatoms,
+ nrnb, vcm, wcycle, enerd, force_vir, shake_vir, total_vir, pres, constr,
+ &signaller, state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
CGLO_GSTAT | CGLO_ENERGY
| (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
: 0));
checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions, top_global,
- &top, state->x.rvec_array(), state->box,
+ &top, makeConstArrayRef(state->x), state->box,
&shouldCheckNumberOfBondedInteractions);
}
const bool do_dr = ir->nstdisreout != 0;
const bool do_or = ir->nstorireout != 0;
- energyOutput.printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts));
+ EnergyOutput::printAnnealingTemperatures(do_log ? fplog : nullptr, groups, &(ir->opts));
energyOutput.printStepToEnergyFile(mdoutf_get_fp_ene(outf), do_ene, do_dr, do_or,
do_log ? fplog : nullptr, step, t, fcd, awh);
#include "gromacs/domdec/localatomsetmanager.h"
#include "gromacs/domdec/partition.h"
#include "gromacs/ewald/ewald_utils.h"
-#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_gpu_program.h"
+#include "gromacs/ewald/pme_only.h"
#include "gromacs/ewald/pme_pp_comm_gpu.h"
#include "gromacs/fileio/checkpoint.h"
#include "gromacs/fileio/gmxfio.h"
#include "gromacs/fileio/tpxio.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
+#include "gromacs/gpu_utils/device_context.h"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/hardware/detecthardware.h"
#include "gromacs/mdlib/md_support.h"
#include "gromacs/mdlib/mdatoms.h"
#include "gromacs/mdlib/membed.h"
-#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdlib/sighandler.h"
#include "gromacs/mdlib/stophandler.h"
+#include "gromacs/mdlib/tgroup.h"
#include "gromacs/mdlib/updategroups.h"
+#include "gromacs/mdlib/vsite.h"
#include "gromacs/mdrun/mdmodules.h"
#include "gromacs/mdrun/simulationcontext.h"
#include "gromacs/mdrunutility/handlerestart.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/fcdata.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/simulation_workload.h"
GMX_LOG(mdlog.warning)
.asParagraph()
.appendTextFormatted(
- "This run uses the 'GPU halo exchange' feature, enabled by the "
+ "This run has requested the 'GPU halo exchange' feature, enabled by "
+ "the "
"GMX_GPU_DD_COMMS environment variable.");
}
else
// Copy members of master runner.
// \todo Replace with builder when Simulation context and/or runner phases are better defined.
- // Ref https://redmine.gromacs.org/issues/2587 and https://redmine.gromacs.org/issues/2375
+ // Ref https://gitlab.com/gromacs/gromacs/-/issues/2587 and https://gitlab.com/gromacs/gromacs/-/issues/2375
newRunner.hw_opt = hw_opt;
newRunner.filenames = filenames;
bool makeGpuPairList,
const gmx::CpuInfo& cpuinfo)
{
+ // We checked the cut-offs in grompp, but double-check here.
+ // We have PME+LJcutoff kernels for rcoulomb>rvdw.
+ if (EEL_PME_EWALD(ir->coulombtype) && ir->vdwtype == eelCUT)
+ {
+ GMX_RELEASE_ASSERT(ir->rcoulomb >= ir->rvdw,
+ "With Verlet lists and PME we should have rcoulomb>=rvdw");
+ }
+ else
+ {
+ GMX_RELEASE_ASSERT(ir->rcoulomb == ir->rvdw,
+ "With Verlet lists and no PME rcoulomb and rvdw should be identical");
+ }
/* For NVE simulations, we will retain the initial list buffer */
if (EI_DYNAMICS(ir->eI) && ir->verletbuf_tol > 0 && !(EI_MD(ir->eI) && ir->etc == etcNO))
{
{
inputrec = &inputrecInstance;
}
- init_parallel(cr, inputrec, &mtop, partialDeserializedTpr.get());
+ init_parallel(cr->mpi_comm_mygroup, MASTER(cr), inputrec, &mtop, partialDeserializedTpr.get());
}
GMX_RELEASE_ASSERT(inputrec != nullptr, "All ranks should have a valid inputrec now");
partialDeserializedTpr.reset(nullptr);
// the inputrec read by the master rank. The ranks can now all run
// the task-deciding functions and will agree on the result
// without needing to communicate.
- //
- // TODO Should we do the communication in debug mode to support
- // having an assertion?
const bool useDomainDecomposition = (PAR(cr) && !(EI_TPI(inputrec->eI) || inputrec->eI == eiNM));
// Note that these variables describe only their own node.
const DevelopmentFeatureFlags devFlags =
manageDevelopmentFeatures(mdlog, useGpuForNonbonded, pmeRunMode);
- const bool inputIsCompatibleWithModularSimulator = ModularSimulator::isInputCompatible(
+ const bool useModularSimulator = checkUseModularSimulator(
false, inputrec, doRerun, mtop, ms, replExParams, nullptr, doEssentialDynamics, doMembed);
- const bool useModularSimulator = inputIsCompatibleWithModularSimulator
- && !(getenv("GMX_DISABLE_MODULAR_SIMULATOR") != nullptr);
// Build restraints.
// TODO: hide restraint implementation details from Mdrunner.
// TODO: Error handling
mdModules_->assignOptionsToModules(*inputrec->params, nullptr);
- const auto& mdModulesNotifier = mdModules_->notifier().notifier_;
+ // now that the MdModules know their options, they know which callbacks to sign up to
+ mdModules_->subscribeToSimulationSetupNotifications();
+ const auto& mdModulesNotifier = mdModules_->notifier().simulationSetupNotifications_;
if (inputrec->internalParameters != nullptr)
{
{
globalState = std::make_unique<t_state>();
}
- broadcastStateWithoutDynamics(cr, globalState.get());
+ broadcastStateWithoutDynamics(cr->mpi_comm_mygroup, DOMAINDECOMP(cr), PAR(cr), globalState.get());
}
/* A parallel command line option consistency check that we can
snew(fcd, 1);
/* This needs to be called before read_checkpoint to extend the state */
- init_disres(fplog, &mtop, inputrec, cr, ms, fcd, globalState.get(), replExParams.exchangeInterval > 0);
+ init_disres(fplog, &mtop, inputrec, DisResRunMode::MDRun, MASTER(cr) ? DDRole::Master : DDRole::Agent,
+ PAR(cr) ? NumRanks::Multiple : NumRanks::Single, cr->mpi_comm_mysim, ms, fcd,
+ globalState.get(), replExParams.exchangeInterval > 0);
init_orires(fplog, &mtop, inputrec, cr, ms, globalState.get(), &(fcd->orires));
- auto deform = prepareBoxDeformation(globalState->box, cr, *inputrec);
+ auto deform = prepareBoxDeformation(globalState->box, MASTER(cr) ? DDRole::Master : DDRole::Agent,
+ PAR(cr) ? NumRanks::Multiple : NumRanks::Single,
+ cr->mpi_comm_mygroup, *inputrec);
ObservablesHistory observablesHistory = {};
if (PAR(cr))
{
- gmx_bcast(sizeof(box), box, cr);
+ gmx_bcast(sizeof(box), box, cr->mpi_comm_mygroup);
}
if (inputrec->cutoff_scheme != ecutsVERLET)
cr->npmenodes = 0;
cr->duty = (DUTY_PP | DUTY_PME);
- if (inputrec->ePBC == epbcSCREW)
+ if (inputrec->pbcType == PbcType::Screw)
{
gmx_fatal(FARGS, "pbc=screw is only implemented with domain decomposition");
}
}
- // Produce the task assignment for this rank.
- GpuTaskAssignmentsBuilder gpuTaskAssignmentsBuilder;
- GpuTaskAssignments gpuTaskAssignments = gpuTaskAssignmentsBuilder.build(
+ // Produce the task assignment for this rank - done after DD is constructed
+ GpuTaskAssignments gpuTaskAssignments = GpuTaskAssignmentsBuilder::build(
gpuIdsToUse, userGpuTaskAssignment, *hwinfo, communicator, physicalNodeComm,
nonbondedTarget, pmeTarget, bondedTarget, updateTarget, useGpuForNonbonded,
useGpuForPme, thisRankHasDuty(cr, DUTY_PP),
EEL_PME(inputrec->coulombtype) && thisRankHasDuty(cr, DUTY_PME));
// Get the device handles for the modules, nullptr when no task is assigned.
- gmx_device_info_t* nonbondedDeviceInfo = gpuTaskAssignments.initNonbondedDevice(cr);
- gmx_device_info_t* pmeDeviceInfo = gpuTaskAssignments.initPmeDevice();
+ int deviceId = -1;
+ DeviceInformation* deviceInfo = gpuTaskAssignments.initDevice(&deviceId);
- // TODO Initialize GPU streams here.
+ // timing enabling - TODO put this in gpu_utils (even though generally this is just option handling?)
+ bool useTiming = true;
+ if (GMX_GPU == GMX_GPU_CUDA)
+ {
+ /* WARNING: CUDA timings are incorrect with multiple streams.
+ * This is the main reason why they are disabled by default.
+ */
+ // TODO: Consider turning on by default when we can detect nr of streams.
+ useTiming = (getenv("GMX_ENABLE_GPU_TIMING") != nullptr);
+ }
+ else if (GMX_GPU == GMX_GPU_OPENCL)
+ {
+ useTiming = (getenv("GMX_DISABLE_GPU_TIMING") == nullptr);
+ }
// TODO Currently this is always built, yet DD partition code
// checks if it is built before using it. Probably it should
const bool printHostName = (cr->nnodes > 1);
gpuTaskAssignments.reportGpuUsage(mdlog, printHostName, useGpuForBonded, pmeRunMode, useGpuForUpdate);
+ std::unique_ptr<DeviceStreamManager> deviceStreamManager = nullptr;
+
+ if (deviceInfo != nullptr)
+ {
+ if (DOMAINDECOMP(cr) && thisRankHasDuty(cr, DUTY_PP))
+ {
+ dd_setup_dlb_resource_sharing(cr, deviceId);
+ }
+ deviceStreamManager = std::make_unique<DeviceStreamManager>(
+ *deviceInfo, useGpuForPme, useGpuForNonbonded, havePPDomainDecomposition(cr),
+ useGpuForUpdate, useTiming);
+ }
+
// If the user chose a task assignment, give them some hints
// where appropriate.
if (!userGpuTaskAssignment.empty())
/* Master synchronizes its value of reset_counters with all nodes
* including PME only nodes */
int64_t reset_counters = wcycle_get_reset_counters(wcycle);
- gmx_bcast_sim(sizeof(reset_counters), &reset_counters, cr);
+ gmx_bcast(sizeof(reset_counters), &reset_counters, cr->mpi_comm_mysim);
wcycle_set_reset_counters(wcycle, reset_counters);
}
const bool thisRankHasPmeGpuTask = gpuTaskAssignments.thisRankHasPmeGpuTask();
std::unique_ptr<MDAtoms> mdAtoms;
std::unique_ptr<gmx_vsite_t> vsite;
+ std::unique_ptr<GpuBonded> gpuBonded;
t_nrnb nrnb;
if (thisRankHasDuty(cr, DUTY_PP))
{
mdModulesNotifier.notify(*cr);
mdModulesNotifier.notify(&atomSets);
- mdModulesNotifier.notify(PeriodicBoundaryConditionType{ inputrec->ePBC });
+ mdModulesNotifier.notify(inputrec->pbcType);
mdModulesNotifier.notify(SimulationTimeStep{ inputrec->delta_t });
/* Initiate forcerecord */
fr = new t_forcerec;
init_forcerec(fplog, mdlog, fr, fcd, inputrec, &mtop, cr, box,
opt2fn("-table", filenames.size(), filenames.data()),
opt2fn("-tablep", filenames.size(), filenames.data()),
- opt2fns("-tableb", filenames.size(), filenames.data()), *hwinfo,
- nonbondedDeviceInfo, useGpuForBonded,
- pmeRunMode == PmeRunMode::GPU && !thisRankHasDuty(cr, DUTY_PME), pforce, wcycle);
-
- // TODO Move this to happen during domain decomposition setup,
- // once stream and event handling works well with that.
- // TODO remove need to pass local stream into GPU halo exchange - Redmine #3093
- if (havePPDomainDecomposition(cr) && prefer1DAnd1PulseDD && is1DAnd1PulseDD(*cr->dd))
+ opt2fns("-tableb", filenames.size(), filenames.data()), pforce);
+
+ // Save a handle to device stream manager to use elsewhere in the code
+ // TODO: Forcerec is not a correct place to store it.
+ fr->deviceStreamManager = deviceStreamManager.get();
+
+ if (devFlags.enableGpuPmePPComm && !thisRankHasDuty(cr, DUTY_PME))
{
- GMX_RELEASE_ASSERT(devFlags.enableGpuBufferOps,
- "Must use GMX_USE_GPU_BUFFER_OPS=1 to use GMX_GPU_DD_COMMS=1");
- void* streamLocal =
- Nbnxm::gpu_get_command_stream(fr->nbv->gpu_nbv, InteractionLocality::Local);
- void* streamNonLocal =
- Nbnxm::gpu_get_command_stream(fr->nbv->gpu_nbv, InteractionLocality::NonLocal);
- GMX_LOG(mdlog.warning)
- .asParagraph()
- .appendTextFormatted(
- "NOTE: This run uses the 'GPU halo exchange' feature, enabled by the "
- "GMX_GPU_DD_COMMS environment variable.");
- cr->dd->gpuHaloExchange = std::make_unique<GpuHaloExchange>(
- cr->dd, cr->mpi_comm_mysim, streamLocal, streamNonLocal);
+ GMX_RELEASE_ASSERT(
+ deviceStreamManager != nullptr,
+ "GPU device stream manager should be valid in order to use PME-PP direct "
+ "communications.");
+ GMX_RELEASE_ASSERT(
+ deviceStreamManager->streamIsValid(DeviceStreamType::PmePpTransfer),
+ "GPU PP-PME stream should be valid in order to use GPU PME-PP direct "
+ "communications.");
+ fr->pmePpCommGpu = std::make_unique<gmx::PmePpCommGpu>(
+ cr->mpi_comm_mysim, cr->dd->pme_nodeid, deviceStreamManager->context(),
+ deviceStreamManager->stream(DeviceStreamType::PmePpTransfer));
+ }
+
+ fr->nbv = Nbnxm::init_nb_verlet(mdlog, inputrec, fr, cr, *hwinfo, useGpuForNonbonded,
+ deviceStreamManager.get(), &mtop, box, wcycle);
+ // TODO: Move the logic below to a GPU bonded builder
+ if (useGpuForBonded)
+ {
+ GMX_RELEASE_ASSERT(deviceStreamManager != nullptr,
+ "GPU device stream manager should be valid in order to use GPU "
+ "version of bonded forces.");
+ gpuBonded = std::make_unique<GpuBonded>(
+ mtop.ffparams, fr->ic->epsfac * fr->fudgeQQ, deviceStreamManager->context(),
+ deviceStreamManager->bondedStream(havePPDomainDecomposition(cr)), wcycle);
+ fr->gpuBonded = gpuBonded.get();
}
/* Initialize the mdAtoms structure.
/* With periodic molecules the charge groups should be whole at start up
* and the virtual sites should not be far from their proper positions.
*/
- if (!inputrec->bContinuation && MASTER(cr) && !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols))
+ if (!inputrec->bContinuation && MASTER(cr)
+ && !(inputrec->pbcType != PbcType::No && inputrec->bPeriodicMols))
{
/* Make molecules whole at start of run */
- if (fr->ePBC != epbcNONE)
+ if (fr->pbcType != PbcType::No)
{
- do_pbc_first_mtop(fplog, inputrec->ePBC, box, &mtop, globalState->x.rvec_array());
+ do_pbc_first_mtop(fplog, inputrec->pbcType, box, &mtop, globalState->x.rvec_array());
}
if (vsite)
{
PmeGpuProgramStorage pmeGpuProgram;
if (thisRankHasPmeGpuTask)
{
- pmeGpuProgram = buildPmeGpuProgram(pmeDeviceInfo);
+ GMX_RELEASE_ASSERT(
+ (deviceStreamManager != nullptr),
+ "GPU device stream manager should be initialized in order to use GPU for PME.");
+ GMX_RELEASE_ASSERT((deviceInfo != nullptr),
+ "GPU device should be initialized in order to use GPU for PME.");
+ pmeGpuProgram = buildPmeGpuProgram(deviceStreamManager->context());
}
/* Initiate PME if necessary,
if (cr->npmenodes > 0)
{
/* The PME only nodes need to know nChargePerturbed(FEP on Q) and nTypePerturbed(FEP on LJ)*/
- gmx_bcast_sim(sizeof(nChargePerturbed), &nChargePerturbed, cr);
- gmx_bcast_sim(sizeof(nTypePerturbed), &nTypePerturbed, cr);
+ gmx_bcast(sizeof(nChargePerturbed), &nChargePerturbed, cr->mpi_comm_mysim);
+ gmx_bcast(sizeof(nTypePerturbed), &nTypePerturbed, cr->mpi_comm_mysim);
}
if (thisRankHasDuty(cr, DUTY_PME))
{
try
{
+ // TODO: This should be in the builder.
+ GMX_RELEASE_ASSERT(!useGpuForPme || (deviceStreamManager != nullptr),
+ "Device stream manager should be valid in order to use GPU "
+ "version of PME.");
+ GMX_RELEASE_ASSERT(
+ !useGpuForPme || deviceStreamManager->streamIsValid(DeviceStreamType::Pme),
+ "GPU PME stream should be valid in order to use GPU version of PME.");
+
+ const DeviceContext* deviceContext =
+ useGpuForPme ? &deviceStreamManager->context() : nullptr;
+ const DeviceStream* pmeStream =
+ useGpuForPme ? &deviceStreamManager->stream(DeviceStreamType::Pme) : nullptr;
+
pmedata = gmx_pme_init(cr, getNumPmeDomains(cr->dd), inputrec, nChargePerturbed != 0,
nTypePerturbed != 0, mdrunOptions.reproducible, ewaldcoeff_q,
ewaldcoeff_lj, gmx_omp_nthreads_get(emntPME), pmeRunMode,
- nullptr, pmeDeviceInfo, pmeGpuProgram.get(), mdlog);
+ nullptr, deviceContext, pmeStream, pmeGpuProgram.get(), mdlog);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
/* This call is not included in init_domain_decomposition mainly
* because fr->cginfo_mb is set later.
*/
- dd_init_bondeds(fplog, cr->dd, &mtop, vsite.get(), inputrec,
+ dd_init_bondeds(fplog, cr->dd, mtop, vsite.get(), inputrec,
domdecOptions.checkBondedInteractions, fr->cginfo_mb);
}
// make it work.
MdrunScheduleWorkload runScheduleWork;
// Also populates the simulation constant workload description.
- runScheduleWork.simulationWork = createSimulationWorkload(
- useGpuForNonbonded, pmeRunMode, useGpuForBonded, useGpuForUpdate,
- devFlags.enableGpuBufferOps, devFlags.enableGpuHaloExchange,
- devFlags.enableGpuPmePPComm, haveEwaldSurfaceContribution(*inputrec));
+ runScheduleWork.simulationWork =
+ createSimulationWorkload(*inputrec, useGpuForNonbonded, pmeRunMode, useGpuForBonded,
+ useGpuForUpdate, devFlags.enableGpuBufferOps,
+ devFlags.enableGpuHaloExchange, devFlags.enableGpuPmePPComm);
std::unique_ptr<gmx::StatePropagatorDataGpu> stateGpu;
if (gpusWereDetected
&& ((useGpuForPme && thisRankHasDuty(cr, DUTY_PME))
|| runScheduleWork.simulationWork.useGpuBufferOps))
{
- const void* pmeStream = pme_gpu_get_device_stream(fr->pmedata);
- const void* localStream =
- fr->nbv->gpu_nbv != nullptr
- ? Nbnxm::gpu_get_command_stream(fr->nbv->gpu_nbv, InteractionLocality::Local)
- : nullptr;
- const void* nonLocalStream =
- fr->nbv->gpu_nbv != nullptr
- ? Nbnxm::gpu_get_command_stream(fr->nbv->gpu_nbv, InteractionLocality::NonLocal)
- : nullptr;
- const void* deviceContext = pme_gpu_get_device_context(fr->pmedata);
- const int paddingSize = pme_gpu_get_padding_size(fr->pmedata);
GpuApiCallBehavior transferKind = (inputrec->eI == eiMD && !doRerun && !useModularSimulator)
? GpuApiCallBehavior::Async
: GpuApiCallBehavior::Sync;
-
+ GMX_RELEASE_ASSERT(deviceStreamManager != nullptr,
+ "GPU device stream manager should be initialized to use GPU.");
stateGpu = std::make_unique<gmx::StatePropagatorDataGpu>(
- pmeStream, localStream, nonLocalStream, deviceContext, transferKind, paddingSize, wcycle);
+ *deviceStreamManager, transferKind, pme_gpu_get_block_size(fr->pmedata), wcycle);
fr->stateGpu = stateGpu.get();
}
// build and run simulator object based on user-input
auto simulator = simulatorBuilder.build(
- inputIsCompatibleWithModularSimulator, fplog, cr, ms, mdlog,
- static_cast<int>(filenames.size()), filenames.data(), oenv, mdrunOptions,
- startingBehavior, vsite.get(), constr.get(),
+ useModularSimulator, fplog, cr, ms, mdlog, static_cast<int>(filenames.size()),
+ filenames.data(), oenv, mdrunOptions, startingBehavior, vsite.get(), constr.get(),
enforcedRotation ? enforcedRotation->getLegacyEnfrot() : nullptr, deform.get(),
mdModules_->outputProvider(), mdModules_->notifier(), inputrec, imdSession.get(),
pull_work, swap, &mtop, fcd, globalState.get(), &observablesHistory, mdAtoms.get(),
GMX_RELEASE_ASSERT(pmedata, "pmedata was NULL while cr->duty was not DUTY_PP");
/* do PME only */
walltime_accounting = walltime_accounting_init(gmx_omp_nthreads_get(emntPME));
- gmx_pmeonly(pmedata, cr, &nrnb, wcycle, walltime_accounting, inputrec, pmeRunMode);
+ gmx_pmeonly(pmedata, cr, &nrnb, wcycle, walltime_accounting, inputrec, pmeRunMode,
+ deviceStreamManager.get());
}
wallcycle_stop(wcycle, ewcRUN);
// clean up cycle counter
wallcycle_destroy(wcycle);
+ deviceStreamManager.reset(nullptr);
// Free PME data
if (pmedata)
{
}
// FIXME: this is only here to manually unpin mdAtoms->chargeA_ and state->x,
- // before we destroy the GPU context(s) in free_gpu_resources().
+ // before we destroy the GPU context(s) in free_gpu().
// Pinned buffers are associated with contexts in CUDA.
// As soon as we destroy GPU contexts after mdrunner() exits, these lines should go.
mdAtoms.reset(nullptr);
globalState.reset(nullptr);
mdModules_.reset(nullptr); // destruct force providers here as they might also use the GPU
+ gpuBonded.reset(nullptr);
+ /* Free pinned buffers in *fr */
+ delete fr;
+ fr = nullptr;
+
+ if (hwinfo->gpu_info.n_dev > 0)
+ {
+ /* stop the GPU profiler (only CUDA) */
+ stopGpuProfiler();
+ }
+
+ /* With tMPI we need to wait for all ranks to finish deallocation before
+ * destroying the CUDA context in free_gpu() as some tMPI ranks may be sharing
+ * GPU and context.
+ *
+ * This is not a concern in OpenCL where we use one context per rank which
+ * is freed in nbnxn_gpu_free().
+ *
+ * Note: it is safe to not call the barrier on the ranks which do not use GPU,
+ * but it is easier and more futureproof to call it on the whole node.
+ *
+ * Note that this function needs to be called even if GPUs are not used
+ * in this run because the PME ranks have no knowledge of whether GPUs
+ * are used or not, but all ranks need to enter the barrier below.
+ * \todo Remove this physical node barrier after making sure
+ * that it's not needed anymore (with a shared GPU run).
+ */
+ if (GMX_THREAD_MPI)
+ {
+ physicalNodeComm.barrier();
+ }
- /* Free GPU memory and set a physical node tMPI barrier (which should eventually go away) */
- free_gpu_resources(fr, physicalNodeComm, hwinfo->gpu_info);
- free_gpu(nonbondedDeviceInfo);
- free_gpu(pmeDeviceInfo);
- done_forcerec(fr, mtop.molblock.size());
+ free_gpu(deviceInfo);
sfree(fcd);
if (doMembed)
}
#endif
return rc;
-}
+} // namespace gmx
Mdrunner::~Mdrunner()
{
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
-#include "gromacs/pbcutil/mshift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/mtop_lookup.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
-#include "gromacs/utility/smalloc.h"
-typedef struct
+using gmx::ArrayRef;
+using gmx::ArrayRefWithPadding;
+using gmx::RVec;
+
+struct t_shell
{
- int nnucl;
- int shell; /* The shell id */
- int nucl1, nucl2, nucl3; /* The nuclei connected to the shell */
- /* gmx_bool bInterCG; */ /* Coupled to nuclei outside cg? */
- real k; /* force constant */
- real k_1; /* 1 over force constant */
- rvec xold;
- rvec fold;
- rvec step;
-} t_shell;
+ int nnucl = 0; /* The number of nuclei */
+ int shellIndex = -1; /* The shell index */
+ int nucl1 = -1; /* The first nuclei connected to the shell */
+ int nucl2 = -1; /* The second nuclei connected to the shell */
+ int nucl3 = -1; /* The third nuclei connected to the shell */
+ real k = 0; /* force constant */
+ real k_1 = 0; /* 1 over force constant */
+ rvec xold; /* The old shell coordinates */
+ rvec fold; /* The old force on the shell */
+ rvec step; /* Step size for steepest descents */
+};
struct gmx_shellfc_t
{
/* Shell counts, indices, parameters and working data */
- int nshell_gl; /* The number of shells in the system */
- t_shell* shell_gl; /* All the shells (for DD only) */
- int* shell_index_gl; /* Global shell index (for DD only) */
- gmx_bool bInterCG; /* Are there inter charge-group shells? */
- int nshell; /* The number of local shells */
- t_shell* shell; /* The local shells */
- int shell_nalloc; /* The allocation size of shell */
- gmx_bool bPredict; /* Predict shell positions */
- gmx_bool bRequireInit; /* Require initialization of shell positions */
- int nflexcon; /* The number of flexible constraints */
-
- /* Temporary arrays, should be fixed size 2 when fully converted to C++ */
- PaddedHostVector<gmx::RVec>* x; /* Array for iterative minimization */
- PaddedHostVector<gmx::RVec>* f; /* Array for iterative minimization */
+ std::vector<t_shell> shell_gl; /* All the shells (for DD only) */
+ std::vector<int> shell_index_gl; /* Global shell index (for DD only) */
+ gmx_bool bInterCG; /* Are there inter charge-group shells? */
+ std::vector<t_shell> shells; /* The local shells */
+ bool predictShells = false; /* Predict shell positions */
+ bool requireInit = false; /* Require initialization of shell positions */
+ int nflexcon = 0; /* The number of flexible constraints */
+
+ std::array<PaddedHostVector<RVec>, 2> x; /* Coordinate buffers for iterative minimization */
+ std::array<PaddedHostVector<RVec>, 2> f; /* Force buffers for iterative minimization */
/* Flexible constraint working data */
- rvec* acc_dir; /* Acceleration direction for flexcon */
- rvec* x_old; /* Old coordinates for flexcon */
- int flex_nalloc; /* The allocation size of acc_dir and x_old */
- rvec* adir_xnold; /* Work space for init_adir */
- rvec* adir_xnew; /* Work space for init_adir */
- int adir_nalloc; /* Work space for init_adir */
- std::int64_t numForceEvaluations; /* Total number of force evaluations */
- int numConvergedIterations; /* Total number of iterations that converged */
+ std::vector<RVec> acc_dir; /* Acceleration direction for flexcon */
+ gmx::PaddedVector<RVec> x_old; /* Old coordinates for flexcon */
+ gmx::PaddedVector<RVec> adir_xnold; /* Work space for init_adir */
+ gmx::PaddedVector<RVec> adir_xnew; /* Work space for init_adir */
+ std::int64_t numForceEvaluations; /* Total number of force evaluations */
+ int numConvergedIterations; /* Total number of iterations that converged */
};
-static void pr_shell(FILE* fplog, int ns, t_shell s[])
+static void pr_shell(FILE* fplog, ArrayRef<const t_shell> shells)
{
- int i;
-
fprintf(fplog, "SHELL DATA\n");
fprintf(fplog, "%5s %8s %5s %5s %5s\n", "Shell", "Force k", "Nucl1", "Nucl2", "Nucl3");
- for (i = 0; (i < ns); i++)
+ for (const t_shell& shell : shells)
{
- fprintf(fplog, "%5d %8.3f %5d", s[i].shell, 1.0 / s[i].k_1, s[i].nucl1);
- if (s[i].nnucl == 2)
+ fprintf(fplog, "%5d %8.3f %5d", shell.shellIndex, 1.0 / shell.k_1, shell.nucl1);
+ if (shell.nnucl == 2)
{
- fprintf(fplog, " %5d\n", s[i].nucl2);
+ fprintf(fplog, " %5d\n", shell.nucl2);
}
- else if (s[i].nnucl == 3)
+ else if (shell.nnucl == 3)
{
- fprintf(fplog, " %5d %5d\n", s[i].nucl2, s[i].nucl3);
+ fprintf(fplog, " %5d %5d\n", shell.nucl2, shell.nucl3);
}
else
{
* started, but even when called, the prediction was always
* over-written by a subsequent call in the MD loop, so has been
* removed. */
-static void predict_shells(FILE* fplog,
- rvec x[],
- rvec v[],
- real dt,
- int ns,
- t_shell s[],
- const real mass[],
- gmx_mtop_t* mtop,
- gmx_bool bInit)
+static void predict_shells(FILE* fplog,
+ ArrayRef<RVec> x,
+ ArrayRef<RVec> v,
+ real dt,
+ ArrayRef<const t_shell> shells,
+ const real mass[],
+ gmx_mtop_t* mtop,
+ gmx_bool bInit)
{
- int i, m, s1, n1, n2, n3;
- real dt_1, fudge, tm, m1, m2, m3;
- rvec* ptr;
+ int m, n1, n2, n3;
+ real dt_1, fudge, tm, m1, m2, m3;
GMX_RELEASE_ASSERT(mass || mtop, "Must have masses or a way to look them up");
*/
fudge = 1.0;
+ ArrayRef<RVec> xOrV;
if (bInit)
{
if (fplog)
{
fprintf(fplog, "RELAX: Using prediction for initial shell placement\n");
}
- ptr = x;
+ xOrV = x;
dt_1 = 1;
}
else
{
- ptr = v;
+ xOrV = v;
dt_1 = fudge * dt;
}
int molb = 0;
- for (i = 0; (i < ns); i++)
+ for (const t_shell& shell : shells)
{
- s1 = s[i].shell;
+ const int s1 = shell.shellIndex;
if (bInit)
{
clear_rvec(x[s1]);
}
- switch (s[i].nnucl)
+ switch (shell.nnucl)
{
case 1:
- n1 = s[i].nucl1;
+ n1 = shell.nucl1;
for (m = 0; (m < DIM); m++)
{
- x[s1][m] += ptr[n1][m] * dt_1;
+ x[s1][m] += xOrV[n1][m] * dt_1;
}
break;
case 2:
- n1 = s[i].nucl1;
- n2 = s[i].nucl2;
+ n1 = shell.nucl1;
+ n2 = shell.nucl2;
if (mass)
{
m1 = mass[n1];
tm = dt_1 / (m1 + m2);
for (m = 0; (m < DIM); m++)
{
- x[s1][m] += (m1 * ptr[n1][m] + m2 * ptr[n2][m]) * tm;
+ x[s1][m] += (m1 * xOrV[n1][m] + m2 * xOrV[n2][m]) * tm;
}
break;
case 3:
- n1 = s[i].nucl1;
- n2 = s[i].nucl2;
- n3 = s[i].nucl3;
+ n1 = shell.nucl1;
+ n2 = shell.nucl2;
+ n3 = shell.nucl3;
if (mass)
{
m1 = mass[n1];
tm = dt_1 / (m1 + m2 + m3);
for (m = 0; (m < DIM); m++)
{
- x[s1][m] += (m1 * ptr[n1][m] + m2 * ptr[n2][m] + m3 * ptr[n3][m]) * tm;
+ x[s1][m] += (m1 * xOrV[n1][m] + m2 * xOrV[n2][m] + m3 * xOrV[n3][m]) * tm;
}
break;
- default: gmx_fatal(FARGS, "Shell %d has %d nuclei!", i, s[i].nnucl);
+ default: gmx_fatal(FARGS, "Shell %d has %d nuclei!", s1, shell.nnucl);
}
}
}
gmx_shellfc_t* init_shell_flexcon(FILE* fplog, const gmx_mtop_t* mtop, int nflexcon, int nstcalcenergy, bool usingDomainDecomposition)
{
gmx_shellfc_t* shfc;
- t_shell* shell;
- int* shell_index = nullptr;
int ns, nshell, nsi;
int i, j, type, a_offset, mol, ftype, nra;
return nullptr;
}
- snew(shfc, 1);
- shfc->x = new PaddedHostVector<gmx::RVec>[2] {};
- shfc->f = new PaddedHostVector<gmx::RVec>[2] {};
+ shfc = new gmx_shellfc_t;
shfc->nflexcon = nflexcon;
if (nshell == 0)
/* Only flexible constraints, no shells.
* Note that make_local_shells() does not need to be called.
*/
- shfc->nshell = 0;
- shfc->bPredict = FALSE;
-
return shfc;
}
/* We have shells: fill the shell data structure */
/* Global system sized array, this should be avoided */
- snew(shell_index, mtop->natoms);
+ std::vector<int> shell_index(mtop->natoms);
nshell = 0;
for (const AtomProxy atomP : AtomRange(*mtop))
}
}
- snew(shell, nshell);
-
- /* Initiate the shell structures */
- for (i = 0; (i < nshell); i++)
- {
- shell[i].shell = -1;
- shell[i].nnucl = 0;
- shell[i].nucl1 = -1;
- shell[i].nucl2 = -1;
- shell[i].nucl3 = -1;
- /* shell[i].bInterCG=FALSE; */
- shell[i].k_1 = 0;
- shell[i].k = 0;
- }
+ std::vector<t_shell> shell(nshell);
ffparams = &mtop->ffparams;
{
gmx_fatal(FARGS, "nsi is %d should be within 0 - %d. aS = %d", nsi, nshell, aS);
}
- if (shell[nsi].shell == -1)
+ if (shell[nsi].shellIndex == -1)
{
- shell[nsi].shell = a_offset + aS;
+ shell[nsi].shellIndex = a_offset + aS;
ns++;
}
- else if (shell[nsi].shell != a_offset + aS)
+ else if (shell[nsi].shellIndex != a_offset + aS)
{
gmx_fatal(FARGS, "Weird stuff in %s, %d", __FILE__, __LINE__);
}
{
if (fplog)
{
- pr_shell(fplog, ns, shell);
+ pr_shell(fplog, shell);
}
gmx_fatal(FARGS, "Can not handle more than three bonds per shell\n");
}
if (debug)
{
- pr_shell(debug, ns, shell);
+ pr_shell(debug, shell);
}
- shfc->nshell_gl = ns;
shfc->shell_gl = shell;
shfc->shell_index_gl = shell_index;
- shfc->bPredict = (getenv("GMX_NOPREDICT") == nullptr);
- shfc->bRequireInit = FALSE;
- if (!shfc->bPredict)
+ shfc->predictShells = (getenv("GMX_NOPREDICT") == nullptr);
+ shfc->requireInit = false;
+ if (!shfc->predictShells)
{
if (fplog)
{
}
else
{
- shfc->bRequireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != nullptr);
- if (shfc->bRequireInit && fplog)
+ shfc->requireInit = (getenv("GMX_REQUIRE_SHELL_INIT") != nullptr);
+ if (shfc->requireInit && fplog)
{
fprintf(fplog, "\nWill always initiate shell positions\n");
}
}
- if (shfc->bPredict)
+ if (shfc->predictShells)
{
if (shfc->bInterCG)
{
* shell velocities are zeroed, it's a bit tricky to keep
* track of the shell displacements and thus the velocity.
*/
- shfc->bPredict = FALSE;
+ shfc->predictShells = false;
}
}
return shfc;
}
-void make_local_shells(const t_commrec* cr, const t_mdatoms* md, gmx_shellfc_t* shfc)
+void gmx::make_local_shells(const t_commrec* cr, const t_mdatoms* md, gmx_shellfc_t* shfc)
{
- t_shell* shell;
- int a0, a1, *ind, nshell, i;
+ int a0, a1;
gmx_domdec_t* dd = nullptr;
if (DOMAINDECOMP(cr))
}
else
{
- /* Single node: we need all shells, just copy the pointer */
- shfc->nshell = shfc->nshell_gl;
- shfc->shell = shfc->shell_gl;
+ /* Single node: we need all shells, copy them */
+ shfc->shells = shfc->shell_gl;
return;
}
- ind = shfc->shell_index_gl;
+ ArrayRef<const int> ind = shfc->shell_index_gl;
- nshell = 0;
- shell = shfc->shell;
- for (i = a0; i < a1; i++)
+ std::vector<t_shell>& shells = shfc->shells;
+ shells.clear();
+ for (int i = a0; i < a1; i++)
{
if (md->ptype[i] == eptShell)
{
- if (nshell + 1 > shfc->shell_nalloc)
- {
- shfc->shell_nalloc = over_alloc_dd(nshell + 1);
- srenew(shell, shfc->shell_nalloc);
- }
if (dd)
{
- shell[nshell] = shfc->shell_gl[ind[dd->globalAtomIndices[i]]];
+ shells.push_back(shfc->shell_gl[ind[dd->globalAtomIndices[i]]]);
}
else
{
- shell[nshell] = shfc->shell_gl[ind[i]];
+ shells.push_back(shfc->shell_gl[ind[i]]);
}
+ t_shell& shell = shells.back();
/* With inter-cg shells we can no do shell prediction,
* so we do not need the nuclei numbers.
*/
if (!shfc->bInterCG)
{
- shell[nshell].nucl1 = i + shell[nshell].nucl1 - shell[nshell].shell;
- if (shell[nshell].nnucl > 1)
+ shell.nucl1 = i + shell.nucl1 - shell.shellIndex;
+ if (shell.nnucl > 1)
{
- shell[nshell].nucl2 = i + shell[nshell].nucl2 - shell[nshell].shell;
+ shell.nucl2 = i + shell.nucl2 - shell.shellIndex;
}
- if (shell[nshell].nnucl > 2)
+ if (shell.nnucl > 2)
{
- shell[nshell].nucl3 = i + shell[nshell].nucl3 - shell[nshell].shell;
+ shell.nucl3 = i + shell.nucl3 - shell.shellIndex;
}
}
- shell[nshell].shell = i;
- nshell++;
+ shell.shellIndex = i;
}
}
-
- shfc->nshell = nshell;
- shfc->shell = shell;
}
static void do_1pos(rvec xnew, const rvec xold, const rvec f, real step)
xnew[ZZ] = zo + dz;
}
-static void directional_sd(gmx::ArrayRef<const gmx::RVec> xold,
- gmx::ArrayRef<gmx::RVec> xnew,
- const rvec acc_dir[],
- int homenr,
- real step)
+static void directional_sd(ArrayRef<const RVec> xold,
+ ArrayRef<RVec> xnew,
+ ArrayRef<const RVec> acc_dir,
+ int homenr,
+ real step)
{
const rvec* xo = as_rvec_array(xold.data());
rvec* xn = as_rvec_array(xnew.data());
}
}
-static void shell_pos_sd(gmx::ArrayRef<const gmx::RVec> xcur,
- gmx::ArrayRef<gmx::RVec> xnew,
- gmx::ArrayRef<const gmx::RVec> f,
- int ns,
- t_shell s[],
- int count)
+static void shell_pos_sd(ArrayRef<const RVec> xcur,
+ ArrayRef<RVec> xnew,
+ ArrayRef<const RVec> f,
+ ArrayRef<t_shell> shells,
+ int count)
{
const real step_scale_min = 0.8, step_scale_increment = 0.2, step_scale_max = 1.2,
step_scale_multiple = (step_scale_max - step_scale_min) / step_scale_increment;
- int i, shell, d;
+ int d;
real dx, df, k_est;
const real zero = 0;
#ifdef PRINT_STEP
step_min = 1e30;
step_max = 0;
#endif
- for (i = 0; (i < ns); i++)
+ for (t_shell& shell : shells)
{
- shell = s[i].shell;
+ const int ind = shell.shellIndex;
if (count == 1)
{
for (d = 0; d < DIM; d++)
{
- s[i].step[d] = s[i].k_1;
+ shell.step[d] = shell.k_1;
#ifdef PRINT_STEP
- step_min = std::min(step_min, s[i].step[d]);
- step_max = std::max(step_max, s[i].step[d]);
+ step_min = std::min(step_min, shell.step[d]);
+ step_max = std::max(step_max, shell.step[d]);
#endif
}
}
{
for (d = 0; d < DIM; d++)
{
- dx = xcur[shell][d] - s[i].xold[d];
- df = f[shell][d] - s[i].fold[d];
+ dx = xcur[ind][d] - shell.xold[d];
+ df = f[ind][d] - shell.fold[d];
/* -dx/df gets used to generate an interpolated value, but would
* cause a NaN if df were binary-equal to zero. Values close to
* zero won't cause problems (because of the min() and max()), so
k_est = -dx / df;
/* Scale the step size by a factor interpolated from
* step_scale_min to step_scale_max, as k_est goes from 0 to
- * step_scale_multiple * s[i].step[d] */
- s[i].step[d] = step_scale_min * s[i].step[d]
- + step_scale_increment
- * std::min(step_scale_multiple * s[i].step[d],
- std::max(k_est, zero));
+ * step_scale_multiple * shell.step[d] */
+ shell.step[d] = step_scale_min * shell.step[d]
+ + step_scale_increment
+ * std::min(step_scale_multiple * shell.step[d],
+ std::max(k_est, zero));
}
else
{
}
else /* 0 != dx */
{
- s[i].step[d] *= step_scale_max;
+ shell.step[d] *= step_scale_max;
}
}
#ifdef PRINT_STEP
- step_min = std::min(step_min, s[i].step[d]);
- step_max = std::max(step_max, s[i].step[d]);
+ step_min = std::min(step_min, shell.step[d]);
+ step_max = std::max(step_max, shell.step[d]);
#endif
}
}
- copy_rvec(xcur[shell], s[i].xold);
- copy_rvec(f[shell], s[i].fold);
+ copy_rvec(xcur[ind], shell.xold);
+ copy_rvec(f[ind], shell.fold);
- do_1pos3(xnew[shell], xcur[shell], f[shell], s[i].step);
+ do_1pos3(xnew[ind], xcur[ind], f[ind], shell.step);
if (gmx_debug_at)
{
- fprintf(debug, "shell[%d] = %d\n", i, shell);
- pr_rvec(debug, 0, "fshell", f[shell], DIM, TRUE);
- pr_rvec(debug, 0, "xold", xcur[shell], DIM, TRUE);
- pr_rvec(debug, 0, "step", s[i].step, DIM, TRUE);
- pr_rvec(debug, 0, "xnew", xnew[shell], DIM, TRUE);
+ fprintf(debug, "shell = %d\n", ind);
+ pr_rvec(debug, 0, "fshell", f[ind], DIM, TRUE);
+ pr_rvec(debug, 0, "xold", xcur[ind], DIM, TRUE);
+ pr_rvec(debug, 0, "step", shell.step, DIM, TRUE);
+ pr_rvec(debug, 0, "xnew", xnew[ind], DIM, TRUE);
}
}
#ifdef PRINT_STEP
#endif
}
-static void decrease_step_size(int nshell, t_shell s[])
+static void decrease_step_size(ArrayRef<t_shell> shells)
{
- int i;
-
- for (i = 0; i < nshell; i++)
+ for (t_shell& shell : shells)
{
- svmul(0.8, s[i].step, s[i].step);
+ svmul(0.8, shell.step, shell.step);
}
}
}
-static real rms_force(const t_commrec* cr,
- gmx::ArrayRef<const gmx::RVec> force,
- int ns,
- t_shell s[],
- int ndir,
- real* sf_dir,
- real* Epot)
+static real rms_force(const t_commrec* cr,
+ ArrayRef<const RVec> force,
+ ArrayRef<const t_shell> shells,
+ int ndir,
+ real* sf_dir,
+ real* Epot)
{
double buf[4];
const rvec* f = as_rvec_array(force.data());
buf[0] = *sf_dir;
- for (int i = 0; i < ns; i++)
+ for (const t_shell& shell : shells)
{
- int shell = s[i].shell;
- buf[0] += norm2(f[shell]);
+ buf[0] += norm2(f[shell.shellIndex]);
}
- int ntot = ns;
+ int ntot = shells.ssize();
if (PAR(cr))
{
return (ntot ? std::sqrt(buf[0] / ntot) : 0);
}
-static void dump_shells(FILE* fp, gmx::ArrayRef<gmx::RVec> f, real ftol, int ns, t_shell s[])
+static void dump_shells(FILE* fp, ArrayRef<RVec> f, real ftol, ArrayRef<const t_shell> shells)
{
- int i, shell;
real ft2, ff2;
ft2 = gmx::square(ftol);
- for (i = 0; (i < ns); i++)
+ for (const t_shell& shell : shells)
{
- shell = s[i].shell;
- ff2 = iprod(f[shell], f[shell]);
+ const int ind = shell.shellIndex;
+ ff2 = iprod(f[ind], f[ind]);
if (ff2 > ft2)
{
- fprintf(fp, "SHELL %5d, force %10.5f %10.5f %10.5f, |f| %10.5f\n", shell,
- f[shell][XX], f[shell][YY], f[shell][ZZ], std::sqrt(ff2));
+ fprintf(fp, "SHELL %5d, force %10.5f %10.5f %10.5f, |f| %10.5f\n", ind, f[ind][XX],
+ f[ind][YY], f[ind][ZZ], std::sqrt(ff2));
}
}
}
int64_t step,
const t_mdatoms* md,
int end,
- rvec* x_old,
- rvec* x_init,
- rvec* x,
- rvec* f,
- rvec* acc_dir,
+ ArrayRefWithPadding<RVec> xOld,
+ ArrayRef<RVec> x_init,
+ ArrayRefWithPadding<RVec> xCurrent,
+ ArrayRef<RVec> f,
+ ArrayRef<RVec> acc_dir,
const matrix box,
- gmx::ArrayRef<const real> lambda,
+ ArrayRef<const real> lambda,
real* dvdlambda)
{
- rvec * xnold, *xnew;
double dt, w_dt;
int n, d;
unsigned short* ptype;
{
n = end;
}
- if (n > shfc->adir_nalloc)
- {
- shfc->adir_nalloc = over_alloc_dd(n);
- srenew(shfc->adir_xnold, shfc->adir_nalloc);
- srenew(shfc->adir_xnew, shfc->adir_nalloc);
- }
- xnold = shfc->adir_xnold;
- xnew = shfc->adir_xnew;
+ shfc->adir_xnold.resizeWithPadding(n);
+ shfc->adir_xnew.resizeWithPadding(n);
+ rvec* xnold = as_rvec_array(shfc->adir_xnold.data());
+ rvec* xnew = as_rvec_array(shfc->adir_xnew.data());
+ rvec* x_old = as_rvec_array(xOld.paddedArrayRef().data());
+ rvec* x = as_rvec_array(xCurrent.paddedArrayRef().data());
ptype = md->ptype;
}
}
}
- constr->apply(FALSE, FALSE, step, 0, 1.0, x, xnold, nullptr, box, lambda[efptBONDED],
- &(dvdlambda[efptBONDED]), nullptr, nullptr, gmx::ConstraintVariable::Positions);
- constr->apply(FALSE, FALSE, step, 0, 1.0, x, xnew, nullptr, box, lambda[efptBONDED],
- &(dvdlambda[efptBONDED]), nullptr, nullptr, gmx::ConstraintVariable::Positions);
+ constr->apply(FALSE, FALSE, step, 0, 1.0, xCurrent, shfc->adir_xnold.arrayRefWithPadding(), {},
+ box, lambda[efptBONDED], &(dvdlambda[efptBONDED]), {}, nullptr,
+ gmx::ConstraintVariable::Positions);
+ constr->apply(FALSE, FALSE, step, 0, 1.0, xCurrent, shfc->adir_xnew.arrayRefWithPadding(), {},
+ box, lambda[efptBONDED], &(dvdlambda[efptBONDED]), {}, nullptr,
+ gmx::ConstraintVariable::Positions);
for (n = 0; n < end; n++)
{
}
/* Project the acceleration on the old bond directions */
- constr->apply(FALSE, FALSE, step, 0, 1.0, x_old, xnew, acc_dir, box, lambda[efptBONDED],
- &(dvdlambda[efptBONDED]), nullptr, nullptr, gmx::ConstraintVariable::Deriv_FlexCon);
+ constr->apply(FALSE, FALSE, step, 0, 1.0, xOld, shfc->adir_xnew.arrayRefWithPadding(), acc_dir,
+ box, lambda[efptBONDED], &(dvdlambda[efptBONDED]), {}, nullptr,
+ gmx::ConstraintVariable::Deriv_FlexCon);
}
-void relax_shell_flexcon(FILE* fplog,
- const t_commrec* cr,
- const gmx_multisim_t* ms,
- gmx_bool bVerbose,
- gmx_enfrot* enforcedRotation,
- int64_t mdstep,
- const t_inputrec* inputrec,
- gmx::ImdSession* imdSession,
- pull_t* pull_work,
- gmx_bool bDoNS,
- int force_flags,
- const gmx_localtop_t* top,
- gmx::Constraints* constr,
- gmx_enerdata_t* enerd,
- t_fcdata* fcd,
- int natoms,
- gmx::ArrayRefWithPadding<gmx::RVec> x,
- gmx::ArrayRefWithPadding<gmx::RVec> v,
- const matrix box,
- gmx::ArrayRef<real> lambda,
- history_t* hist,
- gmx::ArrayRefWithPadding<gmx::RVec> f,
- tensor force_vir,
- const t_mdatoms* md,
- t_nrnb* nrnb,
- gmx_wallcycle_t wcycle,
- t_graph* graph,
- gmx_shellfc_t* shfc,
- t_forcerec* fr,
- gmx::MdrunScheduleWorkload* runScheduleWork,
- double t,
- rvec mu_tot,
- const gmx_vsite_t* vsite,
- const DDBalanceRegionHandler& ddBalanceRegionHandler)
+void relax_shell_flexcon(FILE* fplog,
+ const t_commrec* cr,
+ const gmx_multisim_t* ms,
+ gmx_bool bVerbose,
+ gmx_enfrot* enforcedRotation,
+ int64_t mdstep,
+ const t_inputrec* inputrec,
+ gmx::ImdSession* imdSession,
+ pull_t* pull_work,
+ gmx_bool bDoNS,
+ int force_flags,
+ const gmx_localtop_t* top,
+ gmx::Constraints* constr,
+ gmx_enerdata_t* enerd,
+ t_fcdata* fcd,
+ int natoms,
+ ArrayRefWithPadding<RVec> xPadded,
+ ArrayRefWithPadding<RVec> vPadded,
+ const matrix box,
+ ArrayRef<real> lambda,
+ history_t* hist,
+ ArrayRefWithPadding<RVec> f,
+ tensor force_vir,
+ const t_mdatoms* md,
+ t_nrnb* nrnb,
+ gmx_wallcycle_t wcycle,
+ gmx_shellfc_t* shfc,
+ t_forcerec* fr,
+ gmx::MdrunScheduleWorkload* runScheduleWork,
+ double t,
+ rvec mu_tot,
+ const gmx_vsite_t* vsite,
+ const DDBalanceRegionHandler& ddBalanceRegionHandler)
{
- auto xRvec = as_rvec_array(x.paddedArrayRef().data());
- auto vRvec = as_rvec_array(v.paddedArrayRef().data());
-
- int nshell;
- t_shell* shell;
- const t_idef* idef;
- rvec * acc_dir = nullptr, *x_old = nullptr;
- real Epot[2], df[2];
- real sf_dir, invdt;
- real ftol, dum = 0;
- char sbuf[22];
- gmx_bool bCont, bInit, bConverged;
- int nat, dd_ac0, dd_ac1 = 0, i;
- int homenr = md->homenr, end = homenr;
- int nflexcon, number_steps, d, Min = 0, count = 0;
+ real Epot[2], df[2];
+ real sf_dir, invdt;
+ real dum = 0;
+ char sbuf[22];
+ int nat, dd_ac0, dd_ac1 = 0, i;
+ int homenr = md->homenr, end = homenr;
+ int d, Min = 0, count = 0;
#define Try (1 - Min) /* At start Try = 1 */
- bCont = (mdstep == inputrec->init_step) && inputrec->bContinuation;
- bInit = (mdstep == inputrec->init_step) || shfc->bRequireInit;
- ftol = inputrec->em_tol;
- number_steps = inputrec->niter;
- nshell = shfc->nshell;
- shell = shfc->shell;
- nflexcon = shfc->nflexcon;
+ const bool bCont = (mdstep == inputrec->init_step) && inputrec->bContinuation;
+ const bool bInit = (mdstep == inputrec->init_step) || shfc->requireInit;
+ const real ftol = inputrec->em_tol;
+ const int number_steps = inputrec->niter;
+ ArrayRef<t_shell> shells = shfc->shells;
+ const int nflexcon = shfc->nflexcon;
- idef = &top->idef;
+ const InteractionDefinitions& idef = top->idef;
if (DOMAINDECOMP(cr))
{
shfc->f[i].resizeWithPadding(nat);
}
- /* Create views that we can swap */
- gmx::ArrayRefWithPadding<gmx::RVec> posWithPadding[2];
- gmx::ArrayRefWithPadding<gmx::RVec> forceWithPadding[2];
- gmx::ArrayRef<gmx::RVec> pos[2];
- gmx::ArrayRef<gmx::RVec> force[2];
+ /* Create views that we can swap for trail and minimum for positions and forces */
+ ArrayRefWithPadding<RVec> posWithPadding[2];
+ ArrayRefWithPadding<RVec> forceWithPadding[2];
+ ArrayRef<RVec> pos[2];
+ ArrayRef<RVec> force[2];
for (i = 0; (i < 2); i++)
{
posWithPadding[i] = shfc->x[i].arrayRefWithPadding();
force[i] = forceWithPadding[i].paddedArrayRef();
}
- if (bDoNS && inputrec->ePBC != epbcNONE && !DOMAINDECOMP(cr))
+ ArrayRef<RVec> x = xPadded.unpaddedArrayRef();
+ ArrayRef<RVec> v = vPadded.unpaddedArrayRef();
+
+ if (bDoNS && inputrec->pbcType != PbcType::No && !DOMAINDECOMP(cr))
{
/* This is the only time where the coordinates are used
* before do_force is called, which normally puts all
* charge groups in the box.
*/
- auto xRef = x.paddedArrayRef();
- put_atoms_in_box_omp(fr->ePBC, box, xRef.subArray(0, md->homenr),
+ put_atoms_in_box_omp(fr->pbcType, box, x.subArray(0, md->homenr),
gmx_omp_nthreads_get(emntDefault));
-
- if (graph)
- {
- mk_mshift(fplog, graph, fr->ePBC, box, xRvec);
- }
- }
-
- /* After this all coordinate arrays will contain whole charge groups */
- if (graph)
- {
- shift_self(graph, box, xRvec);
}
if (nflexcon)
{
- if (nat > shfc->flex_nalloc)
- {
- shfc->flex_nalloc = over_alloc_dd(nat);
- srenew(shfc->acc_dir, shfc->flex_nalloc);
- srenew(shfc->x_old, shfc->flex_nalloc);
- }
- acc_dir = shfc->acc_dir;
- x_old = shfc->x_old;
- auto xArrayRef = x.paddedArrayRef();
- auto vArrayRef = v.paddedArrayRef();
+ shfc->acc_dir.resize(nat);
+ shfc->x_old.resizeWithPadding(nat);
+ ArrayRef<RVec> x_old = shfc->x_old.arrayRefWithPadding().unpaddedArrayRef();
for (i = 0; i < homenr; i++)
{
for (d = 0; d < DIM; d++)
{
- shfc->x_old[i][d] = xArrayRef[i][d] - vArrayRef[i][d] * inputrec->delta_t;
+ x_old[i][d] = x[i][d] - v[i][d] * inputrec->delta_t;
}
}
}
/* Do a prediction of the shell positions, when appropriate.
* Without velocities (EM, NM, BD) we only do initial prediction.
*/
- if (shfc->bPredict && !bCont && (EI_STATE_VELOCITY(inputrec->eI) || bInit))
- {
- predict_shells(fplog, xRvec, vRvec, inputrec->delta_t, nshell, shell, md->massT, nullptr, bInit);
- }
-
- /* do_force expected the charge groups to be in the box */
- if (graph)
+ if (shfc->predictShells && !bCont && (EI_STATE_VELOCITY(inputrec->eI) || bInit))
{
- unshift_self(graph, box, xRvec);
+ predict_shells(fplog, x, v, inputrec->delta_t, shells, md->massT, nullptr, bInit);
}
/* Calculate the forces first time around */
if (gmx_debug_at)
{
- pr_rvecs(debug, 0, "x b4 do_force", xRvec, homenr);
+ pr_rvecs(debug, 0, "x b4 do_force", as_rvec_array(x.data()), homenr);
}
int shellfc_flags = force_flags | (bVerbose ? GMX_FORCE_ENERGY : 0);
do_force(fplog, cr, ms, inputrec, nullptr, enforcedRotation, imdSession, pull_work, mdstep,
- nrnb, wcycle, top, box, x, hist, forceWithPadding[Min], force_vir, md, enerd, fcd,
- lambda, graph, fr, runScheduleWork, vsite, mu_tot, t, nullptr,
+ nrnb, wcycle, top, box, xPadded, hist, forceWithPadding[Min], force_vir, md, enerd,
+ fcd, lambda, fr, runScheduleWork, vsite, mu_tot, t, nullptr,
(bDoNS ? GMX_FORCE_NS : 0) | shellfc_flags, ddBalanceRegionHandler);
sf_dir = 0;
if (nflexcon)
{
- init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end, shfc->x_old, xRvec, xRvec,
- as_rvec_array(force[Min].data()), shfc->acc_dir, box, lambda, &dum);
+ init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end, shfc->x_old.arrayRefWithPadding(),
+ x, xPadded, force[Min], shfc->acc_dir, box, lambda, &dum);
for (i = 0; i < end; i++)
{
sum_epot(&(enerd->grpp), enerd->term);
Epot[Min] = enerd->term[F_EPOT];
- df[Min] = rms_force(cr, forceWithPadding[Min].paddedArrayRef(), nshell, shell, nflexcon,
- &sf_dir, &Epot[Min]);
+ df[Min] = rms_force(cr, forceWithPadding[Min].paddedArrayRef(), shells, nflexcon, &sf_dir, &Epot[Min]);
df[Try] = 0;
if (debug)
{
pr_rvecs(debug, 0, "force0", as_rvec_array(force[Min].data()), md->nr);
}
- if (nshell + nflexcon > 0)
+ if (!shells.empty() || nflexcon > 0)
{
/* Copy x to pos[Min] & pos[Try]: during minimization only the
* shell positions are updated, therefore the other particles must
* be set here, in advance.
*/
- std::copy(x.paddedArrayRef().begin(), x.paddedArrayRef().end(),
+ std::copy(xPadded.paddedArrayRef().begin(), xPadded.paddedArrayRef().end(),
posWithPadding[Min].paddedArrayRef().begin());
- std::copy(x.paddedArrayRef().begin(), x.paddedArrayRef().end(),
+ std::copy(xPadded.paddedArrayRef().begin(), xPadded.paddedArrayRef().end(),
posWithPadding[Try].paddedArrayRef().begin());
}
/* First check whether we should do shells, or whether the force is
* low enough even without minimization.
*/
- bConverged = (df[Min] < ftol);
+ bool bConverged = (df[Min] < ftol);
for (count = 1; (!(bConverged) && (count < number_steps)); count++)
{
if (vsite)
{
- construct_vsites(vsite, as_rvec_array(pos[Min].data()), inputrec->delta_t, vRvec,
- idef->iparams, idef->il, fr->ePBC, fr->bMolPBC, cr, box);
+ construct_vsites(vsite, as_rvec_array(pos[Min].data()), inputrec->delta_t,
+ as_rvec_array(v.data()), idef.iparams, idef.il, fr->pbcType,
+ fr->bMolPBC, cr, box);
}
if (nflexcon)
{
- init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end, x_old, xRvec,
- as_rvec_array(pos[Min].data()), as_rvec_array(force[Min].data()), acc_dir,
- box, lambda, &dum);
+ init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end,
+ shfc->x_old.arrayRefWithPadding(), x, posWithPadding[Min], force[Min],
+ shfc->acc_dir, box, lambda, &dum);
- directional_sd(pos[Min], pos[Try], acc_dir, end, fr->fc_stepsize);
+ directional_sd(pos[Min], pos[Try], shfc->acc_dir, end, fr->fc_stepsize);
}
/* New positions, Steepest descent */
- shell_pos_sd(pos[Min], pos[Try], force[Min], nshell, shell, count);
-
- /* do_force expected the charge groups to be in the box */
- if (graph)
- {
- unshift_self(graph, box, as_rvec_array(pos[Try].data()));
- }
+ shell_pos_sd(pos[Min], pos[Try], force[Min], shells, count);
if (gmx_debug_at)
{
/* Try the new positions */
do_force(fplog, cr, ms, inputrec, nullptr, enforcedRotation, imdSession, pull_work, 1, nrnb,
wcycle, top, box, posWithPadding[Try], hist, forceWithPadding[Try], force_vir, md,
- enerd, fcd, lambda, graph, fr, runScheduleWork, vsite, mu_tot, t, nullptr,
- shellfc_flags, ddBalanceRegionHandler);
+ enerd, fcd, lambda, fr, runScheduleWork, vsite, mu_tot, t, nullptr, shellfc_flags,
+ ddBalanceRegionHandler);
sum_epot(&(enerd->grpp), enerd->term);
if (gmx_debug_at)
{
sf_dir = 0;
if (nflexcon)
{
- init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end, x_old, xRvec,
- as_rvec_array(pos[Try].data()), as_rvec_array(force[Try].data()), acc_dir,
- box, lambda, &dum);
+ init_adir(shfc, constr, inputrec, cr, dd_ac1, mdstep, md, end,
+ shfc->x_old.arrayRefWithPadding(), x, posWithPadding[Try], force[Try],
+ shfc->acc_dir, box, lambda, &dum);
+ ArrayRef<const RVec> acc_dir = shfc->acc_dir;
for (i = 0; i < end; i++)
{
sf_dir += md->massT[i] * norm2(acc_dir[i]);
Epot[Try] = enerd->term[F_EPOT];
- df[Try] = rms_force(cr, force[Try], nshell, shell, nflexcon, &sf_dir, &Epot[Try]);
+ df[Try] = rms_force(cr, force[Try], shells, nflexcon, &sf_dir, &Epot[Try]);
if (debug)
{
if (gmx_debug_at)
{
fprintf(debug, "SHELL ITER %d\n", count);
- dump_shells(debug, force[Try], ftol, nshell, shell);
+ dump_shells(debug, force[Try], ftol, shells);
}
}
if (nflexcon)
{
/* Correct the velocities for the flexible constraints */
- invdt = 1 / inputrec->delta_t;
- auto vArrayRef = v.paddedArrayRef();
+ invdt = 1 / inputrec->delta_t;
for (i = 0; i < end; i++)
{
for (d = 0; d < DIM; d++)
{
- vArrayRef[i][d] += (pos[Try][i][d] - pos[Min][i][d]) * invdt;
+ v[i][d] += (pos[Try][i][d] - pos[Min][i][d]) * invdt;
}
}
}
}
else
{
- decrease_step_size(nshell, shell);
+ decrease_step_size(shells);
}
}
shfc->numForceEvaluations += count;
}
/* Copy back the coordinates and the forces */
- std::copy(pos[Min].begin(), pos[Min].end(), x.paddedArrayRef().data());
+ std::copy(pos[Min].begin(), pos[Min].end(), x.data());
std::copy(force[Min].begin(), force[Min].end(), f.unpaddedArrayRef().begin());
}
shfc->numForceEvaluations / numStepsAsDouble);
}
- // TODO Deallocate memory in shfc
+ delete shfc;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdio>
-#include "gromacs/math/arrayrefwithpadding.h"
#include "gromacs/mdlib/vsite.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/topology/atoms.h"
struct pull_t;
struct t_forcerec;
struct t_fcdata;
-struct t_graph;
struct t_inputrec;
class t_state;
namespace gmx
{
+template<typename>
+class ArrayRef;
+template<typename>
+class ArrayRefWithPadding;
class Constraints;
class ImdSession;
class MdrunScheduleWorkload;
} // namespace gmx
/* Initialization function, also predicts the initial shell postions.
+ * Returns a pointer to an initialized shellfc object.
*/
gmx_shellfc_t* init_shell_flexcon(FILE* fplog,
const gmx_mtop_t* mtop,
const t_mdatoms* md,
t_nrnb* nrnb,
gmx_wallcycle_t wcycle,
- t_graph* graph,
gmx_shellfc_t* shfc,
t_forcerec* fr,
gmx::MdrunScheduleWorkload* runScheduleWork,
const gmx_vsite_t* vsite,
const DDBalanceRegionHandler& ddBalanceRegionHandler);
-/* Print some final output */
+/* Print some final output and delete shellfc */
void done_shellfc(FILE* fplog, gmx_shellfc_t* shellfc, int64_t numSteps);
/*! \brief Count the different particle types in a system
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* other resources to create or configure the context. The simulation may in
* turn consume or borrow some resources from the context. This is a new
* framework that will evolve in the contexts of
- * https://redmine.gromacs.org/issues/2375
- * https://redmine.gromacs.org/issues/2587
+ * https://gitlab.com/gromacs/gromacs/-/issues/2375
+ * https://gitlab.com/gromacs/gromacs/-/issues/2587
*
* The public interface of SimulationContext is not yet well-specified.
* Client code can create an instance with gmx::createSimulationContext()
* Non-const accessors to shared resources need to be associated with update
* signals that the simulation components (modules and runner) can subscribe to.
*
- * Also reference https://redmine.gromacs.org/issues/2587
+ * Also reference https://gitlab.com/gromacs/gromacs/-/issues/2587
*/
class SimulationContext final
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019-2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* @return Unique pointer to a Simulator object
*/
template<typename... Args>
- std::unique_ptr<ISimulator> build(bool inputIsCompatibleWithModularSimulator, Args&&... args);
+ std::unique_ptr<ISimulator> build(bool useModularSimulator, Args&&... args);
};
//! Build a Simulator object
template<typename... Args>
-std::unique_ptr<ISimulator> SimulatorBuilder::build(bool inputIsCompatibleWithModularSimulator, Args&&... args)
+std::unique_ptr<ISimulator> SimulatorBuilder::build(bool useModularSimulator, Args&&... args)
{
- // GMX_DISABLE_MODULAR_SIMULATOR allows to disable modular simulator for all uses
- const auto disableModularSimulator = (getenv("GMX_DISABLE_MODULAR_SIMULATOR") != nullptr);
-
- if (!disableModularSimulator && inputIsCompatibleWithModularSimulator)
+ if (useModularSimulator)
{
// NOLINTNEXTLINE(modernize-make-unique): make_unique does not work with private constructor
return std::unique_ptr<ModularSimulator>(new ModularSimulator(std::forward<Args>(args)...));
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <ctime>
#include <algorithm>
-
#include <cfenv>
#include "gromacs/commandline/filenm.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/nbnxm/nbnxm.h"
{
GMX_RELEASE_ASSERT(gmx_omp_nthreads_get(emntDefault) == 1, "TPI does not support OpenMP");
- gmx_localtop_t top;
+ gmx_localtop_t top(top_global->ffparams);
PaddedHostVector<gmx::RVec> f{};
real lambda, t, temp, beta, drmax, epot;
double embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
GMX_UNUSED_VALUE(outputProvider);
+ if (EVDW_PME(inputrec->vdwtype))
+ {
+ gmx_fatal(FARGS, "Test particle insertion not implemented with LJ-PME");
+ }
+ if (haveEwaldSurfaceContribution(*inputrec))
+ {
+ gmx_fatal(FARGS,
+ "TPI with PME currently only works in a 3D geometry with tin-foil "
+ "boundary conditions");
+ }
+
GMX_LOG(mdlog.info)
.asParagraph()
.appendText(
gmx_mtop_generate_local_top(*top_global, &top, inputrec->efep != efepNO);
- SimulationGroups* groups = &top_global->groups;
+ const SimulationGroups* groups = &top_global->groups;
bCavity = (inputrec->eI == eiTPIC);
if (bCavity)
init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
state_global->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
/* We never need full pbc for TPI */
- fr->ePBC = epbcXYZ;
+ fr->pbcType = PbcType::Xyz;
/* Determine the temperature for the Boltzmann weighting */
temp = inputrec->opts.ref_t[0];
if (fplog)
bStateChanged = TRUE;
bNS = TRUE;
- put_atoms_in_box(fr->ePBC, box, x);
+ put_atoms_in_box(fr->pbcType, box, x);
/* Put all atoms except for the inserted ones on the grid */
rvec vzero = { 0, 0, 0 };
/* TODO: Avoid updating all atoms at every bNS step */
fr->nbv->setAtomProperties(*mdatoms, fr->cginfo);
- fr->nbv->constructPairlist(InteractionLocality::Local, &top.excls, step, nrnb);
+ fr->nbv->constructPairlist(InteractionLocality::Local, top.excls, step, nrnb);
bNS = FALSE;
}
clear_mat(vir);
clear_mat(pres);
- /* Calc energy (no forces) on new positions.
- * Since we only need the intermolecular energy
- * and the RF exclusion terms of the inserted molecule occur
- * within a single charge group we can pass NULL for the graph.
- * This also avoids shifts that would move charge groups
- * out of the box. */
+ /* Calc energy (no forces) on new positions. */
/* Make do_force do a single node force calculation */
cr->nnodes = 1;
do_force(fplog, cr, ms, inputrec, nullptr, nullptr, imdSession, pull_work, step, nrnb,
wcycle, &top, state_global->box, state_global->x.arrayRefWithPadding(),
&state_global->hist, f.arrayRefWithPadding(), force_vir, mdatoms, enerd, fcd,
- state_global->lambda, nullptr, fr, runScheduleWork, nullptr, mu_tot, t, nullptr,
+ state_global->lambda, fr, runScheduleWork, nullptr, mu_tot, t, nullptr,
GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY | (bStateChanged ? GMX_FORCE_STATECHANGED : 0),
DDBalanceRegionHandler(nullptr));
std::feclearexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
sprintf(str, "t%g_step%d.pdb", t, static_cast<int>(step));
sprintf(str2, "t: %f step %d ener: %f", t, static_cast<int>(step), epot);
write_sto_conf_mtop(str, str2, top_global, state_global->x.rvec_array(),
- state_global->v.rvec_array(), inputrec->ePBC, state_global->box);
+ state_global->v.rvec_array(), inputrec->pbcType, state_global->box);
}
step++;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
+#include <cerrno>
#include <cstring>
#include <fcntl.h>
#include <algorithm>
#include <exception>
#include <functional>
+#include <optional>
#include <tuple>
#include "gromacs/commandline/filenm.h"
-#include "gromacs/compat/optional.h"
#include "gromacs/fileio/checkpoint.h"
#include "gromacs/fileio/gmxfio.h"
#include "gromacs/mdrunutility/multisim.h"
* (relevant only when restarting)
*
* Does not throw */
- compat::optional<int> makeIndexOfNextPart(AppendingBehavior appendingBehavior) const;
+ std::optional<int> makeIndexOfNextPart(AppendingBehavior appendingBehavior) const;
//! Describes how mdrun will (re)start
StartingBehavior startingBehavior = StartingBehavior::NewSimulation;
//! When restarting from a checkpoint, contains the contents of its header
- compat::optional<CheckpointHeaderContents> headerContents;
+ std::optional<CheckpointHeaderContents> headerContents;
//! When restarting from a checkpoint, contains the names of expected output files
- compat::optional<std::vector<gmx_file_position_t>> outputFiles;
+ std::optional<std::vector<gmx_file_position_t>> outputFiles;
};
/*! \brief Choose the starting behaviour for this simulation
}
}
-compat::optional<int> StartingBehaviorHandler::makeIndexOfNextPart(const AppendingBehavior appendingBehavior) const
+std::optional<int> StartingBehaviorHandler::makeIndexOfNextPart(const AppendingBehavior appendingBehavior) const
{
- compat::optional<int> indexOfNextPart;
+ std::optional<int> indexOfNextPart;
if (startingBehavior == StartingBehavior::RestartWithoutAppending)
{
handler.ensureMultiSimBehaviorsMatch(ms);
// When not appending, prepare a suffix for the part number
- compat::optional<int> indexOfNextPart = handler.makeIndexOfNextPart(appendingBehavior);
+ std::optional<int> indexOfNextPart = handler.makeIndexOfNextPart(appendingBehavior);
// If a part suffix is used, change the file names accordingly.
if (indexOfNextPart)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016,2017,2019, by the GROMACS development team, led by
+# Copyright (c) 2016,2017,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
threadaffinitytest.cpp)
gmx_add_unit_test(MdrunUtilityUnitTests mdrunutility-test
- threadaffinity.cpp)
+ CPP_SOURCE_FILES
+ threadaffinity.cpp
+ )
target_link_libraries(mdrunutility-test PRIVATE mdrunutility-test-shared)
gmx_add_mpi_unit_test(MdrunUtilityMpiUnitTests mdrunutility-mpi-test 4
- threadaffinity_mpi.cpp)
+ CPP_SOURCE_FILES
+ threadaffinity_mpi.cpp
+ )
# TODO This target does not exist in a non-MPI build. It would be preferable
# to change functions like gmx_add_mpi_unit_test to add link-time dependencies
# as well as source files.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class ThreadAffinityHeterogeneousNodesTest : public ::testing::Test
{
public:
- int currentNode() const { return gmx_node_rank() / 2; }
- int indexInNode() const { return gmx_node_rank() % 2; }
- bool isMaster() const { return gmx_node_rank() == 0; }
+ static int currentNode() { return gmx_node_rank() / 2; }
+ static int indexInNode() { return gmx_node_rank() % 2; }
+ static bool isMaster() { return gmx_node_rank() == 0; }
- void setupNodes(ThreadAffinityTestHelper* helper, std::array<int, 2> cores)
+ static void setupNodes(ThreadAffinityTestHelper* helper, std::array<int, 2> cores)
{
const int node = currentNode();
helper->setPhysicalNodeId(node);
helper->setLogicalProcessorCount(cores[node]);
}
- void expectNodeAffinitySet(ThreadAffinityTestHelper* helper, int node, int core)
+ static void expectNodeAffinitySet(ThreadAffinityTestHelper* helper, int node, int core)
{
if (currentNode() == node)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
expectAffinitySet(core);
}
}
+ // NOLINTNEXTLINE readability-convert-member-functions-to-static
void expectAffinitySetThatFails(int core)
{
using ::testing::Return;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return basicMdspan.data() + basicMdspan.mapping().required_span_size();
}
+//! Convenience type for often-used two dimensional extents
+using dynamicExtents2D = extents<dynamic_extent, dynamic_extent>;
+
//! Convenience type for often-used three dimensional extents
using dynamicExtents3D = extents<dynamic_extent, dynamic_extent, dynamic_extent>;
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(MDSpanTests mdspan-test
- accessor_policy.cpp
- extents.cpp
- extensions.cpp
- layouts.cpp
- mdspan.cpp
- )
+ CPP_SOURCE_FILES
+ accessor_policy.cpp
+ extents.cpp
+ extensions.cpp
+ layouts.cpp
+ mdspan.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define DUTY_PP (1U << 0U)
#define DUTY_PME (1U << 1U)
+//! Whether the current DD role is master or slave
+enum class DDRole
+{
+ Master,
+ Agent
+};
+
+//! Whether one or more ranks are used
+enum class NumRanks
+{
+ Single,
+ Multiple
+};
+
typedef struct
{
int bUse;
* This is true if havePPDomainDecomposition is true, but the converse does not
* apply (see docs of havePpDomainDecomposition()).
*
- * \todo As part of Redmine #2395, replace calls to this with
+ * \todo As part of Issue #2395, replace calls to this with
* havePPDomainDecomposition or a call of some other/new function, as
* appropriate to each case. Then eliminate this macro. */
#define DOMAINDECOMP(cr) (((cr)->dd != nullptr) && PAR(cr))
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int fep_state = 0; /*current fep state -- just for printing */
std::vector<double> enerpart_lambda; /* Partial Hamiltonian for lambda and flambda[], includes at least all perturbed terms */
+ std::vector<double> dhdlLambda; /* dHdL at all neighboring lambda points (the current lambda point also at index 0). */
real foreign_term[F_NRE] = { 0 }; /* alternate array for storing foreign lambda energies */
struct gmx_grppairener_t foreign_grpp; /* alternate array for storing foreign lambda energies */
};
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
/* Abstract type for PME that is defined only in the routine that use them. */
-struct gmx_ns_t;
struct gmx_pme_t;
struct nonbonded_verlet_t;
struct bonded_threading_t;
+class DeviceContext;
class DispersionCorrection;
struct t_forcetable;
struct t_QMMMrec;
namespace gmx
{
+class DeviceStreamManager;
class GpuBonded;
class ForceProviders;
class StatePropagatorDataGpu;
class PmePpCommGpu;
+class WholeMoleculeTransform;
} // namespace gmx
/* macros for the cginfo data in forcerec
struct cginfo_mb_t
{
- int cg_start;
- int cg_end;
- int cg_mod;
- int* cginfo;
+ int cg_start = 0;
+ int cg_end = 0;
+ int cg_mod = 0;
+ std::vector<int> cginfo;
};
struct interaction_const_t* ic = nullptr;
/* PBC stuff */
- int ePBC = 0;
+ PbcType pbcType = PbcType::Xyz;
//! Tells whether atoms inside a molecule can be in different periodic images,
// i.e. whether we need to take into account PBC when computing distances inside molecules.
// This determines whether PBC must be considered for e.g. bonded interactions.
*/
real rlist = 0;
- /* Charge sum and dipole for topology A/B ([0]/[1]) for Ewald corrections */
- double qsum[2] = { 0 };
- double q2sum[2] = { 0 };
- double c6sum[2] = { 0 };
- rvec mu_tot[2] = { { 0 } };
+ /* Charge sum for topology A/B ([0]/[1]) for Ewald corrections */
+ double qsum[2] = { 0 };
+ double q2sum[2] = { 0 };
+ double c6sum[2] = { 0 };
/* Dispersion correction stuff */
std::unique_ptr<DispersionCorrection> dispersionCorrection;
real sc_sigma6_min = 0;
/* Information about atom properties for the molecule blocks in the system */
- struct cginfo_mb_t* cginfo_mb = nullptr;
+ std::vector<cginfo_mb_t> cginfo_mb;
/* Information about atom properties for local and non-local atoms */
std::vector<int> cginfo;
rvec* shift_vec = nullptr;
+ std::unique_ptr<gmx::WholeMoleculeTransform> wholeMoleculeTransform;
+
int cutoff_scheme = 0; /* group- or Verlet-style cutoff */
gmx_bool bNonbonded = FALSE; /* true if nonbonded calculations are *not* turned off */
/* The number of atoms participating in do_force_lowlevel */
int natoms_force = 0;
- /* The number of atoms participating in force and constraints */
+ /* The number of atoms participating in force calculation and constraints */
int natoms_force_constr = 0;
- /* The allocation size of vectors of size natoms_force */
- int nalloc_force = 0;
-
/* Forces that should not enter into the coord x force virial summation:
* PPPM/PME/Ewald/posres/ForceProviders
*/
std::vector<gmx::RVec> shiftForces;
/* Non bonded Parameter lists */
- int ntype = 0; /* Number of atom types */
- gmx_bool bBHAM = FALSE;
- real* nbfp = nullptr;
- real* ljpme_c6grid = nullptr; /* C6-values used on grid in LJPME */
+ int ntype = 0; /* Number of atom types */
+ gmx_bool bBHAM = FALSE;
+ std::vector<real> nbfp;
+ real* ljpme_c6grid = nullptr; /* C6-values used on grid in LJPME */
/* Energy group pair flags */
int* egp_flags = nullptr;
*/
int n_tpi = 0;
- /* QMMM stuff */
- gmx_bool bQMMM = FALSE;
- struct t_QMMMrec* qr = nullptr;
-
- /* QM-MM neighborlists */
- struct t_nblist* QMMMlist = nullptr;
-
/* Limit for printing large forces, negative is don't print */
real print_force = 0;
// TODO: This is not supposed to be here. StatePropagatorDataGpu should be a part of
// general StatePropagatorData object that is passed around
gmx::StatePropagatorDataGpu* stateGpu = nullptr;
+ // TODO: Should not be here. This is here only to pass the pointer around.
+ gmx::DeviceStreamManager* deviceStreamManager = nullptr;
+
+ //! GPU device context
+ DeviceContext* deviceContext = nullptr;
/* For PME-PP GPU communication */
std::unique_ptr<gmx::PmePpCommGpu> pmePpCommGpu;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class ForceProviders;
class IMDOutputProvider;
class IMdpOptionProvider;
+struct MdModulesNotifier;
/*! \libinternal \brief
* Extension module for \Gromacs simulations.
virtual IMDOutputProvider* outputProvider() = 0;
//! Initializes force providers from this module.
virtual void initForceProviders(ForceProviders* forceProviders) = 0;
+ //! Subscribe to simulation setup notifications
+ virtual void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) = 0;
+ //! Subscribe to pre processing notifications
+ virtual void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) = 0;
};
} // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2010, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx_bool ir_coulomb_switched(const t_inputrec* ir)
{
- return (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT || ir->coulombtype == eelENCADSHIFT
+ return (ir->coulombtype == eelSWITCH || ir->coulombtype == eelSHIFT
|| ir->coulombtype == eelPMESWITCH || ir->coulombtype == eelPMEUSERSWITCH
|| ir->coulomb_modifier == eintmodPOTSWITCH || ir->coulomb_modifier == eintmodFORCESWITCH);
}
gmx_bool ir_vdw_switched(const t_inputrec* ir)
{
- return (ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT || ir->vdwtype == evdwENCADSHIFT
+ return (ir->vdwtype == evdwSWITCH || ir->vdwtype == evdwSHIFT
|| ir->vdw_modifier == eintmodPOTSWITCH || ir->vdw_modifier == eintmodFORCESWITCH);
}
sfree(ir->opts.tau_t);
sfree(ir->opts.acc);
sfree(ir->opts.nFreeze);
- sfree(ir->opts.QMmethod);
- sfree(ir->opts.QMbasis);
- sfree(ir->opts.QMcharge);
- sfree(ir->opts.QMmult);
- sfree(ir->opts.bSH);
- sfree(ir->opts.CASorbitals);
- sfree(ir->opts.CASelectrons);
- sfree(ir->opts.SAon);
- sfree(ir->opts.SAoff);
- sfree(ir->opts.SAsteps);
sfree(ir->opts.egp_flags);
done_lambdas(ir->fepvals);
sfree(ir->fepvals);
delete ir->params;
}
-static void pr_qm_opts(FILE* fp, int indent, const char* title, const t_grpopts* opts)
-{
- fprintf(fp, "%s:\n", title);
-
- pr_int(fp, indent, "ngQM", opts->ngQM);
- if (opts->ngQM > 0)
- {
- pr_ivec(fp, indent, "QMmethod", opts->QMmethod, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "QMbasis", opts->QMbasis, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "QMcharge", opts->QMcharge, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "QMmult", opts->QMmult, opts->ngQM, FALSE);
- pr_bvec(fp, indent, "SH", opts->bSH, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "CASorbitals", opts->CASorbitals, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "CASelectrons", opts->CASelectrons, opts->ngQM, FALSE);
- pr_rvec(fp, indent, "SAon", opts->SAon, opts->ngQM, FALSE);
- pr_rvec(fp, indent, "SAoff", opts->SAoff, opts->ngQM, FALSE);
- pr_ivec(fp, indent, "SAsteps", opts->SAsteps, opts->ngQM, FALSE);
- }
-}
-
static void pr_grp_opts(FILE* out, int indent, const char* title, const t_grpopts* opts, gmx_bool bMDPformat)
{
int i, m, j;
PR("period", awhDimParams->period);
PR("force-constant", awhDimParams->forceConstant);
PR("diffusion", awhDimParams->diffusion);
- PR("start", awhDimParams->origin);
- PR("end", awhDimParams->end);
PR("cover-diameter", awhDimParams->coverDiameter);
}
/* Neighborsearching parameters */
PS("cutoff-scheme", ECUTSCHEME(ir->cutoff_scheme));
PI("nstlist", ir->nstlist);
- PS("pbc", epbc_names[ir->ePBC]);
+ PS("pbc", c_pbcTypeNames[ir->pbcType].c_str());
PS("periodic-molecules", EBOOL(ir->bPeriodicMols));
PR("verlet-buffer-tolerance", ir->verletbuf_tol);
PR("rlist", ir->rlist);
/* QMMM */
PS("QMMM", EBOOL(ir->bQMMM));
- PI("QMconstraints", ir->QMconstraints);
- PI("QMMMscheme", ir->QMMMscheme);
- PR("MMChargeScaleFactor", ir->scalefactor);
- pr_qm_opts(fp, indent, "qm-opts", &(ir->opts));
+ fprintf(fp, "%s:\n", "qm-opts");
+ pr_int(fp, indent, "ngQM", ir->opts.ngQM);
/* CONSTRAINT OPTIONS */
PS("constraint-algorithm", ECONSTRTYPE(ir->eConstrAlg));
cmp_int64(fp, "inputrec->nsteps", ir1->nsteps, ir2->nsteps);
cmp_int64(fp, "inputrec->init_step", ir1->init_step, ir2->init_step);
cmp_int(fp, "inputrec->simulation_part", -1, ir1->simulation_part, ir2->simulation_part);
- cmp_int(fp, "inputrec->ePBC", -1, ir1->ePBC, ir2->ePBC);
+ cmp_int(fp, "inputrec->pbcType", -1, static_cast<int>(ir1->pbcType), static_cast<int>(ir2->pbcType));
cmp_bool(fp, "inputrec->bPeriodicMols", -1, ir1->bPeriodicMols, ir2->bPeriodicMols);
cmp_int(fp, "inputrec->cutoff_scheme", -1, ir1->cutoff_scheme, ir2->cutoff_scheme);
cmp_int(fp, "inputrec->nstlist", -1, ir1->nstlist, ir2->nstlist);
bool inputrecPbcXY2Walls(const t_inputrec* ir)
{
- return (ir->ePBC == epbcXY && ir->nwall == 2);
+ return (ir->pbcType == PbcType::XY && ir->nwall == 2);
}
bool integratorHasConservedEnergyQuantity(const t_inputrec* ir)
{
if (!EI_MD(ir->eI))
- {
+ { // NOLINT bugprone-branch-clone
// Energy minimization or stochastic integrator: no conservation
return false;
}
}
else
{
- return ePBC2npbcdim(ir->ePBC);
+ return numPbcDimensions(ir->pbcType);
}
}
{
int n = 0;
- switch (ir->ePBC)
+ switch (ir->pbcType)
{
- case epbcXYZ:
- case epbcNONE: n = 3; break;
- case epbcXY: n = (ir->nwall == 0 ? 3 : 2); break;
- case epbcSCREW: n = 1; break;
+ case PbcType::Xyz:
+ case PbcType::No: n = 3; break;
+ case PbcType::XY: n = (ir->nwall == 0 ? 3 : 2); break;
+ case PbcType::Screw: n = 1; break;
default: gmx_incons("Unknown pbc in calc_nrdf");
}
{
return EEL_PME_EWALD(ir.coulombtype) && (ir.ewald_geometry == eewg3DC || ir.epsilon_surface != 0);
}
+
+bool haveFreeEnergyType(const t_inputrec& ir, const int fepType)
+{
+ for (int i = 0; i < ir.fepvals->n_lambda; i++)
+ {
+ if (ir.fepvals->all_lambda[fepType][i] > 0)
+ {
+ return true;
+ }
+ }
+ return false;
+}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class KeyValueTreeObject;
} // namespace gmx
+enum class PbcType;
+
struct t_grpopts
{
//! Number of T-Coupl groups
/* QMMM stuff */
//! Number of QM groups
int ngQM;
- //! Level of theory in the QM calculation
- int* QMmethod;
- //! Basisset in the QM calculation
- int* QMbasis;
- //! Total charge in the QM region
- int* QMcharge;
- //! Spin multiplicicty in the QM region
- int* QMmult;
- //! Surface hopping (diabatic hop only)
- gmx_bool* bSH;
- //! Number of orbiatls in the active space
- int* CASorbitals;
- //! Number of electrons in the active space
- int* CASelectrons;
- //! At which gap (A.U.) the SA is switched on
- real* SAon;
- //! At which gap (A.U.) the SA is switched off
- real* SAoff;
- //! In how many steps SA goes from 1-1 to 0.5-0.5
- int* SAsteps;
};
struct t_simtemp
//! Type of combination rule in LJ-PME
int ljpme_combination_rule;
//! Type of periodic boundary conditions
- int ePBC;
+ PbcType pbcType;
//! Periodic molecules
bool bPeriodicMols;
//! Continuation run: starting state is correct (ie. constrained)
t_grpopts opts;
//! QM/MM calculation
gmx_bool bQMMM;
- //! Constraints on QM bonds
- int QMconstraints;
- //! Scheme: ONIOM or normal
- int QMMMscheme;
- //! Factor for scaling the MM charges in QM calc.
- real scalefactor;
/* Fields for removed features go here (better caching) */
//! Whether AdResS is enabled - always false if a valid .tpr was read
bool inputrecPbcXY2Walls(const t_inputrec* ir);
/*! \brief Returns true for MD integator with T and/or P-coupling that supports
- * calculating the conserved energy quantity.
+ * calculating a conserved energy quantity.
+ *
+ * Note that dynamical integrators without T and P coupling (ie NVE)
+ * return false, i.e. the return value refers to whether there
+ * is a conserved quantity different than the total energy.
*/
bool integratorHasConservedEnergyQuantity(const t_inputrec* ir);
*/
bool haveEwaldSurfaceContribution(const t_inputrec& ir);
+/*! \brief Check if calculation of the specific FEP type was requested.
+ *
+ * \param[in] ir Input record.
+ * \param[in] fepType Free-energy perturbation type to check for.
+ *
+ * \returns If the \p fepType is perturbed in this run.
+ */
+bool haveFreeEnergyType(const t_inputrec& ir, int fepType);
+
#endif /* GMX_MDTYPES_INPUTREC_H */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
"Shift",
"User",
"Generalized-Born (unused)",
- "Reaction-Field-nec",
- "Encad-shift",
+ "Reaction-Field-nec (unsupported)",
+ "Encad-shift (unused)",
"PME-User",
"PME-Switch",
"PME-User-Switch",
const char* eljpme_names[eljpmeNR + 1] = { "Geometric", "Lorentz-Berthelot", nullptr };
-const char* evdw_names[evdwNR + 1] = { "Cut-off", "Switch", "Shift", "User",
- "Encad-shift", "PME", nullptr };
+const char* evdw_names[evdwNR + 1] = { "Cut-off", "Switch", "Shift", "User", "Encad-shift (unused)",
+ "PME", nullptr };
const char* econstr_names[econtNR + 1] = { "Lincs", "Shake", nullptr };
const char* eSwapFixedGrp_names[eSwapFixedGrpNR + 1] = { "Split0", "Split1", "Solvent", nullptr };
-
-const char* eQMmethod_names[eQMmethodNR + 1] = { "AM1", "PM3", "RHF", "UHF",
- "DFT", "B3LYP", "MP2", "CASSCF",
- "B3LYPLAN", "DIRECT", nullptr };
-
-const char* eQMbasis_names[eQMbasisNR + 1] = { "STO3G", "STO-3G", "3-21G", "3-21G*",
- "3-21+G*", "6-21G", "6-31G", "6-31G*",
- "6-31+G*", "6-311G", nullptr };
-
-const char* eQMMMscheme_names[eQMMMschemeNR + 1] = { "normal", "ONIOM", nullptr };
-
const char* gmx_nblist_geometry_names[GMX_NBLIST_GEOMETRY_NR + 1] = {
"Particle-Particle", "Water3-Particle", "Water3-Water3", "Water4-Particle",
"Water4-Water4", "CG-CG", nullptr
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
eelUSER,
eelGB_NOTUSED,
eelRF_NEC_UNSUPPORTED,
- eelENCADSHIFT,
+ eelENCADSHIFT_NOTUSED,
eelPMEUSER,
eelPMESWITCH,
eelPMEUSERSWITCH,
evdwSWITCH,
evdwSHIFT,
evdwUSER,
- evdwENCADSHIFT,
+ evdwENCADSHIFT_UNUSED,
evdwPME,
evdwNR
};
//! String for swap group splitting
extern const char* eSwapFixedGrp_names[eSwapFixedGrpNR + 1];
-//! QMMM methods.
-enum
-{
- eQMmethodAM1,
- eQMmethodPM3,
- eQMmethodRHF,
- eQMmethodUHF,
- eQMmethodDFT,
- eQMmethodB3LYP,
- eQMmethodMP2,
- eQMmethodCASSCF,
- eQMmethodB3LYPLAN,
- eQMmethodDIRECT,
- eQMmethodNR
-};
-//! String corresponding to QMMM methods
-extern const char* eQMmethod_names[eQMmethodNR + 1];
-//! Macro to pick QMMM method name
-#define EQMMETHOD(e) enum_name(e, eQMmethodNR, eQMmethod_names)
-
-//! QMMM basis function for QM part
-enum
-{
- eQMbasisSTO3G,
- eQMbasisSTO3G2,
- eQMbasis321G,
- eQMbasis321Gp,
- eQMbasis321dGp,
- eQMbasis621G,
- eQMbasis631G,
- eQMbasis631Gp,
- eQMbasis631dGp,
- eQMbasis6311G,
- eQMbasisNR
-};
-//! Name for QMMM basis function
-extern const char* eQMbasis_names[eQMbasisNR + 1];
-//! Macro to pick right basis function string
-#define EQMBASIS(e) enum_name(e, eQMbasisNR, eQMbasis_names)
-
-//! QMMM scheme
-enum
-{
- eQMMMschemenormal,
- eQMMMschemeoniom,
- eQMMMschemeNR
-};
-//! QMMMM scheme names
-extern const char* eQMMMscheme_names[eQMMMschemeNR + 1];
-//! Macro to pick QMMMM scheme name
-#define EQMMMSCHEME(e) enum_name(e, eQMMMschemeNR, eQMMMscheme_names)
-
/*! \brief Neighborlist geometry type.
*
* Kernels will compute interactions between two particles,
//! String corresponding to interactions in neighborlist code
extern const char* gmx_nblist_interaction_names[GMX_NBLIST_INTERACTION_NR + 1];
-
-//! \brief QM/MM mode
-enum struct GmxQmmmMode
-{
- GMX_QMMM_ORIGINAL,
- GMX_QMMM_MIMIC
-};
#endif /* GMX_MDTYPES_MD_ENUMS_H */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
unsigned short* cU2;
//! Group index for orientation restraints
unsigned short* cORF;
- //! QMMM atoms
- gmx_bool* bQM;
//! Number of atoms on this processor. TODO is this still used?
int homenr;
//! The lambda value used to create the contents of the struct
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class SimulationWorkload
{
public:
+ //! Whether total dipole needs to be computed
+ bool computeMuTot = false;
//! If we have calculation of short range nonbondeds on CPU
bool useCpuNonbonded = false;
//! If we have calculation of short range nonbondeds on GPU
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void set_box_rel(const t_inputrec* ir, t_state* state)
{
/* Make sure the box obeys the restrictions before we fix the ratios */
- correct_box(nullptr, 0, state->box, nullptr);
+ correct_box(nullptr, 0, state->box);
clear_mat(state->box_rel);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "locality.h"
+class DeviceContext;
+class DeviceStream;
class GpuEventSynchronizer;
struct gmx_wallcycle;
namespace gmx
{
+class DeviceStreamManager;
class StatePropagatorDataGpu
{
* ops are offloaded. This feature is currently not available in OpenCL and
* hence these streams are not set in these builds.
*
- * \note In CUDA, the update stream is created in the constructor as a temporary
- * solution, in place until the stream manager is introduced.
- * Note that this makes it impossible to construct this object in CUDA
- * builds executing on a host without any CUDA-capable device available.
- *
- * \note In CUDA, \p deviceContext is unused, hence always nullptr;
- * all stream arguments can also be nullptr in runs where the
- * respective streams are not required.
- * In OpenCL, \p deviceContext needs to be a valid device context.
- * In OpenCL runs StatePropagatorDataGpu is currently only used
- * with PME offload, and only on ranks with PME duty. Hence, the
- * \p pmeStream argument needs to be a valid OpenCL queue object
- * which must have been created in \p deviceContext.
- *
- * \todo Make a \p CommandStream visible in the CPU parts of the code so we
- * will not have to pass a void*.
- * \todo Make a \p DeviceContext object visible in CPU parts of the code so we
- * will not have to pass a void*.
- *
- * \param[in] pmeStream Device PME stream, nullptr allowed.
- * \param[in] localStream Device NBNXM local stream, nullptr allowed.
- * \param[in] nonLocalStream Device NBNXM non-local stream, nullptr allowed.
- * \param[in] deviceContext Device context, nullptr allowed.
- * \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
- * \param[in] paddingSize Padding size for coordinates buffer.
- * \param[in] wcycle Wall cycle counter data.
+ * \param[in] deviceStreamManager Object that owns the DeviceContext and DeviceStreams.
+ * \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
+ * \param[in] allocationBlockSizeDivisor Deterines padding size for coordinates buffer.
+ * \param[in] wcycle Wall cycle counter data.
*/
- StatePropagatorDataGpu(const void* pmeStream,
- const void* localStream,
- const void* nonLocalStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle);
+ StatePropagatorDataGpu(const DeviceStreamManager& deviceStreamManager,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle);
/*! \brief Constructor to use in PME-only rank and in tests.
*
* \param[in] pmeStream Device PME stream, nullptr is not allowed.
* \param[in] deviceContext Device context, nullptr allowed for non-OpenCL builds.
* \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
- * \param[in] paddingSize Padding size for coordinates buffer.
+ * \param[in] allocationBlockSizeDivisor Determines padding size for coordinates buffer.
* \param[in] wcycle Wall cycle counter data.
*/
- StatePropagatorDataGpu(const void* pmeStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle);
+ StatePropagatorDataGpu(const DeviceStream* pmeStream,
+ const DeviceContext& deviceContext,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle);
//! Move constructor
StatePropagatorDataGpu(StatePropagatorDataGpu&& other) noexcept;
*
* \returns GPU positions buffer.
*/
- DeviceBuffer<float> getCoordinates();
+ DeviceBuffer<RVec> getCoordinates();
/*! \brief Copy positions to the GPU memory.
*
*
* \returns GPU velocities buffer.
*/
- DeviceBuffer<float> getVelocities();
+ DeviceBuffer<RVec> getVelocities();
/*! \brief Copy velocities to the GPU memory.
*
*
* \returns GPU force buffer.
*/
- DeviceBuffer<float> getForces();
+ DeviceBuffer<RVec> getForces();
/*! \brief Copy forces to the GPU memory.
*
*
* \returns The device command stream to use in update-constraints.
*/
- void* getUpdateStream();
+ const DeviceStream* getUpdateStream();
/*! \brief Getter for the number of local atoms.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
};
-StatePropagatorDataGpu::StatePropagatorDataGpu(const void* /* pmeStream */,
- const void* /* localStream */,
- const void* /* nonLocalStream */,
- const void* /* deviceContext */,
+StatePropagatorDataGpu::StatePropagatorDataGpu(const DeviceStreamManager& /* deviceStreamManager */,
GpuApiCallBehavior /* transferKind */,
- int /* paddingSize */,
+ int /* allocationBlockSizeDivisor */,
gmx_wallcycle* /* wcycle */) :
impl_(nullptr)
{
}
-StatePropagatorDataGpu::StatePropagatorDataGpu(const void* /* pmeStream */,
- const void* /* deviceContext */,
+StatePropagatorDataGpu::StatePropagatorDataGpu(const DeviceStream* /* pmeStream */,
+ const DeviceContext& /* deviceContext */,
GpuApiCallBehavior /* transferKind */,
- int /* paddingSize */,
+ int /* allocationBlockSizeDivisor */,
gmx_wallcycle* /* wcycle */) :
impl_(nullptr)
{
void StatePropagatorDataGpu::reinit(int /* numAtomsLocal */, int /* numAtomsAll */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
std::tuple<int, int> StatePropagatorDataGpu::getAtomRangesFromAtomLocality(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return std::make_tuple(0, 0);
}
-DeviceBuffer<float> StatePropagatorDataGpu::getCoordinates()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getCoordinates()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
- return DeviceBuffer<float>{};
+ return {};
}
GpuEventSynchronizer* StatePropagatorDataGpu::getCoordinatesReadyOnDeviceEvent(
const SimulationWorkload& /* simulationWork */,
const StepWorkload& /* stepWork */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
void StatePropagatorDataGpu::waitCoordinatesCopiedToDevice(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
GpuEventSynchronizer* StatePropagatorDataGpu::xUpdatedOnDevice()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
void StatePropagatorDataGpu::copyCoordinatesToGpu(const gmx::ArrayRef<const gmx::RVec> /* h_x */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
void StatePropagatorDataGpu::waitCoordinatesReadyOnHost(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
void StatePropagatorDataGpu::copyCoordinatesFromGpu(gmx::ArrayRef<gmx::RVec> /* h_x */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
-DeviceBuffer<float> StatePropagatorDataGpu::getVelocities()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getVelocities()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
- return DeviceBuffer<float>{};
+ return {};
}
void StatePropagatorDataGpu::copyVelocitiesToGpu(const gmx::ArrayRef<const gmx::RVec> /* h_v */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
GpuEventSynchronizer* StatePropagatorDataGpu::getVelocitiesReadyOnDeviceEvent(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
void StatePropagatorDataGpu::copyVelocitiesFromGpu(gmx::ArrayRef<gmx::RVec> /* h_v */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
void StatePropagatorDataGpu::waitVelocitiesReadyOnHost(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
-DeviceBuffer<float> StatePropagatorDataGpu::getForces()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getForces()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
- return DeviceBuffer<float>{};
+ return {};
}
void StatePropagatorDataGpu::copyForcesToGpu(const gmx::ArrayRef<const gmx::RVec> /* h_f */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
GpuEventSynchronizer* StatePropagatorDataGpu::getForcesReadyOnDeviceEvent(AtomLocality /* atomLocality */,
bool /* useGpuFBufferOps */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
GpuEventSynchronizer* StatePropagatorDataGpu::fReducedOnDevice()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
void StatePropagatorDataGpu::copyForcesFromGpu(gmx::ArrayRef<gmx::RVec> /* h_f */,
AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
void StatePropagatorDataGpu::waitForcesReadyOnHost(AtomLocality /* atomLocality */)
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
}
-void* StatePropagatorDataGpu::getUpdateStream()
+const DeviceStream* StatePropagatorDataGpu::getUpdateStream()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return nullptr;
int StatePropagatorDataGpu::numAtomsLocal()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return 0;
int StatePropagatorDataGpu::numAtomsAll()
{
- GMX_ASSERT(false,
+ GMX_ASSERT(!impl_,
"A CPU stub method from GPU state propagator data was called instead of one from "
"GPU implementation.");
return 0;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* ops are offloaded. This feature is currently not available in OpenCL and
* hence these streams are not set in these builds.
*
- * \note In CUDA, the update stream is created in the constructor as a temporary
- * solution, in place until the stream manager is introduced.
- * Note that this makes it impossible to construct this object in CUDA
- * builds executing on a host without any CUDA-capable device available.
- *
- * \note In CUDA, \p deviceContext is unused, hence always nullptr;
- * all stream arguments can also be nullptr in runs where the
- * respective streams are not required.
- * In OpenCL, \p deviceContext needs to be a valid device context.
- * In OpenCL runs StatePropagatorDataGpu is currently only used
- * with PME offload, and only on ranks with PME duty. Hence, the
- * \p pmeStream argument needs to be a valid OpenCL queue object
- * which must have been created in \p deviceContext.
- *
- * \todo Make a \p CommandStream visible in the CPU parts of the code so we
- * will not have to pass a void*.
- * \todo Make a \p DeviceContext object visible in CPU parts of the code so we
- * will not have to pass a void*.
- *
- * \param[in] pmeStream Device PME stream, nullptr allowed.
- * \param[in] localStream Device NBNXM local stream, nullptr allowed.
- * \param[in] nonLocalStream Device NBNXM non-local stream, nullptr allowed.
- * \param[in] deviceContext Device context, nullptr allowed.
- * \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
- * \param[in] paddingSize Padding size for coordinates buffer.
- * \param[in] wcycle Wall cycle counter data.
+ * \param[in] deviceStreamManager Object that owns the DeviceContext and DeviceStreams.
+ * \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
+ * \param[in] allocationBlockSizeDivisor Determines the padding size for coordinates buffer.
+ * \param[in] wcycle Wall cycle counter data.
*/
- Impl(const void* pmeStream,
- const void* localStream,
- const void* nonLocalStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle);
+ Impl(const DeviceStreamManager& deviceStreamManager,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle);
/*! \brief Constructor to use in PME-only rank and in tests.
*
* \param[in] pmeStream Device PME stream, nullptr is not allowed.
* \param[in] deviceContext Device context, nullptr allowed for non-OpenCL builds.
* \param[in] transferKind H2D/D2H transfer call behavior (synchronous or not).
- * \param[in] paddingSize Padding size for coordinates buffer.
+ * \param[in] allocationBlockSizeDivisor Determines the padding size for coordinates buffer.
* \param[in] wcycle Wall cycle counter data.
*/
- Impl(const void* pmeStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle);
+ Impl(const DeviceStream* pmeStream,
+ const DeviceContext& deviceContext,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle);
~Impl();
*
* \returns GPU positions buffer.
*/
- DeviceBuffer<float> getCoordinates();
+ DeviceBuffer<RVec> getCoordinates();
/*! \brief Copy positions to the GPU memory.
*
*
* \returns GPU velocities buffer.
*/
- DeviceBuffer<float> getVelocities();
+ DeviceBuffer<RVec> getVelocities();
/*! \brief Copy velocities to the GPU memory.
*
*
* \returns GPU force buffer.
*/
- DeviceBuffer<float> getForces();
+ DeviceBuffer<RVec> getForces();
/*! \brief Copy forces to the GPU memory.
*
*
* \returns The device command stream to use in update-constraints.
*/
- void* getUpdateStream();
+ const DeviceStream* getUpdateStream();
/*! \brief Getter for the number of local atoms.
*
private:
//! GPU PME stream.
- CommandStream pmeStream_ = nullptr;
+ const DeviceStream* pmeStream_;
//! GPU NBNXM local stream.
- CommandStream localStream_ = nullptr;
- //! GPU NBNXM non-local stream
- CommandStream nonLocalStream_ = nullptr;
+ const DeviceStream* localStream_;
+ //! GPU NBNXM non-local stream.
+ const DeviceStream* nonLocalStream_;
//! GPU Update-constreaints stream.
- CommandStream updateStream_ = nullptr;
+ const DeviceStream* updateStream_;
// Streams to use for coordinates H2D and D2H copies (one event for each atom locality)
- EnumerationArray<AtomLocality, CommandStream> xCopyStreams_ = { { nullptr } };
+ EnumerationArray<AtomLocality, const DeviceStream*> xCopyStreams_ = { { nullptr } };
// Streams to use for velocities H2D and D2H copies (one event for each atom locality)
- EnumerationArray<AtomLocality, CommandStream> vCopyStreams_ = { { nullptr } };
+ EnumerationArray<AtomLocality, const DeviceStream*> vCopyStreams_ = { { nullptr } };
// Streams to use for forces H2D and D2H copies (one event for each atom locality)
- EnumerationArray<AtomLocality, CommandStream> fCopyStreams_ = { { nullptr } };
+ EnumerationArray<AtomLocality, const DeviceStream*> fCopyStreams_ = { { nullptr } };
/*! \brief An array of events that indicate H2D copy is complete (one event for each atom locality)
*
//! An array of events that indicate D2H copy of forces is complete (one event for each atom locality)
EnumerationArray<AtomLocality, GpuEventSynchronizer> fReadyOnHost_;
- /*! \brief GPU context (for OpenCL builds)
- * \todo Make a Context class usable in CPU code
- */
- DeviceContext deviceContext_ = nullptr;
+ //! GPU context (for OpenCL builds)
+ const DeviceContext& deviceContext_;
//! Default GPU calls behavior
GpuApiCallBehavior transferKind_ = GpuApiCallBehavior::Async;
- //! Padding size for the coordinates buffer
- int paddingSize_ = 0;
+ //! Required minimum divisor of the allocation size of the coordinates buffer
+ int allocationBlockSizeDivisor_ = 0;
//! Number of local atoms
int numAtomsLocal_ = -1;
int numAtomsAll_ = -1;
//! Device positions buffer
- DeviceBuffer<float> d_x_;
+ DeviceBuffer<RVec> d_x_;
//! Number of particles saved in the positions buffer
int d_xSize_ = -1;
//! Allocation size for the positions buffer
int d_xCapacity_ = -1;
//! Device velocities buffer
- DeviceBuffer<float> d_v_;
+ DeviceBuffer<RVec> d_v_;
//! Number of particles saved in the velocities buffer
int d_vSize_ = -1;
//! Allocation size for the velocities buffer
int d_vCapacity_ = -1;
//! Device force buffer
- DeviceBuffer<float> d_f_;
+ DeviceBuffer<RVec> d_f_;
//! Number of particles saved in the force buffer
int d_fSize_ = -1;
//! Allocation size for the force buffer
* \param[in] h_data Host-side buffer.
* \param[in] dataSize Device-side data allocation size.
* \param[in] atomLocality If all, local or non-local ranges should be copied.
- * \param[in] commandStream GPU stream to execute copy in.
+ * \param[in] deviceStream GPU stream to execute copy in.
*/
- void copyToDevice(DeviceBuffer<float> d_data,
+ void copyToDevice(DeviceBuffer<RVec> d_data,
gmx::ArrayRef<const gmx::RVec> h_data,
int dataSize,
AtomLocality atomLocality,
- CommandStream commandStream);
+ const DeviceStream& deviceStream);
/*! \brief Performs the copy of data from device to host buffer.
*
* \param[in] d_data Device-side buffer.
* \param[in] dataSize Device-side data allocation size.
* \param[in] atomLocality If all, local or non-local ranges should be copied.
- * \param[in] commandStream GPU stream to execute copy in.
+ * \param[in] deviceStream GPU stream to execute copy in.
*/
void copyFromDevice(gmx::ArrayRef<gmx::RVec> h_data,
- DeviceBuffer<float> d_data,
+ DeviceBuffer<RVec> d_data,
int dataSize,
AtomLocality atomLocality,
- CommandStream commandStream);
+ const DeviceStream& deviceStream);
};
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#if GMX_GPU != GMX_GPU_NONE
-# if GMX_GPU == GMX_GPU_CUDA
-# include "gromacs/gpu_utils/cudautils.cuh"
-# endif
+# include "gromacs/gpu_utils/device_stream_manager.h"
# include "gromacs/gpu_utils/devicebuffer.h"
-# if GMX_GPU == GMX_GPU_OPENCL
-# include "gromacs/gpu_utils/oclutils.h"
-# endif
+# include "gromacs/gpu_utils/gputraits.h"
# include "gromacs/math/vectypes.h"
# include "gromacs/mdtypes/state_propagator_data_gpu.h"
# include "gromacs/timing/wallcycle.h"
namespace gmx
{
-StatePropagatorDataGpu::Impl::Impl(const void* pmeStream,
- const void* localStream,
- const void* nonLocalStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle) :
+StatePropagatorDataGpu::Impl::Impl(const DeviceStreamManager& deviceStreamManager,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle) :
+ deviceContext_(deviceStreamManager.context()),
transferKind_(transferKind),
- paddingSize_(paddingSize),
+ allocationBlockSizeDivisor_(allocationBlockSizeDivisor),
wcycle_(wcycle)
{
- static_assert(GMX_GPU != GMX_GPU_NONE,
- "This object should only be constructed on the GPU code-paths.");
+ static_assert(
+ GMX_GPU != GMX_GPU_NONE,
+ "GPU state propagator data object should only be constructed on the GPU code-paths.");
- // TODO: Refactor when the StreamManager is introduced.
+ // We need to keep local copies for re-initialization.
+ pmeStream_ = &deviceStreamManager.stream(DeviceStreamType::Pme);
+ localStream_ = &deviceStreamManager.stream(DeviceStreamType::NonBondedLocal);
+ nonLocalStream_ = &deviceStreamManager.stream(DeviceStreamType::NonBondedNonLocal);
+ // PME stream is used in OpenCL for H2D coordinate transfer
if (GMX_GPU == GMX_GPU_OPENCL)
{
- GMX_ASSERT(deviceContext != nullptr, "GPU context should be set in OpenCL builds.");
- GMX_ASSERT(pmeStream != nullptr, "GPU PME stream should be set in OpenCL builds.");
-
- // The update stream is set to the PME stream in OpenCL, since PME stream is the only stream created in the PME context.
- pmeStream_ = *static_cast<const CommandStream*>(pmeStream);
- updateStream_ = *static_cast<const CommandStream*>(pmeStream);
- deviceContext_ = *static_cast<const DeviceContext*>(deviceContext);
- GMX_UNUSED_VALUE(localStream);
- GMX_UNUSED_VALUE(nonLocalStream);
+ updateStream_ = &deviceStreamManager.stream(DeviceStreamType::Pme);
}
-
- if (GMX_GPU == GMX_GPU_CUDA)
+ else
{
- if (pmeStream != nullptr)
- {
- pmeStream_ = *static_cast<const CommandStream*>(pmeStream);
- }
- if (localStream != nullptr)
- {
- localStream_ = *static_cast<const CommandStream*>(localStream);
- }
- if (nonLocalStream != nullptr)
- {
- nonLocalStream_ = *static_cast<const CommandStream*>(nonLocalStream);
- }
-
- // TODO: The update stream should be created only when it is needed.
-# if (GMX_GPU == GMX_GPU_CUDA)
- cudaError_t stat;
- stat = cudaStreamCreate(&updateStream_);
- CU_RET_ERR(stat, "CUDA stream creation failed in StatePropagatorDataGpu");
-# endif
- GMX_UNUSED_VALUE(deviceContext);
+ updateStream_ = &deviceStreamManager.stream(DeviceStreamType::UpdateAndConstraints);
}
// Map the atom locality to the stream that will be used for coordinates,
fCopyStreams_[AtomLocality::All] = updateStream_;
}
-StatePropagatorDataGpu::Impl::Impl(const void* pmeStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle) :
+StatePropagatorDataGpu::Impl::Impl(const DeviceStream* pmeStream,
+ const DeviceContext& deviceContext,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle) :
+ deviceContext_(deviceContext),
transferKind_(transferKind),
- paddingSize_(paddingSize),
+ allocationBlockSizeDivisor_(allocationBlockSizeDivisor),
wcycle_(wcycle)
{
- static_assert(GMX_GPU != GMX_GPU_NONE,
- "This object should only be constructed on the GPU code-paths.");
-
- if (GMX_GPU == GMX_GPU_OPENCL)
- {
- GMX_ASSERT(deviceContext != nullptr, "GPU context should be set in OpenCL builds.");
- deviceContext_ = *static_cast<const DeviceContext*>(deviceContext);
- }
+ static_assert(
+ GMX_GPU != GMX_GPU_NONE,
+ "GPU state propagator data object should only be constructed on the GPU code-paths.");
- GMX_ASSERT(pmeStream != nullptr, "GPU PME stream should be set.");
- pmeStream_ = *static_cast<const CommandStream*>(pmeStream);
-
- localStream_ = nullptr;
+ GMX_ASSERT(pmeStream->isValid(), "GPU PME stream should be valid.");
+ pmeStream_ = pmeStream;
+ localStream_ = pmeStream; // For clearing the force buffer
nonLocalStream_ = nullptr;
updateStream_ = nullptr;
numAtomsAll_ = numAtomsAll;
int numAtomsPadded;
- if (paddingSize_ > 0)
+ if (allocationBlockSizeDivisor_ > 0)
{
- numAtomsPadded = ((numAtomsAll_ + paddingSize_ - 1) / paddingSize_) * paddingSize_;
+ numAtomsPadded = ((numAtomsAll_ + allocationBlockSizeDivisor_ - 1) / allocationBlockSizeDivisor_)
+ * allocationBlockSizeDivisor_;
}
else
{
numAtomsPadded = numAtomsAll_;
}
- reallocateDeviceBuffer(&d_x_, DIM * numAtomsPadded, &d_xSize_, &d_xCapacity_, deviceContext_);
+ reallocateDeviceBuffer(&d_x_, numAtomsPadded, &d_xSize_, &d_xCapacity_, deviceContext_);
const size_t paddingAllocationSize = numAtomsPadded - numAtomsAll_;
if (paddingAllocationSize > 0)
{
// The PME stream is used here because the padding region of d_x_ is only in the PME task.
- clearDeviceBufferAsync(&d_x_, DIM * numAtomsAll_, DIM * paddingAllocationSize, pmeStream_);
+ clearDeviceBufferAsync(&d_x_, numAtomsAll_, paddingAllocationSize, *pmeStream_);
}
- reallocateDeviceBuffer(&d_v_, DIM * numAtomsAll_, &d_vSize_, &d_vCapacity_, deviceContext_);
+ reallocateDeviceBuffer(&d_v_, numAtomsAll_, &d_vSize_, &d_vCapacity_, deviceContext_);
const int d_fOldCapacity = d_fCapacity_;
- reallocateDeviceBuffer(&d_f_, DIM * numAtomsAll_, &d_fSize_, &d_fCapacity_, deviceContext_);
+ reallocateDeviceBuffer(&d_f_, numAtomsAll_, &d_fSize_, &d_fCapacity_, deviceContext_);
// Clearing of the forces can be done in local stream since the nonlocal stream cannot reach
// the force accumulation stage before syncing with the local stream. Only done in CUDA,
// since the force buffer ops are not implemented in OpenCL.
if (GMX_GPU == GMX_GPU_CUDA && d_fCapacity_ != d_fOldCapacity)
{
- clearDeviceBufferAsync(&d_f_, 0, d_fCapacity_, localStream_);
+ clearDeviceBufferAsync(&d_f_, 0, d_fCapacity_, *localStream_);
}
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
return std::make_tuple(atomsStartAt, numAtomsToCopy);
}
-void StatePropagatorDataGpu::Impl::copyToDevice(DeviceBuffer<float> d_data,
+void StatePropagatorDataGpu::Impl::copyToDevice(DeviceBuffer<RVec> d_data,
const gmx::ArrayRef<const gmx::RVec> h_data,
int dataSize,
AtomLocality atomLocality,
- CommandStream commandStream)
+ const DeviceStream& deviceStream)
{
GMX_UNUSED_VALUE(dataSize);
+ GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
+
GMX_ASSERT(dataSize >= 0, "Trying to copy to device buffer before it was allocated.");
+ GMX_ASSERT(deviceStream.isValid(), "No stream is valid for copying with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
int atomsStartAt, numAtomsToCopy;
std::tie(atomsStartAt, numAtomsToCopy) = getAtomRangesFromAtomLocality(atomLocality);
- int elementsStartAt = atomsStartAt * DIM;
- int numElementsToCopy = numAtomsToCopy * DIM;
-
if (numAtomsToCopy != 0)
{
- GMX_ASSERT(elementsStartAt + numElementsToCopy <= dataSize,
+ GMX_ASSERT(atomsStartAt + numAtomsToCopy <= dataSize,
"The device allocation is smaller than requested copy range.");
GMX_ASSERT(atomsStartAt + numAtomsToCopy <= h_data.ssize(),
"The host buffer is smaller than the requested copy range.");
- copyToDeviceBuffer(&d_data, reinterpret_cast<const float*>(&h_data.data()[atomsStartAt]),
- elementsStartAt, numElementsToCopy, commandStream, transferKind_, nullptr);
+ copyToDeviceBuffer(&d_data, reinterpret_cast<const RVec*>(&h_data.data()[atomsStartAt]),
+ atomsStartAt, numAtomsToCopy, deviceStream, transferKind_, nullptr);
}
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
}
void StatePropagatorDataGpu::Impl::copyFromDevice(gmx::ArrayRef<gmx::RVec> h_data,
- DeviceBuffer<float> d_data,
+ DeviceBuffer<RVec> d_data,
int dataSize,
AtomLocality atomLocality,
- CommandStream commandStream)
+ const DeviceStream& deviceStream)
{
GMX_UNUSED_VALUE(dataSize);
+ GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
+
GMX_ASSERT(dataSize >= 0, "Trying to copy from device buffer before it was allocated.");
+ GMX_ASSERT(deviceStream.isValid(), "No stream is valid for copying with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
int atomsStartAt, numAtomsToCopy;
std::tie(atomsStartAt, numAtomsToCopy) = getAtomRangesFromAtomLocality(atomLocality);
- int elementsStartAt = atomsStartAt * DIM;
- int numElementsToCopy = numAtomsToCopy * DIM;
-
if (numAtomsToCopy != 0)
{
- GMX_ASSERT(elementsStartAt + numElementsToCopy <= dataSize,
+ GMX_ASSERT(atomsStartAt + numAtomsToCopy <= dataSize,
"The device allocation is smaller than requested copy range.");
GMX_ASSERT(atomsStartAt + numAtomsToCopy <= h_data.ssize(),
"The host buffer is smaller than the requested copy range.");
- copyFromDeviceBuffer(reinterpret_cast<float*>(&h_data.data()[atomsStartAt]), &d_data,
- elementsStartAt, numElementsToCopy, commandStream, transferKind_, nullptr);
+ copyFromDeviceBuffer(reinterpret_cast<RVec*>(&h_data.data()[atomsStartAt]), &d_data,
+ atomsStartAt, numAtomsToCopy, deviceStream, transferKind_, nullptr);
}
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
}
-DeviceBuffer<float> StatePropagatorDataGpu::Impl::getCoordinates()
+DeviceBuffer<RVec> StatePropagatorDataGpu::Impl::getCoordinates()
{
return d_x_;
}
AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = xCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = xCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying positions with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyToDevice(d_x_, h_x, d_xSize_, atomLocality, commandStream);
+ copyToDevice(d_x_, h_x, d_xSize_, atomLocality, *deviceStream);
// markEvent is skipped in OpenCL as:
// - it's not needed, copy is done in the same stream as the only consumer task (PME)
// TODO: remove this by adding an event-mark free flavor of this function
if (GMX_GPU == GMX_GPU_CUDA)
{
- xReadyOnDevice_[atomLocality].markEvent(commandStream);
+ xReadyOnDevice_[atomLocality].markEvent(*deviceStream);
}
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
void StatePropagatorDataGpu::Impl::copyCoordinatesFromGpu(gmx::ArrayRef<gmx::RVec> h_x, AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = xCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = xCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying positions with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyFromDevice(h_x, d_x_, d_xSize_, atomLocality, commandStream);
+ copyFromDevice(h_x, d_x_, d_xSize_, atomLocality, *deviceStream);
// Note: unlike copyCoordinatesToGpu this is not used in OpenCL, and the conditional is not needed.
- xReadyOnHost_[atomLocality].markEvent(commandStream);
+ xReadyOnHost_[atomLocality].markEvent(*deviceStream);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
}
-DeviceBuffer<float> StatePropagatorDataGpu::Impl::getVelocities()
+DeviceBuffer<RVec> StatePropagatorDataGpu::Impl::getVelocities()
{
return d_v_;
}
AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = vCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = vCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying velocities with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyToDevice(d_v_, h_v, d_vSize_, atomLocality, commandStream);
- vReadyOnDevice_[atomLocality].markEvent(commandStream);
+ copyToDevice(d_v_, h_v, d_vSize_, atomLocality, *deviceStream);
+ vReadyOnDevice_[atomLocality].markEvent(*deviceStream);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
void StatePropagatorDataGpu::Impl::copyVelocitiesFromGpu(gmx::ArrayRef<gmx::RVec> h_v, AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = vCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = vCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying velocities with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyFromDevice(h_v, d_v_, d_vSize_, atomLocality, commandStream);
- vReadyOnHost_[atomLocality].markEvent(commandStream);
+ copyFromDevice(h_v, d_v_, d_vSize_, atomLocality, *deviceStream);
+ vReadyOnHost_[atomLocality].markEvent(*deviceStream);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
}
-DeviceBuffer<float> StatePropagatorDataGpu::Impl::getForces()
+DeviceBuffer<RVec> StatePropagatorDataGpu::Impl::getForces()
{
return d_f_;
}
AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = fCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = fCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying forces with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyToDevice(d_f_, h_f, d_fSize_, atomLocality, commandStream);
- fReadyOnDevice_[atomLocality].markEvent(commandStream);
+ copyToDevice(d_f_, h_f, d_fSize_, atomLocality, *deviceStream);
+ fReadyOnDevice_[atomLocality].markEvent(*deviceStream);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
void StatePropagatorDataGpu::Impl::copyForcesFromGpu(gmx::ArrayRef<gmx::RVec> h_f, AtomLocality atomLocality)
{
GMX_ASSERT(atomLocality < AtomLocality::Count, "Wrong atom locality.");
- CommandStream commandStream = fCopyStreams_[atomLocality];
- GMX_ASSERT(commandStream != nullptr,
+ const DeviceStream* deviceStream = fCopyStreams_[atomLocality];
+ GMX_ASSERT(deviceStream != nullptr,
"No stream is valid for copying forces with given atom locality.");
wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
- copyFromDevice(h_f, d_f_, d_fSize_, atomLocality, commandStream);
- fReadyOnHost_[atomLocality].markEvent(commandStream);
+ copyFromDevice(h_f, d_f_, d_fSize_, atomLocality, *deviceStream);
+ fReadyOnHost_[atomLocality].markEvent(*deviceStream);
wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
wallcycle_stop(wcycle_, ewcLAUNCH_GPU);
wallcycle_stop(wcycle_, ewcWAIT_GPU_STATE_PROPAGATOR_DATA);
}
-void* StatePropagatorDataGpu::Impl::getUpdateStream()
+const DeviceStream* StatePropagatorDataGpu::Impl::getUpdateStream()
{
- return &updateStream_;
+ return updateStream_;
}
int StatePropagatorDataGpu::Impl::numAtomsLocal()
}
-StatePropagatorDataGpu::StatePropagatorDataGpu(const void* pmeStream,
- const void* localStream,
- const void* nonLocalStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle) :
- impl_(new Impl(pmeStream, localStream, nonLocalStream, deviceContext, transferKind, paddingSize, wcycle))
+StatePropagatorDataGpu::StatePropagatorDataGpu(const DeviceStreamManager& deviceStreamManager,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle) :
+ impl_(new Impl(deviceStreamManager, transferKind, allocationBlockSizeDivisor, wcycle))
{
}
-StatePropagatorDataGpu::StatePropagatorDataGpu(const void* pmeStream,
- const void* deviceContext,
- GpuApiCallBehavior transferKind,
- int paddingSize,
- gmx_wallcycle* wcycle) :
- impl_(new Impl(pmeStream, deviceContext, transferKind, paddingSize, wcycle))
+StatePropagatorDataGpu::StatePropagatorDataGpu(const DeviceStream* pmeStream,
+ const DeviceContext& deviceContext,
+ GpuApiCallBehavior transferKind,
+ int allocationBlockSizeDivisor,
+ gmx_wallcycle* wcycle) :
+ impl_(new Impl(pmeStream, deviceContext, transferKind, allocationBlockSizeDivisor, wcycle))
{
}
}
-DeviceBuffer<float> StatePropagatorDataGpu::getCoordinates()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getCoordinates()
{
return impl_->getCoordinates();
}
}
-DeviceBuffer<float> StatePropagatorDataGpu::getVelocities()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getVelocities()
{
return impl_->getVelocities();
}
}
-DeviceBuffer<float> StatePropagatorDataGpu::getForces()
+DeviceBuffer<RVec> StatePropagatorDataGpu::getForces()
{
return impl_->getForces();
}
}
-void* StatePropagatorDataGpu::getUpdateStream()
+const DeviceStream* StatePropagatorDataGpu::getUpdateStream()
{
return impl_->getUpdateStream();
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
char path[GMX_PATH_MAX];
gmx_getcwd(path, GMX_PATH_MAX);
- return MCL_init_client(path);
+ MCL_init_client(path);
}
void gmx::MimicCommunicator::sendInitData(gmx_mtop_t* mtop, PaddedHostVector<gmx::RVec> coords)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief
* Initializes the communicator
*/
- void init();
+ static void init();
/*! \brief
* Sends the data needed for MiMiC initialization
* @param mtop global topology data
* @param coords coordinates of all atoms
*/
- void sendInitData(gmx_mtop_t* mtop, PaddedHostVector<gmx::RVec> coords);
+ static void sendInitData(gmx_mtop_t* mtop, PaddedHostVector<gmx::RVec> coords);
/*! \brief
* Gets the number of MD steps to perform from MiMiC
*
* @return nsteps the number of MD steps to perform
*/
- int64_t getStepNumber();
+ static int64_t getStepNumber();
/*! \brief
* Receive and array of updated atomic coordinates from MiMiC
* @param x array of coordinates to fill
* @param natoms number of atoms in the system
*/
- void getCoords(PaddedHostVector<RVec>* x, int natoms);
+ static void getCoords(PaddedHostVector<RVec>* x, int natoms);
/*! \brief
* Send the potential energy value to MiMiC
*
* @param energy energy value to send
*/
- void sendEnergies(real energy);
+ static void sendEnergies(real energy);
/*! \brief
* Send classical forces acting on all atoms in the system
* @param forces array of forces to send
* @param natoms number of atoms in the system
*/
- void sendForces(ArrayRef<gmx::RVec> forces, int natoms);
+ static void sendForces(ArrayRef<gmx::RVec> forces, int natoms);
/*! \brief
* Finish communications and disconnect from the server
*/
- void finalize();
+ static void finalize();
};
} // namespace gmx
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
file(GLOB MODULARSIMULATOR_SOURCES *.cpp)
add_library(modularsimulator OBJECT ${MODULARSIMULATOR_SOURCES})
+target_include_directories(modularsimulator SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
gmx_target_compile_options(modularsimulator)
target_compile_definitions(modularsimulator PRIVATE HAVE_CONFIG_H)
+# Should be possible to remove this when resolving #3290
target_include_directories(modularsimulator SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
if(GMX_OPENMP)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/topology/topology.h"
#include "freeenergyperturbationelement.h"
FILE* fplog,
const MDLogger& mdlog,
t_commrec* cr,
- t_inputrec* inputrec,
+ const t_inputrec* inputrec,
const MDAtoms* mdAtoms,
t_nrnb* nrnb,
gmx_wallcycle* wcycle,
bool hasReadEkinState) :
energyReductionStep_(-1),
virialReductionStep_(-1),
+ vvSchedulingStep_(-1),
doStopCM_(inputrec->comm_mode != ecmNO),
nstcomm_(inputrec->nstcomm),
nstglobalcomm_(nstglobalcomm),
{
GMX_ASSERT(localTopology_, "Setup called before local topology was set.");
- // Only do initial communication step for one of the velocity-verlet stages
- if (algorithm == ComputeGlobalsAlgorithm::LeapFrog
- || algorithm == ComputeGlobalsAlgorithm::VelocityVerletAtFullTimeStep)
+ if (doStopCM_ && !inputrec_->bContinuation)
{
- unsigned int cglo_flags =
- (CGLO_TEMPERATURE | CGLO_GSTAT
- | (shouldCheckNumberOfBondedInteractions_ ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0)
- | (hasReadEkinState_ ? CGLO_READEKIN : 0));
-
- if (algorithm == ComputeGlobalsAlgorithm::VelocityVerletAtFullTimeStep)
- {
- cglo_flags |= CGLO_PRESSURE | CGLO_CONSTRAINT;
- }
-
- const bool stopCM = doStopCM_ && !inputrec_->bContinuation;
-
// To minimize communication, compute_globals computes the COM velocity
// and the kinetic energy for the velocities without COM motion removed.
// Thus to get the kinetic energy without the COM contribution, we need
// to call compute_globals twice.
- for (int cgloIteration = 0; cgloIteration < (stopCM ? 2 : 1); cgloIteration++)
- {
- unsigned int cglo_flags_iteration = cglo_flags;
- if (stopCM && cgloIteration == 0)
- {
- cglo_flags_iteration |= CGLO_STOPCM;
- cglo_flags_iteration &= ~CGLO_TEMPERATURE;
- }
- compute(-1, cglo_flags_iteration, nullSignaller_.get(), false, true);
+ compute(-1, CGLO_GSTAT | CGLO_STOPCM, nullSignaller_.get(), false, true);
- if (cglo_flags_iteration & CGLO_STOPCM)
- {
- auto v = as_rvec_array(statePropagatorData_->velocitiesView().paddedArrayRef().data());
- // At initialization, do not pass x with acceleration-correction mode
- // to avoid (incorrect) correction of the initial coordinates.
- rvec* xPtr = nullptr;
- if (vcm_.mode != ecmLINEAR_ACCELERATION_CORRECTION)
- {
- xPtr = as_rvec_array(statePropagatorData_->positionsView().paddedArrayRef().data());
- }
- process_and_stopcm_grp(fplog_, &vcm_, *mdAtoms_->mdatoms(), xPtr, v);
- inc_nrnb(nrnb_, eNR_STOPCM, mdAtoms_->mdatoms()->homenr);
- }
- }
+ auto v = statePropagatorData_->velocitiesView();
+ // At initialization, do not pass x with acceleration-correction mode
+ // to avoid (incorrect) correction of the initial coordinates.
+ auto x = vcm_.mode == ecmLINEAR_ACCELERATION_CORRECTION ? ArrayRefWithPadding<RVec>()
+ : statePropagatorData_->positionsView();
+ process_and_stopcm_grp(fplog_, &vcm_, *mdAtoms_->mdatoms(), x.unpaddedArrayRef(),
+ v.unpaddedArrayRef());
+ inc_nrnb(nrnb_, eNR_STOPCM, mdAtoms_->mdatoms()->homenr);
+ }
- // Calculate the initial half step temperature, and save the ekinh_old
- for (int i = 0; (i < inputrec_->opts.ngtc); i++)
- {
- copy_mat(energyElement_->ekindata()->tcstat[i].ekinh,
- energyElement_->ekindata()->tcstat[i].ekinh_old);
- }
+ unsigned int cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT | (hasReadEkinState_ ? CGLO_READEKIN : 0));
+
+ if (algorithm == ComputeGlobalsAlgorithm::VelocityVerlet)
+ {
+ cglo_flags |= CGLO_PRESSURE | CGLO_CONSTRAINT;
+ }
+
+ compute(-1, cglo_flags, nullSignaller_.get(), false, true);
+
+ // Calculate the initial half step temperature, and save the ekinh_old
+ for (int i = 0; (i < inputrec_->opts.ngtc); i++)
+ {
+ copy_mat(energyElement_->ekindata()->tcstat[i].ekinh,
+ energyElement_->ekindata()->tcstat[i].ekinh_old);
}
}
}
const bool doEnergy = step == energyReductionStep_;
- int flags =
- (needGlobalReduction ? CGLO_GSTAT : 0) | (doEnergy ? CGLO_ENERGY : 0)
- | (needComReduction ? CGLO_STOPCM : 0) | CGLO_TEMPERATURE | CGLO_PRESSURE | CGLO_CONSTRAINT
- | (shouldCheckNumberOfBondedInteractions_ ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0);
+ int flags = (needGlobalReduction ? CGLO_GSTAT : 0) | (doEnergy ? CGLO_ENERGY : 0)
+ | (needComReduction ? CGLO_STOPCM : 0) | CGLO_TEMPERATURE | CGLO_PRESSURE
+ | CGLO_CONSTRAINT;
// Since we're already communicating at this step, we
// can propagate intra-simulation signals. Note that
compute(step, flags, signaller.get(), true);
}));
}
- else if (algorithm == ComputeGlobalsAlgorithm::VelocityVerletAtFullTimeStep)
+ else if (algorithm == ComputeGlobalsAlgorithm::VelocityVerlet)
{
- // For vv, the state at the beginning of the step is positions at time t, velocities at time t - dt/2
- // The first velocity propagation (+dt/2) therefore actually corresponds to the previous step.
- // So we need information from the last step in the first half of the integration
- if (!needGlobalReduction && !do_per_step(step - 1, nstglobalcomm_))
+ // For VV, we schedule two calls to compute globals per step.
+ if (step != vvSchedulingStep_)
{
- return;
- }
+ // This is the first scheduling call for this step (positions & velocities at full time
+ // step) Set this as the current scheduling step
+ vvSchedulingStep_ = step;
+
+ // For vv, the state at the beginning of the step is positions at time t, velocities at time t - dt/2
+ // The first velocity propagation (+dt/2) therefore actually corresponds to the previous step.
+ // So we need information from the last step in the first half of the integration
+ if (!needGlobalReduction && !do_per_step(step - 1, nstglobalcomm_))
+ {
+ return;
+ }
- const bool doTemperature = step != initStep_ || inputrec_->bContinuation;
- const bool doEnergy = step == energyReductionStep_;
+ const bool doTemperature = step != initStep_ || inputrec_->bContinuation;
+ const bool doEnergy = step == energyReductionStep_;
- int flags = (needGlobalReduction ? CGLO_GSTAT : 0) | (doEnergy ? CGLO_ENERGY : 0)
- | (doTemperature ? CGLO_TEMPERATURE : 0) | CGLO_PRESSURE | CGLO_CONSTRAINT
- | (needComReduction ? CGLO_STOPCM : 0)
- | (shouldCheckNumberOfBondedInteractions_ ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0)
- | CGLO_SCALEEKIN;
+ int flags = (needGlobalReduction ? CGLO_GSTAT : 0) | (doEnergy ? CGLO_ENERGY : 0)
+ | (doTemperature ? CGLO_TEMPERATURE : 0) | CGLO_PRESSURE | CGLO_CONSTRAINT
+ | (needComReduction ? CGLO_STOPCM : 0) | CGLO_SCALEEKIN;
- (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
- [this, step, flags]() { compute(step, flags, nullSignaller_.get(), false); }));
- }
- else if (algorithm == ComputeGlobalsAlgorithm::VelocityVerletAfterCoordinateUpdate)
- {
- // second call to compute_globals for this step
- if (!needGlobalReduction)
- {
- return;
+ (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
+ [this, step, flags]() { compute(step, flags, nullSignaller_.get(), false); }));
}
- int flags = CGLO_GSTAT | CGLO_CONSTRAINT
- | (shouldCheckNumberOfBondedInteractions_ ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
- : 0);
-
- // Since we're already communicating at this step, we
- // can propagate intra-simulation signals. Note that
- // check_nstglobalcomm has the responsibility for
- // choosing the value of nstglobalcomm which satisfies
- // the need of the different signallers.
- const bool doIntraSimSignal = true;
- // Disable functionality
- const bool doInterSimSignal = false;
-
- auto signaller = std::make_shared<SimulationSignaller>(signals_, cr_, nullptr,
- doInterSimSignal, doIntraSimSignal);
+ else
+ {
+ // second call to compute_globals for this step
+ // Reset the scheduling step to avoid confusion if scheduling needs
+ // to be repeated (in case of unexpected simulation termination)
+ vvSchedulingStep_ = -1;
- (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
- [this, step, flags, signaller = std::move(signaller)]() {
- compute(step, flags, signaller.get(), true);
- }));
+ if (!needGlobalReduction)
+ {
+ return;
+ }
+ int flags = CGLO_GSTAT | CGLO_CONSTRAINT;
+
+ // Since we're already communicating at this step, we
+ // can propagate intra-simulation signals. Note that
+ // check_nstglobalcomm has the responsibility for
+ // choosing the value of nstglobalcomm which satisfies
+ // the need of the different signallers.
+ const bool doIntraSimSignal = true;
+ // Disable functionality
+ const bool doInterSimSignal = false;
+
+ auto signaller = std::make_shared<SimulationSignaller>(
+ signals_, cr_, nullptr, doInterSimSignal, doIntraSimSignal);
+
+ (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
+ [this, step, flags, signaller = std::move(signaller)]() {
+ compute(step, flags, signaller.get(), true);
+ }));
+ }
}
}
bool useLastBox,
bool isInit)
{
- auto x = as_rvec_array(statePropagatorData_->positionsView().paddedArrayRef().data());
- auto v = as_rvec_array(statePropagatorData_->velocitiesView().paddedArrayRef().data());
+ auto x = statePropagatorData_->positionsView().unpaddedArrayRef();
+ auto v = statePropagatorData_->velocitiesView().unpaddedArrayRef();
auto box = statePropagatorData_->constBox();
auto lastbox = useLastBox ? statePropagatorData_->constPreviousBox()
: statePropagatorData_->constBox();
? freeEnergyPerturbationElement_->constLambdaView()[efptVDW]
: 0;
- compute_globals(gstat_, cr_, inputrec_, fr_, energyElement_->ekindata(), x, v, box, vdwLambda,
- mdAtoms_->mdatoms(), nrnb_, &vcm_, step != -1 ? wcycle_ : nullptr,
- energyElement_->enerdata(), energyElement_->forceVirial(step),
- energyElement_->constraintVirial(step), energyElement_->totalVirial(step),
- energyElement_->pressure(step), energyElement_->muTot(), constr_, signaller, lastbox,
- &totalNumberOfBondedInteractions_, energyElement_->needToSumEkinhOld(), flags);
+ compute_globals(
+ gstat_, cr_, inputrec_, fr_, energyElement_->ekindata(), x, v, box, vdwLambda,
+ mdAtoms_->mdatoms(), nrnb_, &vcm_, step != -1 ? wcycle_ : nullptr, energyElement_->enerdata(),
+ energyElement_->forceVirial(step), energyElement_->constraintVirial(step),
+ energyElement_->totalVirial(step), energyElement_->pressure(step), constr_, signaller,
+ lastbox, &totalNumberOfBondedInteractions_, energyElement_->needToSumEkinhOld(),
+ flags | (shouldCheckNumberOfBondedInteractions_ ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS : 0));
checkNumberOfBondedInteractions(mdlog_, cr_, totalNumberOfBondedInteractions_, top_global_,
localTopology_, x, box, &shouldCheckNumberOfBondedInteractions_);
if (flags & CGLO_STOPCM && !isInit)
//! Explicit template instantiation
//! @{
template class ComputeGlobalsElement<ComputeGlobalsAlgorithm::LeapFrog>;
-template class ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerletAtFullTimeStep>;
-template class ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerletAfterCoordinateUpdate>;
+template class ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>;
//! @}
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
enum class ComputeGlobalsAlgorithm
{
LeapFrog,
- VelocityVerletAtFullTimeStep,
- VelocityVerletAfterCoordinateUpdate
+ VelocityVerlet
};
//! The function type allowing to request a check of the number of bonded interactions
FILE* fplog,
const MDLogger& mdlog,
t_commrec* cr,
- t_inputrec* inputrec,
+ const t_inputrec* inputrec,
const MDAtoms* mdAtoms,
t_nrnb* nrnb,
gmx_wallcycle* wcycle,
//! Next step at which virial needs to be reduced
Step virialReductionStep_;
+ //! For VV only, we need to schedule twice per step. This keeps track of the scheduling stage.
+ Step vvSchedulingStep_;
+
//! Whether center of mass motion stopping is enabled
const bool doStopCM_;
//! Number of steps after which center of mass motion is removed
//! Handles communication.
t_commrec* cr_;
//! Contains user input mdp options.
- t_inputrec* inputrec_;
+ const t_inputrec* inputrec_;
//! Full system topology - only needed for checkNumberOfBondedInteractions.
const gmx_mtop_t* top_global_;
//! Atom parameters for this domain.
{
tensor vir_con;
- rvec *x, *xprime, *min_proj, *v;
+ ArrayRefWithPadding<RVec> x;
+ ArrayRefWithPadding<RVec> xprime;
+ ArrayRef<RVec> min_proj;
+ ArrayRefWithPadding<RVec> v;
const real lambdaBonded = freeEnergyPerturbationElement_
? freeEnergyPerturbationElement_->constLambdaView()[efptBONDED]
switch (variable)
{
case ConstraintVariable::Positions:
- x = as_rvec_array(statePropagatorData_->previousPositionsView().paddedArrayRef().data());
- xprime = as_rvec_array(statePropagatorData_->positionsView().paddedArrayRef().data());
- min_proj = nullptr;
- v = as_rvec_array(statePropagatorData_->velocitiesView().paddedArrayRef().data());
+ x = statePropagatorData_->previousPositionsView();
+ xprime = statePropagatorData_->positionsView();
+ v = statePropagatorData_->velocitiesView();
break;
case ConstraintVariable::Velocities:
- x = as_rvec_array(statePropagatorData_->positionsView().paddedArrayRef().data());
- xprime = as_rvec_array(statePropagatorData_->velocitiesView().paddedArrayRef().data());
- min_proj = as_rvec_array(statePropagatorData_->velocitiesView().paddedArrayRef().data());
- v = nullptr;
+ x = statePropagatorData_->positionsView();
+ xprime = statePropagatorData_->velocitiesView();
+ min_proj = statePropagatorData_->velocitiesView().unpaddedArrayRef();
break;
default: gmx_fatal(FARGS, "Constraint algorithm not implemented for modular simulator.");
}
* good approximation, statistically insignificant in any real free energy
* calculation. Any possible error is not a simulation propagation error,
* but a potential reporting error in the data that goes to dh/dlambda.
- * Cf. redmine issue #1255
+ * Cf. Issue #1255
*/
const real c_dvdlConstraintCorrectionFactor = EI_VV(inputrec_->eI) ? 2.0 : 1.0;
energyElement_->enerdata()->term[F_DVDL_CONSTR] += c_dvdlConstraintCorrectionFactor * dvdlambda;
{
// TODO: Correcting the box is done here (if using DD) or in ForceElement (non-DD simulations).
// Think about unifying this responsibility, could this be done in one place?
- t_graph* graph = nullptr;
- if (correct_box(fplog_, step, localState->box, graph))
+ if (correct_box(fplog_, step, localState->box))
{
isMasterState = true;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/energyhistory.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/pullhistory.h"
#include "gromacs/mdtypes/state.h"
#include "forceelement.h"
+#include "gromacs/domdec/mdsetup.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/mdlib/constr.h"
#include "gromacs/mdlib/force.h"
#include "gromacs/mdlib/force_flags.h"
#include "gromacs/mdlib/mdatoms.h"
+#include "gromacs/mdrun/shellfc.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/pbcutil/pbc.h"
#include "energyelement.h"
struct gmx_enfrot;
struct gmx_multisim_t;
class history_t;
-struct t_graph;
namespace gmx
{
ForceElement::ForceElement(StatePropagatorData* statePropagatorData,
EnergyElement* energyElement,
FreeEnergyPerturbationElement* freeEnergyPerturbationElement,
+ bool isVerbose,
bool isDynamicBox,
FILE* fplog,
const t_commrec* cr,
gmx_vsite_t* vsite,
ImdSession* imdSession,
pull_t* pull_work,
+ Constraints* constr,
+ const gmx_mtop_t* globalTopology,
gmx_enfrot* enforcedRotation) :
+ shellfc_(init_shell_flexcon(fplog,
+ globalTopology,
+ constr ? constr->numFlexibleConstraints() : 0,
+ inputrec->nstcalcenergy,
+ DOMAINDECOMP(cr))),
+ doShellFC_(shellfc_ != nullptr),
nextNSStep_(-1),
nextEnergyCalculationStep_(-1),
nextVirialCalculationStep_(-1),
freeEnergyPerturbationElement_(freeEnergyPerturbationElement),
localTopology_(nullptr),
isDynamicBox_(isDynamicBox),
+ isVerbose_(isVerbose),
+ nShellRelaxationSteps_(0),
ddBalanceRegionHandler_(cr),
lambda_(),
fplog_(fplog),
pull_work_(pull_work),
fcd_(fcd),
runScheduleWork_(runScheduleWork),
+ constr_(constr),
enforcedRotation_(enforcedRotation)
{
lambda_.fill(0);
+
+ if (doShellFC_ && !DOMAINDECOMP(cr))
+ {
+ // This was done in mdAlgorithmsSetupAtomData(), but shellfc
+ // won't be available outside this element.
+ make_local_shells(cr, mdAtoms->mdatoms(), shellfc_);
+ }
}
void ForceElement::scheduleTask(Step step, Time time, const RegisterRunFunctionPtr& registerRunFunction)
| (nextVirialCalculationStep_ == step ? GMX_FORCE_VIRIAL : 0)
| (nextEnergyCalculationStep_ == step ? GMX_FORCE_ENERGY : 0)
| (nextFreeEnergyCalculationStep_ == step ? GMX_FORCE_DHDL : 0)
- | (nextNSStep_ == step ? GMX_FORCE_NS : 0));
-
- (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
- [this, step, time, flags]() { run(step, time, flags); }));
+ | (!doShellFC_ && nextNSStep_ == step ? GMX_FORCE_NS : 0));
+
+ (*registerRunFunction)(std::make_unique<SimulatorRunFunction>([this, step, time, flags]() {
+ if (doShellFC_)
+ {
+ run<true>(step, time, flags);
+ }
+ else
+ {
+ run<false>(step, time, flags);
+ }
+ }));
}
void ForceElement::elementSetup()
GMX_ASSERT(localTopology_, "Setup called before local topology was set.");
}
+template<bool doShellFC>
void ForceElement::run(Step step, Time time, unsigned int flags)
{
// Disabled functionality
- Awh* awh = nullptr;
- gmx_edsam* ed = nullptr;
- gmx_multisim_t* ms = nullptr;
- t_graph* graph = nullptr;
+ gmx_multisim_t* ms = nullptr;
+
if (!DOMAINDECOMP(cr_) && (flags & GMX_FORCE_NS) && inputrecDynamicBox(inputrec_))
{
// TODO: Correcting the box is done in DomDecHelper (if using DD) or here (non-DD simulations).
// Think about unifying this responsibility, could this be done in one place?
auto box = statePropagatorData_->box();
- correct_box(fplog_, step, box, graph);
+ correct_box(fplog_, step, box);
}
/* The coordinates (x) are shifted (to get whole molecules)
ArrayRef<real> lambda =
freeEnergyPerturbationElement_ ? freeEnergyPerturbationElement_->lambdaView() : lambda_;
- do_force(fplog_, cr_, ms, inputrec_, awh, enforcedRotation_, imdSession_, pull_work_, step,
- nrnb_, wcycle_, localTopology_, box, x, hist, forces, force_vir, mdAtoms_->mdatoms(),
- energyElement_->enerdata(), fcd_, lambda, graph, fr_, runScheduleWork_, vsite_,
- energyElement_->muTot(), time, ed, static_cast<int>(flags), ddBalanceRegionHandler_);
+ if (doShellFC)
+ {
+ auto v = statePropagatorData_->velocitiesView();
+
+ relax_shell_flexcon(
+ fplog_, cr_, ms, isVerbose_, enforcedRotation_, step, inputrec_, imdSession_,
+ pull_work_, step == nextNSStep_, static_cast<int>(flags), localTopology_, constr_,
+ energyElement_->enerdata(), fcd_, statePropagatorData_->localNumAtoms(), x, v, box,
+ lambda, hist, forces, force_vir, mdAtoms_->mdatoms(), nrnb_, wcycle_, shellfc_, fr_,
+ runScheduleWork_, time, energyElement_->muTot(), vsite_, ddBalanceRegionHandler_);
+ nShellRelaxationSteps_++;
+ }
+ else
+ {
+ // Disabled functionality
+ Awh* awh = nullptr;
+ gmx_edsam* ed = nullptr;
+
+ do_force(fplog_, cr_, ms, inputrec_, awh, enforcedRotation_, imdSession_, pull_work_, step,
+ nrnb_, wcycle_, localTopology_, box, x, hist, forces, force_vir, mdAtoms_->mdatoms(),
+ energyElement_->enerdata(), fcd_, lambda, fr_, runScheduleWork_, vsite_,
+ energyElement_->muTot(), time, ed, static_cast<int>(flags), ddBalanceRegionHandler_);
+ }
energyElement_->addToForceVirial(force_vir, step);
}
+void ForceElement::elementTeardown()
+{
+ if (doShellFC_)
+ {
+ done_shellfc(fplog_, shellfc_, nShellRelaxationSteps_);
+ }
+}
+
void ForceElement::setTopology(const gmx_localtop_t* top)
{
localTopology_ = top;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \libinternal \file
* \brief Declares the force element for the modular simulator
*
+ * This element calculates the forces, with or without shells or
+ * flexible constraints.
+ *
* \author Pascal Merz <pascal.merz@me.com>
* \ingroup module_modularsimulator
*/
#include "topologyholder.h"
struct gmx_enfrot;
+struct gmx_shellfc_t;
struct gmx_wallcycle;
struct pull_t;
struct t_fcdata;
* \ingroup module_modularsimulator
* \brief Force element
*
- * The force element manages the call to do_force(...)
+ * The force element manages the call to either
+ * do_force(...) or relax_shell_flexcon(...)
*/
class ForceElement final :
public ISimulatorElement,
ForceElement(StatePropagatorData* statePropagatorData,
EnergyElement* energyElement,
FreeEnergyPerturbationElement* freeEnergyPerturbationElement,
+ bool isVerbose,
bool isDynamicBox,
FILE* fplog,
const t_commrec* cr,
gmx_vsite_t* vsite,
ImdSession* imdSession,
pull_t* pull_work,
+ Constraints* constr,
+ const gmx_mtop_t* globalTopology,
gmx_enfrot* enforcedRotation);
/*! \brief Register force calculation for step / time
//! Check that we got the local topology
void elementSetup() override;
- //! No element teardown needed
- void elementTeardown() override {}
+ //! Print some final output
+ void elementTeardown() override;
private:
//! ITopologyHolderClient implementation
//! IEnergySignallerClient implementation
SignallerCallbackPtr registerEnergyCallback(EnergySignallerEvent event) override;
//! The actual do_force call
+ template<bool doShellFC>
void run(Step step, Time time, unsigned int flags);
+ //! The shell / FC helper struct
+ gmx_shellfc_t* shellfc_;
+ //! Whether shells or flexible constraints are present
+ const bool doShellFC_;
+
//! The next NS step
Step nextNSStep_;
//! The next energy calculation step
//! Whether we're having a dynamic box
const bool isDynamicBox_;
+ //! Whether we're being verbose
+ const bool isVerbose_;
+ //! The number of shell relaxation steps we did
+ Step nShellRelaxationSteps_;
//! DD / DLB helper object
const DDBalanceRegionHandler ddBalanceRegionHandler_;
t_fcdata* fcd_;
//! Schedule of work for each MD step for this task.
MdrunScheduleWorkload* runScheduleWork_;
+ //! Handles constraints.
+ Constraints* constr_;
//! Handles enforced rotation.
gmx_enfrot* enforcedRotation_;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/md_support.h"
#include "gromacs/mdlib/mdatoms.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
namespace gmx
#include "gromacs/domdec/domdec.h"
#include "gromacs/ewald/pme.h"
#include "gromacs/ewald/pme_load_balancing.h"
+#include "gromacs/ewald/pme_pp.h"
#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdrunutility/printtime.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/fcdata.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/observableshistory.h"
#include "gromacs/mdtypes/state.h"
#include "freeenergyperturbationelement.h"
#include "parrinellorahmanbarostat.h"
#include "propagator.h"
-#include "shellfcelement.h"
#include "signallers.h"
#include "statepropagatordata.h"
#include "trajectoryelement.h"
bool hasReadEkinState = MASTER(cr) ? state_global->ekinstate.hasReadEkinState : false;
if (PAR(cr))
{
- gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr);
+ gmx_bcast(sizeof(hasReadEkinState), &hasReadEkinState, cr->mpi_comm_mygroup);
}
if (hasReadEkinState)
{
{
const bool isVerbose = mdrunOptions.verbose;
const bool isDynamicBox = inputrecDynamicBox(inputrec);
- // Check for polarizable models and flexible constraints
- if (ShellFCElement::doShellsOrFlexConstraints(topologyHolder_->globalTopology(),
- constr ? constr->numFlexibleConstraints() : 0))
- {
- auto shellFCElement = std::make_unique<ShellFCElement>(
- statePropagatorDataPtr, energyElementPtr, freeEnergyPerturbationElement, isVerbose,
- isDynamicBox, fplog, cr, inputrec, mdAtoms, nrnb, fr, fcd, wcycle, runScheduleWork, vsite,
- imdSession, pull_work, constr, &topologyHolder_->globalTopology(), enforcedRotation);
- topologyHolder_->registerClient(shellFCElement.get());
- neighborSearchSignallerBuilder->registerSignallerClient(
- compat::make_not_null(shellFCElement.get()));
- energySignallerBuilder->registerSignallerClient(compat::make_not_null(shellFCElement.get()));
-
- // std::move *should* not be needed with c++-14, but clang-3.6 still requires it
- return std::move(shellFCElement);
- }
- else
- {
- auto forceElement = std::make_unique<ForceElement>(
- statePropagatorDataPtr, energyElementPtr, freeEnergyPerturbationElement,
- isDynamicBox, fplog, cr, inputrec, mdAtoms, nrnb, fr, fcd, wcycle, runScheduleWork,
- vsite, imdSession, pull_work, enforcedRotation);
- topologyHolder_->registerClient(forceElement.get());
- neighborSearchSignallerBuilder->registerSignallerClient(compat::make_not_null(forceElement.get()));
- energySignallerBuilder->registerSignallerClient(compat::make_not_null(forceElement.get()));
-
- // std::move *should* not be needed with c++-14, but clang-3.6 still requires it
- return std::move(forceElement);
- }
+
+ auto forceElement = std::make_unique<ForceElement>(
+ statePropagatorDataPtr, energyElementPtr, freeEnergyPerturbationElement, isVerbose,
+ isDynamicBox, fplog, cr, inputrec, mdAtoms, nrnb, fr, fcd, wcycle, runScheduleWork, vsite,
+ imdSession, pull_work, constr, &topologyHolder_->globalTopology(), enforcedRotation);
+ topologyHolder_->registerClient(forceElement.get());
+ neighborSearchSignallerBuilder->registerSignallerClient(compat::make_not_null(forceElement.get()));
+ energySignallerBuilder->registerSignallerClient(compat::make_not_null(forceElement.get()));
+
+ // std::move *should* not be needed with c++-14, but clang-3.6 still requires it
+ return std::move(forceElement);
}
std::unique_ptr<ISimulatorElement> ModularSimulator::buildIntegrator(
}
else if (inputrec->eI == eiVV)
{
- auto computeGlobalsElementAtFullTimeStep =
- std::make_unique<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerletAtFullTimeStep>>(
- statePropagatorDataPtr, energyElementPtr, freeEnergyPerturbationElementPtr,
- &signals_, nstglobalcomm_, fplog, mdlog, cr, inputrec, mdAtoms, nrnb,
- wcycle, fr, &topologyHolder_->globalTopology(), constr, hasReadEkinState);
- topologyHolder_->registerClient(computeGlobalsElementAtFullTimeStep.get());
- energySignallerBuilder->registerSignallerClient(
- compat::make_not_null(computeGlobalsElementAtFullTimeStep.get()));
- trajectoryElementBuilder->registerSignallerClient(
- compat::make_not_null(computeGlobalsElementAtFullTimeStep.get()));
-
- auto computeGlobalsElementAfterCoordinateUpdate =
- std::make_unique<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerletAfterCoordinateUpdate>>(
+ auto computeGlobalsElement =
+ std::make_unique<ComputeGlobalsElement<ComputeGlobalsAlgorithm::VelocityVerlet>>(
statePropagatorDataPtr, energyElementPtr, freeEnergyPerturbationElementPtr,
&signals_, nstglobalcomm_, fplog, mdlog, cr, inputrec, mdAtoms, nrnb,
wcycle, fr, &topologyHolder_->globalTopology(), constr, hasReadEkinState);
- topologyHolder_->registerClient(computeGlobalsElementAfterCoordinateUpdate.get());
- energySignallerBuilder->registerSignallerClient(
- compat::make_not_null(computeGlobalsElementAfterCoordinateUpdate.get()));
+ topologyHolder_->registerClient(computeGlobalsElement.get());
+ energySignallerBuilder->registerSignallerClient(compat::make_not_null(computeGlobalsElement.get()));
trajectoryElementBuilder->registerSignallerClient(
- compat::make_not_null(computeGlobalsElementAfterCoordinateUpdate.get()));
+ compat::make_not_null(computeGlobalsElement.get()));
*checkBondedInteractionsCallback =
- computeGlobalsElementAfterCoordinateUpdate->getCheckNumberOfBondedInteractionsCallback();
+ computeGlobalsElement->getCheckNumberOfBondedInteractionsCallback();
auto propagatorVelocities = std::make_unique<Propagator<IntegrationStep::VelocitiesOnly>>(
inputrec->delta_t * 0.5, statePropagatorDataPtr, mdAtoms, wcycle);
addToCallListAndMove(std::move(constraintElement), elementCallList, elementsOwnershipList);
}
- addToCallListAndMove(std::move(computeGlobalsElementAtFullTimeStep), elementCallList,
- elementsOwnershipList);
+ addToCallList(compat::make_not_null(computeGlobalsElement.get()), elementCallList);
addToCallList(statePropagatorDataPtr, elementCallList); // we have a full microstate at time t here!
if (inputrec->etc == etcVRESCALE)
{
addToCallListAndMove(std::move(constraintElement), elementCallList, elementsOwnershipList);
}
- addToCallListAndMove(std::move(computeGlobalsElementAfterCoordinateUpdate), elementCallList,
- elementsOwnershipList);
+ addToCallListAndMove(std::move(computeGlobalsElement), elementCallList, elementsOwnershipList);
addToCallList(energyElementPtr, elementCallList); // we have the energies at time t here!
if (prBarostat)
{
isInputCompatible
&& conditionalAssert(!doMembed,
"Membrane embedding is not supported by the modular simulator.");
- const bool useGraph = !areMoleculesDistributedOverPbc(*inputrec, globalTopology, MDLogger());
- isInputCompatible =
- isInputCompatible
- && conditionalAssert(!useGraph, "Graph is not supported by the modular simulator.");
// TODO: Change this to the boolean passed when we merge the user interface change for the GPU update.
isInputCompatible =
isInputCompatible
* the research papers on the package. Check out http://www.gromacs.org.
*/
/*! \libinternal \file
- * \brief Declares the modular simulator
+ * \brief Provides the modular simulator.
+ *
+ * Defines the ModularSimulator class. Provides checkUseModularSimulator() utility function
+ * to determine whether the ModularSimulator should be used.
*
* \author Pascal Merz <pascal.merz@me.com>
* \ingroup module_modularsimulator
//! \cond
//! Helper function to add elements or signallers to the call list via raw pointer
template<typename T, typename U>
+ static void addToCallList(U* element, std::vector<compat::not_null<T*>>& callList);
+ //! Helper function to add elements or signallers to the call list via non-null raw pointer
+ template<typename T, typename U>
static void addToCallList(compat::not_null<U*> element, std::vector<compat::not_null<T*>>& callList);
//! Helper function to add elements or signallers to the call list via smart pointer
template<typename T, typename U>
}
//! \cond
+template<typename T, typename U>
+void ModularSimulator::addToCallList(U* element, std::vector<compat::not_null<T*>>& callList)
+{
+ if (element)
+ {
+ callList.emplace_back(element);
+ }
+}
+
template<typename T, typename U>
void ModularSimulator::addToCallList(gmx::compat::not_null<U*> element,
std::vector<compat::not_null<T*>>& callList)
template<typename T, typename U>
void ModularSimulator::addToCallList(std::unique_ptr<U>& element, std::vector<compat::not_null<T*>>& callList)
{
- callList.emplace_back(compat::make_not_null(element.get()));
+ if (element)
+ {
+ callList.emplace_back(compat::make_not_null(element.get()));
+ }
}
template<typename T, typename U>
std::vector<compat::not_null<T*>>& callList,
std::vector<std::unique_ptr<T>>& elementList)
{
- callList.emplace_back(compat::make_not_null(element.get()));
- elementList.emplace_back(std::move(element));
+ if (element)
+ {
+ callList.emplace_back(compat::make_not_null(element.get()));
+ elementList.emplace_back(std::move(element));
+ }
}
//! \endcond
+/*!
+ * \brief Whether or not to use the ModularSimulator
+ *
+ * GMX_DISABLE_MODULAR_SIMULATOR environment variable allows to disable modular simulator for
+ * all uses.
+ *
+ * See ModularSimulator::isInputCompatible() for function signature.
+ *
+ * \ingroup module_modularsimulator
+ */
+template<typename... Ts>
+auto checkUseModularSimulator(Ts&&... args)
+ -> decltype(ModularSimulator::isInputCompatible(std::forward<Ts>(args)...))
+{
+ return ModularSimulator::isInputCompatible(std::forward<Ts>(args)...)
+ && getenv("GMX_DISABLE_MODULAR_SIMULATOR") == nullptr;
+}
+
} // namespace gmx
#endif // GROMACS_MODULARSIMULATOR_MODULARSIMULATOR_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/update.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/pbcutil/boxutilities.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/mdrunoptions.h"
#include "gromacs/mdtypes/state.h"
#include "gromacs/nbnxm/nbnxm.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/mdatoms.h"
#include "gromacs/mdlib/update.h"
+#include "gromacs/mdtypes/mdatom.h"
#include "gromacs/timing/wallcycle.h"
#include "gromacs/utility/fatalerror.h"
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2019,2020, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-/*! \internal \file
- * \brief Defines the shell / flex constraints element for the modular simulator
- *
- * \author Pascal Merz <pascal.merz@me.com>
- * \ingroup module_modularsimulator
- */
-
-#include "gmxpre.h"
-
-#include "shellfcelement.h"
-
-#include "gromacs/domdec/mdsetup.h"
-#include "gromacs/math/vectypes.h"
-#include "gromacs/mdlib/constr.h"
-#include "gromacs/mdlib/force.h"
-#include "gromacs/mdlib/force_flags.h"
-#include "gromacs/mdlib/mdatoms.h"
-#include "gromacs/mdrun/shellfc.h"
-#include "gromacs/mdtypes/inputrec.h"
-#include "gromacs/pbcutil/pbc.h"
-#include "gromacs/topology/atoms.h"
-#include "gromacs/topology/mtop_util.h"
-
-#include "energyelement.h"
-#include "freeenergyperturbationelement.h"
-#include "statepropagatordata.h"
-
-struct gmx_edsam;
-struct gmx_enfrot;
-struct gmx_multisim_t;
-class history_t;
-struct t_graph;
-
-namespace gmx
-{
-bool ShellFCElement::doShellsOrFlexConstraints(const gmx_mtop_t& mtop, int nflexcon)
-{
- if (nflexcon != 0)
- {
- return true;
- }
- std::array<int, eptNR> n = gmx_mtop_particletype_count(mtop);
- return n[eptShell] != 0;
-}
-
-ShellFCElement::ShellFCElement(StatePropagatorData* statePropagatorData,
- EnergyElement* energyElement,
- FreeEnergyPerturbationElement* freeEnergyPerturbationElement,
- bool isVerbose,
- bool isDynamicBox,
- FILE* fplog,
- const t_commrec* cr,
- const t_inputrec* inputrec,
- const MDAtoms* mdAtoms,
- t_nrnb* nrnb,
- t_forcerec* fr,
- t_fcdata* fcd,
- gmx_wallcycle* wcycle,
- MdrunScheduleWorkload* runScheduleWork,
- gmx_vsite_t* vsite,
- ImdSession* imdSession,
- pull_t* pull_work,
- Constraints* constr,
- const gmx_mtop_t* globalTopology,
- gmx_enfrot* enforcedRotation) :
- nextNSStep_(-1),
- nextEnergyCalculationStep_(-1),
- nextVirialCalculationStep_(-1),
- nextFreeEnergyCalculationStep_(-1),
- statePropagatorData_(statePropagatorData),
- energyElement_(energyElement),
- freeEnergyPerturbationElement_(freeEnergyPerturbationElement),
- localTopology_(nullptr),
- isDynamicBox_(isDynamicBox),
- isVerbose_(isVerbose),
- nSteps_(0),
- ddBalanceRegionHandler_(cr),
- fplog_(fplog),
- cr_(cr),
- inputrec_(inputrec),
- mdAtoms_(mdAtoms),
- nrnb_(nrnb),
- wcycle_(wcycle),
- fr_(fr),
- vsite_(vsite),
- imdSession_(imdSession),
- pull_work_(pull_work),
- fcd_(fcd),
- runScheduleWork_(runScheduleWork),
- constr_(constr),
- enforcedRotation_(enforcedRotation)
-{
- lambda_.fill(0);
-
- shellfc_ = init_shell_flexcon(fplog, globalTopology, constr_ ? constr_->numFlexibleConstraints() : 0,
- inputrec->nstcalcenergy, DOMAINDECOMP(cr));
-
- GMX_ASSERT(shellfc_, "ShellFCElement built, but init_shell_flexcon returned a nullptr");
-
- if (!DOMAINDECOMP(cr))
- {
- // This was done in mdAlgorithmsSetupAtomData(), but shellfc
- // won't be available outside this element.
- make_local_shells(cr, mdAtoms->mdatoms(), shellfc_);
- }
-}
-
-void ShellFCElement::scheduleTask(Step step, Time time, const RegisterRunFunctionPtr& registerRunFunction)
-{
- unsigned int flags =
- (GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES | (isDynamicBox_ ? GMX_FORCE_DYNAMICBOX : 0)
- | (nextVirialCalculationStep_ == step ? GMX_FORCE_VIRIAL : 0)
- | (nextEnergyCalculationStep_ == step ? GMX_FORCE_ENERGY : 0)
- | (nextFreeEnergyCalculationStep_ == step ? GMX_FORCE_DHDL : 0));
-
- const bool isNSStep = (step == nextNSStep_);
- (*registerRunFunction)(std::make_unique<SimulatorRunFunction>(
- [this, step, time, flags, isNSStep]() { run(step, time, isNSStep, flags); }));
- nSteps_++;
-}
-
-void ShellFCElement::elementSetup()
-{
- GMX_ASSERT(localTopology_, "Setup called before local topology was set.");
-}
-
-void ShellFCElement::run(Step step, Time time, bool isNSStep, unsigned int flags)
-{
- // Disabled functionality
- gmx_multisim_t* ms = nullptr;
- t_graph* graph = nullptr;
-
- if (!DOMAINDECOMP(cr_) && isNSStep && inputrecDynamicBox(inputrec_))
- {
- // TODO: Correcting the box is done in DomDecHelper (if using DD) or here (non-DD simulations).
- // Think about unifying this responsibility, could this be done in one place?
- auto box = statePropagatorData_->box();
- correct_box(fplog_, step, box, graph);
- }
-
- auto x = statePropagatorData_->positionsView();
- auto v = statePropagatorData_->velocitiesView();
- auto forces = statePropagatorData_->forcesView();
- auto box = statePropagatorData_->constBox();
- history_t* hist = nullptr; // disabled
-
- tensor force_vir = { { 0 } };
- // TODO: Make lambda const (needs some adjustments in lower force routines)
- ArrayRef<real> lambda =
- freeEnergyPerturbationElement_ ? freeEnergyPerturbationElement_->lambdaView() : lambda_;
- relax_shell_flexcon(fplog_, cr_, ms, isVerbose_, enforcedRotation_, step, inputrec_, imdSession_,
- pull_work_, isNSStep, static_cast<int>(flags), localTopology_, constr_,
- energyElement_->enerdata(), fcd_, statePropagatorData_->localNumAtoms(), x,
- v, box, lambda, hist, forces, force_vir, mdAtoms_->mdatoms(), nrnb_,
- wcycle_, graph, shellfc_, fr_, runScheduleWork_, time,
- energyElement_->muTot(), vsite_, ddBalanceRegionHandler_);
- energyElement_->addToForceVirial(force_vir, step);
-}
-
-void ShellFCElement::elementTeardown()
-{
- done_shellfc(fplog_, shellfc_, nSteps_);
-}
-
-void ShellFCElement::setTopology(const gmx_localtop_t* top)
-{
- localTopology_ = top;
-}
-
-SignallerCallbackPtr ShellFCElement::registerNSCallback()
-{
- return std::make_unique<SignallerCallback>(
- [this](Step step, Time gmx_unused time) { this->nextNSStep_ = step; });
-}
-
-SignallerCallbackPtr ShellFCElement::registerEnergyCallback(EnergySignallerEvent event)
-{
- if (event == EnergySignallerEvent::EnergyCalculationStep)
- {
- return std::make_unique<SignallerCallback>(
- [this](Step step, Time /*unused*/) { nextEnergyCalculationStep_ = step; });
- }
- if (event == EnergySignallerEvent::VirialCalculationStep)
- {
- return std::make_unique<SignallerCallback>(
- [this](Step step, Time /*unused*/) { nextVirialCalculationStep_ = step; });
- }
- if (event == EnergySignallerEvent::FreeEnergyCalculationStep)
- {
- return std::make_unique<SignallerCallback>(
- [this](Step step, Time /*unused*/) { nextFreeEnergyCalculationStep_ = step; });
- }
- return nullptr;
-}
-} // namespace gmx
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2019,2020, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-/*! \libinternal \file
- * \brief Declares the shell / flex constraints element for the modular simulator
- *
- * \author Pascal Merz <pascal.merz@me.com>
- * \ingroup module_modularsimulator
- */
-
-#ifndef GMX_MODULARSIMULATOR_SHELLFCELEMENT_H
-#define GMX_MODULARSIMULATOR_SHELLFCELEMENT_H
-
-#include <array>
-
-#include "gromacs/domdec/dlbtiming.h"
-#include "gromacs/mdtypes/md_enums.h"
-#include "gromacs/utility/real.h"
-
-#include "modularsimulatorinterfaces.h"
-#include "topologyholder.h"
-
-struct gmx_enfrot;
-struct gmx_shellfc_t;
-struct gmx_wallcycle;
-struct pull_t;
-struct t_fcdata;
-struct t_nrnb;
-
-namespace gmx
-{
-class Awh;
-class EnergyElement;
-class FreeEnergyPerturbationElement;
-class ImdSession;
-class MDAtoms;
-class MdrunScheduleWorkload;
-class StatePropagatorData;
-
-/*! \libinternal
- * \ingroup module_modularsimulator
- * \brief Shell & flex constraints element
- *
- * The ShellFCElement manages the call to relax_shell_flexcon(...)
- */
-class ShellFCElement final :
- public ISimulatorElement,
- public ITopologyHolderClient,
- public INeighborSearchSignallerClient,
- public IEnergySignallerClient
-{
-public:
- //! Constructor
- ShellFCElement(StatePropagatorData* statePropagatorData,
- EnergyElement* energyElement,
- FreeEnergyPerturbationElement* freeEnergyPerturbationElement,
- bool isVerbose,
- bool isDynamicBox,
- FILE* fplog,
- const t_commrec* cr,
- const t_inputrec* inputrec,
- const MDAtoms* mdAtoms,
- t_nrnb* nrnb,
- t_forcerec* fr,
- t_fcdata* fcd,
- gmx_wallcycle* wcycle,
- MdrunScheduleWorkload* runScheduleWork,
- gmx_vsite_t* vsite,
- ImdSession* imdSession,
- pull_t* pull_work,
- Constraints* constr,
- const gmx_mtop_t* globalTopology,
- gmx_enfrot* enforcedRotation);
-
- /*! \brief Register shell / flex constraint calculation for step / time
- *
- * @param step The step number
- * @param time The time
- * @param registerRunFunction Function allowing to register a run function
- */
- void scheduleTask(Step step, Time time, const RegisterRunFunctionPtr& registerRunFunction) override;
-
- //! Check that we got the local topology
- void elementSetup() override;
- //! Print some final output
- void elementTeardown() override;
-
- //! Whether either shells or flexible constraints are used
- static bool doShellsOrFlexConstraints(const gmx_mtop_t& mtop, int nflexcon);
-
-private:
- //! ITopologyHolderClient implementation
- void setTopology(const gmx_localtop_t* top) override;
- //! INeighborSearchSignallerClient implementation
- SignallerCallbackPtr registerNSCallback() override;
- //! IEnergySignallerClient implementation
- SignallerCallbackPtr registerEnergyCallback(EnergySignallerEvent event) override;
- //! The actual do_force call
- void run(Step step, Time time, bool isNSStep, unsigned int flags);
-
- //! The shell / FC helper struct
- gmx_shellfc_t* shellfc_;
-
- //! The next NS step
- Step nextNSStep_;
- //! The next energy calculation step
- Step nextEnergyCalculationStep_;
- //! The next energy calculation step
- Step nextVirialCalculationStep_;
- //! The next free energy calculation step
- Step nextFreeEnergyCalculationStep_;
-
- //! Pointer to the micro state
- StatePropagatorData* statePropagatorData_;
- //! Pointer to the energy element
- EnergyElement* energyElement_;
- //! The free energy perturbation element
- FreeEnergyPerturbationElement* freeEnergyPerturbationElement_;
-
- //! The local topology - updated by Topology via Client system
- const gmx_localtop_t* localTopology_;
-
- //! Whether we're having a dynamic box
- const bool isDynamicBox_;
- //! Whether we're being verbose
- const bool isVerbose_;
- //! The number of shell relaxation steps we did
- Step nSteps_;
-
- //! DD / DLB helper object
- const DDBalanceRegionHandler ddBalanceRegionHandler_;
-
- /* \brief The FEP lambda vector
- *
- * Used if FEP is off, since do_force
- * requires lambda to be allocated anyway
- */
- std::array<real, efptNR> lambda_;
-
- // Access to ISimulator data
- //! Handles logging.
- FILE* fplog_;
- //! Handles communication.
- const t_commrec* cr_;
- //! Contains user input mdp options.
- const t_inputrec* inputrec_;
- //! Atom parameters for this domain.
- const MDAtoms* mdAtoms_;
- //! Manages flop accounting.
- t_nrnb* nrnb_;
- //! Manages wall cycle accounting.
- gmx_wallcycle* wcycle_;
- //! Parameters for force calculations.
- t_forcerec* fr_;
- //! Handles virtual sites.
- gmx_vsite_t* vsite_;
- //! The Interactive Molecular Dynamics session.
- ImdSession* imdSession_;
- //! The pull work object.
- pull_t* pull_work_;
- //! Helper struct for force calculations.
- t_fcdata* fcd_;
- //! Schedule of work for each MD step for this task.
- MdrunScheduleWorkload* runScheduleWork_;
- //! Handles constraints.
- Constraints* constr_;
- //! Handles enforced rotation.
- gmx_enfrot* enforcedRotation_;
-};
-
-} // namespace gmx
-
-#endif // GMX_MODULARSIMULATOR_SHELLFCELEMENT_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
lastStep_(-1),
canMoleculesBeDistributedOverPBC_(canMoleculesBeDistributedOverPBC),
systemHasPeriodicMolecules_(inputrec->bPeriodicMols),
- pbcType_(inputrec->ePBC),
+ pbcType_(inputrec->pbcType),
topologyHolder_(topologyHolder),
lastPlannedStep_(inputrec->nsteps + inputrec->init_step),
writeFinalConfiguration_(writeFinalConfiguration),
return box_;
}
-const rvec* StatePropagatorData::constBox()
+const rvec* StatePropagatorData::constBox() const
{
return box_;
}
return previousBox_;
}
-const rvec* StatePropagatorData::constPreviousBox()
+const rvec* StatePropagatorData::constPreviousBox() const
{
return previousBox_;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "topologyholder.h"
struct gmx_mdoutf;
+enum class PbcType : int;
struct t_commrec;
struct t_inputrec;
class t_state;
//! Get pointer to box
rvec* box();
//! Get const pointer to box
- const rvec* constBox();
+ const rvec* constBox() const;
//! Get pointer to previous box
rvec* previousBox();
//! Get const pointer to previous box
- const rvec* constPreviousBox();
+ const rvec* constPreviousBox() const;
//! Get the local number of atoms
int localNumAtoms();
//! Whether system has molecules self-interacting through PBC (used for final output only)
const bool systemHasPeriodicMolecules_;
//! The PBC type (used for final output only)
- const int pbcType_;
+ const PbcType pbcType_;
//! Pointer to the topology (used for final output only)
const TopologyHolder* topologyHolder_;
//! The (planned) last step - determines whether final configuration is written (used for final output only)
Constraints* constr,
gmx_vsite_t* vsite) :
globalTopology_(globalTopology),
- localTopology_(std::make_unique<gmx_localtop_t>())
+ localTopology_(std::make_unique<gmx_localtop_t>(globalTopology.ffparams))
{
- if (DOMAINDECOMP(cr))
+ if (!DOMAINDECOMP(cr))
{
- dd_init_local_top(globalTopology, localTopology_.get());
- }
- else
- {
- t_graph* graph = nullptr;
// Generate and initialize new topology
// Note that most of the data needed for the constructor is used here -
// this function should probably be simplified sooner or later.
- mdAlgorithmsSetupAtomData(cr, inputrec, globalTopology, localTopology_.get(), fr, &graph,
+ // Note: Legacy mdrun resizes the force buffer in mdAlgorithmsSetupAtomData()
+ // TopologyHolder has no access to the forces, so we are passing a nullptr
+ // TODO: Find a unique approach to resizing the forces in modular simulator (#3461)
+ mdAlgorithmsSetupAtomData(cr, inputrec, globalTopology, localTopology_.get(), fr, nullptr,
mdAtoms, constr, vsite, nullptr);
- GMX_RELEASE_ASSERT(graph == nullptr, "Graph is not implemented for the modular simulator.");
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::IMDOutputProvider* outputProvider,
const MdModulesNotifier& mdModulesNotifier,
const t_inputrec* inputrec,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
const gmx_output_env_t* oenv,
gmx_wallcycle* wcycle,
StartingBehavior startingBehavior,
IMDOutputProvider* outputProvider,
const MdModulesNotifier& mdModulesNotifier,
const t_inputrec* inputrec,
- gmx_mtop_t* top_global,
+ const gmx_mtop_t* top_global,
const gmx_output_env_t* oenv,
gmx_wallcycle* wcycle,
StartingBehavior startingBehavior,
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-file(GLOB NBNXM_SOURCES kernels_reference/*.cpp kernels_simd_4xm/*.cpp kernels_simd_2xmm/*.cpp *.cpp benchmark/*.cpp)
+add_subdirectory(kernels_simd_4xm)
+add_subdirectory(kernels_simd_2xmm)
+
+file (GLOB NBNXM_SOURCES
+ # Source files
+ atomdata.cpp
+ grid.cpp
+ gridset.cpp
+ kernel_common.cpp
+ kerneldispatch.cpp
+ nbnxm.cpp
+ nbnxm_geometry.cpp
+ nbnxm_setup.cpp
+ pairlist.cpp
+ pairlistparams.cpp
+ pairlistset.cpp
+ pairlist_tuning.cpp
+ pairsearch.cpp
+ prunekerneldispatch.cpp
+ # Reference kernel source files
+ kernels_reference/kernel_gpu_ref.cpp
+ kernels_reference/kernel_ref.cpp
+ kernels_reference/kernel_ref_prune.cpp
+ # Benchmark source files
+ # TODO these should not be in libgromacs
+ benchmark/bench_setup.cpp
+ benchmark/bench_system.cpp
+ )
if(GMX_USE_CUDA)
add_subdirectory(cuda)
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "grid.h"
#include "gridset.h"
#include "nbnxm_geometry.h"
+#include "nbnxm_gpu.h"
#include "pairlist.h"
using namespace gmx; // TODO: Remove when this file is moved into gmx namespace
const Nbnxm::KernelType kernelType,
int enbnxninitcombrule,
int ntype,
- const real* nbfp,
+ ArrayRef<const real> nbfp,
int n_energygroups)
{
real c6, c12, tol;
const Nbnxm::KernelType kernelType,
int enbnxninitcombrule,
int ntype,
- const real* nbfp,
+ ArrayRef<const real> nbfp,
int n_energygroups,
int nout)
{
void nbnxn_atomdata_x_to_nbat_x_gpu(const Nbnxm::GridSet& gridSet,
const gmx::AtomLocality locality,
bool fillLocal,
- gmx_nbnxn_gpu_t* gpu_nbv,
- DeviceBuffer<float> d_x,
+ NbnxmGpu* gpu_nbv,
+ DeviceBuffer<RVec> d_x,
GpuEventSynchronizer* xReadyOnDevice)
{
/* wait on partner thread - replaces full barrier */
int sync_th, sync_group_size;
- tMPI_Atomic_memory_barrier(); /* gurantee data is saved before marking work as done */
+# if defined(__clang__)
+ // Suppress warnings that the use of memory_barrier may be excessive
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Watomic-implicit-seq-cst"
+# endif
+
+ tMPI_Atomic_memory_barrier(); /* guarantee data is saved before marking work as done */
tMPI_Atomic_set(&(nbat->syncStep[th]), group_size / 2); /* mark previous step as completed */
/* find thread to sync with. Equal to partner_th unless nth is not a power of two. */
/* guarantee that no later load happens before wait loop is finisehd */
tMPI_Atomic_memory_barrier();
}
+# if defined(__clang__)
+# pragma clang diagnostic pop
+# endif
#else /* TMPI_ATOMICS */
# pragma omp barrier
#endif
/* Add the force array(s) from nbnxn_atomdata_t to f */
void reduceForcesGpu(const gmx::AtomLocality locality,
- DeviceBuffer<float> totalForcesDevice,
+ DeviceBuffer<RVec> totalForcesDevice,
const Nbnxm::GridSet& gridSet,
void* pmeForcesDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
- gmx_nbnxn_gpu_t* gpu_nbv,
+ NbnxmGpu* gpu_nbv,
bool useGpuFPmeReduction,
bool accumulateForce)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \libinternal \file
+ * \brief
+ * Functionality for per-atom data in the nbnxm module
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ * \inlibraryapi
+ */
+
#ifndef GMX_NBNXN_ATOMDATA_H
#define GMX_NBNXN_ATOMDATA_H
#include "gromacs/utility/bitmask.h"
#include "gromacs/utility/real.h"
-#include "gpu_types.h"
-
namespace gmx
{
class MDLogger;
}
+struct NbnxmGpu;
struct nbnxn_atomdata_t;
struct nonbonded_verlet_t;
struct t_mdatoms;
enum class KernelType;
} // namespace Nbnxm
-/* Convenience type for vector with aligned memory */
+//! Convenience type for vector with aligned memory
template<typename T>
using AlignedVector = std::vector<T, gmx::AlignedAllocator<T>>;
return DIM * (a & ~(packSize - 1)) + (a & (packSize - 1));
}
-// Struct that holds force and energy output buffers
+/*! \internal
+ * \brief Struct that holds force and energy output buffers */
struct nbnxn_atomdata_output_t
{
- /* Constructor
+ /*! \brief Constructor
*
* \param[in] kernelType Type of non-bonded kernel
* \param[in] numEnergyGroups The number of energy groups
*/
nbnxn_atomdata_output_t(Nbnxm::KernelType kernelType,
int numEnergyGroups,
- int simdEnergyBUfferStride,
+ int simdEnergyBufferStride,
gmx::PinningPolicy pinningPolicy);
- gmx::HostVector<real> f; // f, size natoms*fstride
- gmx::HostVector<real> fshift; // Shift force array, size SHIFTS*DIM
- gmx::HostVector<real> Vvdw; // Temporary Van der Waals group energy storage
- gmx::HostVector<real> Vc; // Temporary Coulomb group energy storage
- AlignedVector<real> VSvdw; // Temporary SIMD Van der Waals group energy storage
- AlignedVector<real> VSc; // Temporary SIMD Coulomb group energy storage
+ //! f, size natoms*fstride
+ gmx::HostVector<real> f;
+ //! Shift force array, size SHIFTS*DIM
+ gmx::HostVector<real> fshift;
+ //! Temporary Van der Waals group energy storage
+ gmx::HostVector<real> Vvdw;
+ //! Temporary Coulomb group energy storage
+ gmx::HostVector<real> Vc;
+ //! Temporary SIMD Van der Waals group energy storage
+ AlignedVector<real> VSvdw;
+ //! Temporary SIMD Coulomb group energy storage
+ AlignedVector<real> VSc;
};
-/* Block size in atoms for the non-bonded thread force-buffer reduction,
- * should be a multiple of all cell and x86 SIMD sizes (i.e. 2, 4 and 8).
+/*! \brief Block size in atoms for the non-bonded thread force-buffer reduction.
+ *
+ * Should be a multiple of all cell and x86 SIMD sizes (i.e. 2, 4 and 8).
* Should be small to reduce the reduction and zeroing cost,
* but too small will result in overhead.
* Currently the block size is NBNXN_BUFFERFLAG_SIZE*3*sizeof(real)=192 bytes.
# define NBNXN_BUFFERFLAG_SIZE 16
#endif
-/* We store the reduction flags as gmx_bitmask_t.
+/*! \brief We store the reduction flags as gmx_bitmask_t.
* This limits the number of flags to BITMASK_SIZE.
*/
#define NBNXN_BUFFERFLAG_MAX_THREADS (BITMASK_SIZE)
-/* Flags for telling if threads write to force output buffers */
+/*! \internal
+ * \brief Flags for telling if threads write to force output buffers */
typedef struct
{
- int nflag; /* The number of flag blocks */
- gmx_bitmask_t* flag; /* Bit i is set when thread i writes to a cell-block */
- int flag_nalloc; /* Allocation size of cxy_flag */
+ //! The number of flag blocks
+ int nflag;
+ //! Bit i is set when thread i writes to a cell-block
+ gmx_bitmask_t* flag;
+ //! Allocation size of cxy_flag
+ int flag_nalloc;
} nbnxn_buffer_flags_t;
-/* LJ combination rules: geometric, Lorentz-Berthelot, none */
+/*! \brief LJ combination rules: geometric, Lorentz-Berthelot, none */
enum
{
ljcrGEOM,
ljcrNR
};
-/* Struct that stores atom related data for the nbnxn module
+/*! \internal
+ * \brief Struct that stores atom related data for the nbnxn module
*
* Note: performance would improve slightly when all std::vector containers
* in this struct would not initialize during resize().
*/
struct nbnxn_atomdata_t
{ //NOLINT(clang-analyzer-optin.performance.Padding)
+ /*! \internal
+ * \brief The actual atom data parameter values */
struct Params
{
- /* Constructor
+ /*! \brief Constructor
*
* \param[in] pinningPolicy Sets the pinning policy for all data that might be transfered to a GPU
*/
Params(gmx::PinningPolicy pinningPolicy);
- // The number of different atom types
+ //! The number of different atom types
int numTypes;
- // Lennard-Jone 6*C6 and 12*C12 parameters, size numTypes*2*2
+ //! Lennard-Jone 6*C6 and 12*C12 parameters, size numTypes*2*2
gmx::HostVector<real> nbfp;
- // Combination rule, see enum defined above
+ //! Combination rule, see enum defined above
int comb_rule;
- // LJ parameters per atom type, size numTypes*2
+ //! LJ parameters per atom type, size numTypes*2
gmx::HostVector<real> nbfp_comb;
- // As nbfp, but with a stride for the present SIMD architecture
+ //! As nbfp, but with a stride for the present SIMD architecture
AlignedVector<real> nbfp_aligned;
- // Atom types per atom
+ //! Atom types per atom
gmx::HostVector<int> type;
- // LJ parameters per atom for fast SIMD loading
+ //! LJ parameters per atom for fast SIMD loading
gmx::HostVector<real> lj_comb;
- // Charges per atom, not set with format nbatXYZQ
+ //! Charges per atom, not set with format nbatXYZQ
gmx::HostVector<real> q;
- // The number of energy groups
+ //! The number of energy groups
int nenergrp;
- // 2log(nenergrp)
+ //! 2log(nenergrp)
int neg_2log;
- // The energy groups, one int entry per cluster, only set when needed
+ //! The energy groups, one int entry per cluster, only set when needed
gmx::HostVector<int> energrp;
};
- // Diagonal and topology exclusion helper data for all SIMD kernels
+ /*! \internal
+ * \brief Diagonal and topology exclusion helper data for all SIMD kernels. */
struct SimdMasks
{
SimdMasks();
- // Helper data for setting up diagonal exclusion masks in the SIMD 4xN kernels
+ //! Helper data for setting up diagonal exclusion masks in the SIMD 4xN kernels
AlignedVector<real> diagonal_4xn_j_minus_i;
- // Helper data for setting up diaginal exclusion masks in the SIMD 2xNN kernels
+ //! Helper data for setting up diaginal exclusion masks in the SIMD 2xNN kernels
AlignedVector<real> diagonal_2xnn_j_minus_i;
- // Filters for topology exclusion masks for the SIMD kernels
+ //! Filters for topology exclusion masks for the SIMD kernels
AlignedVector<uint32_t> exclusion_filter;
- // Filters for topology exclusion masks for double SIMD kernels without SIMD int32 logical support
+ //! Filters for topology exclusion masks for double SIMD kernels without SIMD int32 logical support
AlignedVector<uint64_t> exclusion_filter64;
- // Array of masks needed for exclusions
+ //! Array of masks needed for exclusions
AlignedVector<real> interaction_array;
};
- /* Constructor
+ /*! \brief Constructor
*
* \param[in] pinningPolicy Sets the pinning policy for all data that might be transfered to a GPU
*/
nbnxn_atomdata_t(gmx::PinningPolicy pinningPolicy);
- /* Returns a const reference to the parameters */
+ //! Returns a const reference to the parameters
const Params& params() const { return params_; }
- /* Returns a non-const reference to the parameters */
+ //! Returns a non-const reference to the parameters
Params& paramsDeprecated() { return params_; }
- /* Returns the current total number of atoms stored */
+ //! Returns the current total number of atoms stored
int numAtoms() const { return numAtoms_; }
- /* Return the coordinate buffer, and q with xFormat==nbatXYZQ */
+ //! Return the coordinate buffer, and q with xFormat==nbatXYZQ
gmx::ArrayRef<const real> x() const { return x_; }
- /* Return the coordinate buffer, and q with xFormat==nbatXYZQ */
+ //! Return the coordinate buffer, and q with xFormat==nbatXYZQ
gmx::ArrayRef<real> x() { return x_; }
- /* Resizes the coordinate buffer and sets the number of atoms */
+ //! Resizes the coordinate buffer and sets the number of atoms
void resizeCoordinateBuffer(int numAtoms);
- /* Resizes the force buffers for the current number of atoms */
+ //! Resizes the force buffers for the current number of atoms
void resizeForceBuffers();
private:
- // The LJ and charge parameters
+ //! The LJ and charge parameters
Params params_;
- // The total number of atoms currently stored
+ //! The total number of atoms currently stored
int numAtoms_;
public:
- int natoms_local; /* Number of local atoms */
- int XFormat; /* The format of x (and q), enum */
- int FFormat; /* The format of f, enum */
- gmx_bool bDynamicBox; /* Do we need to update shift_vec every step? */
- gmx::HostVector<gmx::RVec> shift_vec; /* Shift vectors, copied from t_forcerec */
- int xstride; /* stride for a coordinate in x (usually 3 or 4) */
- int fstride; /* stride for a coordinate in f (usually 3 or 4) */
+ //! Number of local atoms
+ int natoms_local;
+ //! The format of x (and q), enum
+ int XFormat;
+ //! The format of f, enum
+ int FFormat;
+ //! Do we need to update shift_vec every step?
+ gmx_bool bDynamicBox;
+ //! Shift vectors, copied from t_forcerec
+ gmx::HostVector<gmx::RVec> shift_vec;
+ //! stride for a coordinate in x (usually 3 or 4)
+ int xstride;
+ //! stride for a coordinate in f (usually 3 or 4)
+ int fstride;
+
private:
- gmx::HostVector<real> x_; /* x and possibly q, size natoms*xstride */
+ //! x and possibly q, size natoms*xstride
+ gmx::HostVector<real> x_;
public:
- // Masks for handling exclusions in the SIMD kernels
+ //! Masks for handling exclusions in the SIMD kernels
const SimdMasks simdMasks;
- /* Output data */
- std::vector<nbnxn_atomdata_output_t> out; /* Output data structures, 1 per thread */
-
- /* Reduction related data */
- gmx_bool bUseBufferFlags; /* Use the flags or operate on all atoms */
- nbnxn_buffer_flags_t buffer_flags; /* Flags for buffer zeroing+reduc. */
- gmx_bool bUseTreeReduce; /* Use tree for force reduction */
- tMPI_Atomic* syncStep; /* Synchronization step for tree reduce */
+ //! Output data structures, 1 per thread
+ std::vector<nbnxn_atomdata_output_t> out;
+
+ //! Reduction related data
+ //! \{
+ //! Use the flags or operate on all atoms
+ gmx_bool bUseBufferFlags;
+ //! Flags for buffer zeroing+reduc.
+ nbnxn_buffer_flags_t buffer_flags;
+ //! Use tree for force reduction
+ gmx_bool bUseTreeReduce;
+ //! Synchronization step for tree reduce
+ tMPI_Atomic* syncStep;
+ //! \}
};
-/* Copy na rvec elements from x to xnb using nbatFormat, start dest a0,
+/*! \brief Copy na rvec elements from x to xnb using nbatFormat, start dest a0,
* and fills up to na_round with coordinates that are far away.
*/
void copy_rvec_to_nbat_real(const int* a, int na, int na_round, const rvec* x, int nbatFormat, real* xnb, int a0);
+//! Describes the combination rule in use by this force field
enum
{
enbnxninitcombruleDETECT,
enbnxninitcombruleNONE
};
-/* Initialize the non-bonded atom data structure.
+/*! \brief Initialize the non-bonded atom data structure.
+ *
* The enum for nbatXFormat is in the file defining nbnxn_atomdata_t.
* Copy the ntypes*ntypes*2 sized nbfp non-bonded parameter list
* to the atom data structure.
* enbnxninitcombrule sets what combination rule data gets stored in nbat.
*/
-void nbnxn_atomdata_init(const gmx::MDLogger& mdlog,
- nbnxn_atomdata_t* nbat,
- Nbnxm::KernelType kernelType,
- int enbnxninitcombrule,
- int ntype,
- const real* nbfp,
- int n_energygroups,
- int nout);
-
+void nbnxn_atomdata_init(const gmx::MDLogger& mdlog,
+ nbnxn_atomdata_t* nbat,
+ Nbnxm::KernelType kernelType,
+ int enbnxninitcombrule,
+ int ntype,
+ gmx::ArrayRef<const real> nbfp,
+ int n_energygroups,
+ int nout);
+
+//! Sets the atomdata after pair search
void nbnxn_atomdata_set(nbnxn_atomdata_t* nbat,
const Nbnxm::GridSet& gridSet,
const t_mdatoms* mdatoms,
const int* atinfo);
-/* Copy the shift vectors to nbat */
+//! Copy the shift vectors to nbat
void nbnxn_atomdata_copy_shiftvec(gmx_bool dynamic_box, rvec* shift_vec, nbnxn_atomdata_t* nbat);
/*! \brief Transform coordinates to xbat layout
* \param[in] d_x Coordinates to be copied (in plain rvec format).
* \param[in] xReadyOnDevice Event synchronizer indicating that the coordinates are ready in the device memory.
*/
-void nbnxn_atomdata_x_to_nbat_x_gpu(const Nbnxm::GridSet& gridSet,
- gmx::AtomLocality locality,
- bool fillLocal,
- gmx_nbnxn_gpu_t* gpu_nbv,
- DeviceBuffer<float> d_x,
- GpuEventSynchronizer* xReadyOnDevice);
+void nbnxn_atomdata_x_to_nbat_x_gpu(const Nbnxm::GridSet& gridSet,
+ gmx::AtomLocality locality,
+ bool fillLocal,
+ NbnxmGpu* gpu_nbv,
+ DeviceBuffer<gmx::RVec> d_x,
+ GpuEventSynchronizer* xReadyOnDevice);
/*! \brief Add the computed forces to \p f, an internal reduction might be performed as well
*
* \param[in] accumulateForce Whether there are usefull data already in the total force buffer.
*/
void reduceForcesGpu(gmx::AtomLocality locality,
- DeviceBuffer<float> totalForcesDevice,
+ DeviceBuffer<gmx::RVec> totalForcesDevice,
const Nbnxm::GridSet& gridSet,
void* pmeForcesDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
- gmx_nbnxn_gpu_t* gpu_nbv,
+ NbnxmGpu* gpu_nbv,
bool useGpuFPmeReduction,
bool accumulateForce);
-/* Add the fshift force stored in nbat to fshift */
+//! Add the fshift force stored in nbat to fshift
void nbnxn_atomdata_add_nbat_fshift_to_fshift(const nbnxn_atomdata_t& nbat, gmx::ArrayRef<gmx::RVec> fshift);
-/* Get the atom start index and number of atoms for a given locality */
+//! Get the atom start index and number of atoms for a given locality
void nbnxn_get_atom_range(gmx::AtomLocality atomLocality,
const Nbnxm::GridSet& gridSet,
int* atomStart,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "bench_setup.h"
-#include "gromacs/compat/optional.h"
+#include <optional>
+
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/mdlib/dispersioncorrection.h"
#include "gromacs/mdlib/force_flags.h"
*
* Returns an error string when the kernel is not available.
*/
-static gmx::compat::optional<std::string> checkKernelSetup(const KernelBenchOptions& options)
+static std::optional<std::string> checkKernelSetup(const KernelBenchOptions& options)
{
GMX_RELEASE_ASSERT(options.nbnxmSimd < BenchMarkKernels::Count
&& options.nbnxmSimd != BenchMarkKernels::SimdAuto,
GMX_RELEASE_ASSERT(options.ewaldcoeff_q > 0, "Ewald coefficient should be > 0");
ic.ewaldcoeff_q = options.ewaldcoeff_q;
ic.coulombEwaldTables = std::make_unique<EwaldCorrectionTables>();
- init_interaction_const_tables(nullptr, &ic);
+ init_interaction_const_tables(nullptr, &ic, 0);
}
return ic;
PairlistParams pairlistParams(kernelSetup.kernelType, false, options.pairlistCutoff, false);
- GridSet gridSet(epbcXYZ, false, nullptr, nullptr, pairlistParams.pairlistType, false,
+ GridSet gridSet(PbcType::Xyz, false, nullptr, nullptr, pairlistParams.pairlistType, false,
numThreads, pinPolicy);
auto pairlistSets = std::make_unique<PairlistSets>(pairlistParams, false, 0);
- auto pairSearch = std::make_unique<PairSearch>(
- epbcXYZ, false, nullptr, nullptr, pairlistParams.pairlistType, false, numThreads, pinPolicy);
+ auto pairSearch =
+ std::make_unique<PairSearch>(PbcType::Xyz, false, nullptr, nullptr,
+ pairlistParams.pairlistType, false, numThreads, pinPolicy);
auto atomData = std::make_unique<nbnxn_atomdata_t>(pinPolicy);
std::move(atomData), kernelSetup, nullptr, nullptr);
nbnxn_atomdata_init(gmx::MDLogger(), nbv->nbat.get(), kernelSetup.kernelType, combinationRule,
- system.numAtomTypes, system.nonbondedParameters.data(), 1, numThreads);
+ system.numAtomTypes, system.nonbondedParameters, 1, numThreads);
t_nrnb nrnb;
{ 0, int(system.coordinates.size()) }, atomDensity, atomInfo,
system.coordinates, 0, nullptr);
- nbv->constructPairlist(gmx::InteractionLocality::Local, &system.excls, 0, &nrnb);
+ nbv->constructPairlist(gmx::InteractionLocality::Local, system.excls, 0, &nrnb);
t_mdatoms mdatoms;
// We only use (read) the atom type and charge from mdatoms
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "bench_system.h"
+#include <numeric>
#include <vector>
#include "gromacs/math/vec.h"
nonbondedParameters[1] = c12Oxygen;
generateCoordinates(multiplicationFactor, &coordinates, box);
- put_atoms_in_box(epbcXYZ, box, coordinates);
+ put_atoms_in_box(PbcType::Xyz, box, coordinates);
int numAtoms = coordinates.size();
GMX_RELEASE_ASSERT(numAtoms % numAtomsInMolecule == 0,
charges.resize(numAtoms);
atomInfoAllVdw.resize(numAtoms);
atomInfoOxygenVdw.resize(numAtoms);
- snew(excls.index, numAtoms + 1);
- snew(excls.a, numAtoms * numAtomsInMolecule);
- excls.index[0] = 0;
for (int a = 0; a < numAtoms; a++)
{
SET_CGINFO_HAS_Q(atomInfoAllVdw[a]);
SET_CGINFO_HAS_Q(atomInfoOxygenVdw[a]);
- const int firstAtomInMolecule = a - (a % numAtomsInMolecule);
- for (int aj = 0; aj < numAtomsInMolecule; aj++)
- {
- excls.a[a * numAtomsInMolecule + aj] = firstAtomInMolecule + aj;
- }
- excls.index[a + 1] = (a + 1) * numAtomsInMolecule;
+ excls.pushBackListOfSize(numAtomsInMolecule);
+ gmx::ArrayRef<int> exclusionsForAtom = excls.back();
+ const int firstAtomInMolecule = a - (a % numAtomsInMolecule);
+ std::iota(exclusionsForAtom.begin(), exclusionsForAtom.end(), firstAtomInMolecule);
}
forceRec.ntype = numAtomTypes;
- forceRec.nbfp = nonbondedParameters.data();
+ forceRec.nbfp = nonbondedParameters;
snew(forceRec.shift_vec, SHIFTS);
calc_shifts(box, forceRec.shift_vec);
}
#include "gromacs/math/vectypes.h"
#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/topology/block.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
namespace gmx
//! Atom info where only oxygen atoms are marked to have Van der Waals interactions
std::vector<int> atomInfoOxygenVdw;
//! Information about exclusions.
- t_blocka excls;
+ ListOfLists<int> excls;
//! Storage for atom positions.
std::vector<gmx::RVec> coordinates;
//! System simulation box.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* the research papers on the package. Check out http://www.gromacs.org.
*/
-/*! \internal \file
+/*! \file
+ * \internal
*
* \brief Declares constants and helper functions used when handling
* bounding boxes for clusters of particles.
#ifndef DOXYGEN
-/* Bounding box calculations are (currently) always in single precision, so
+/*! \brief Bounding box calculations are (currently) always in single precision, so
* we only need to check for single precision support here.
* This uses less (cache-)memory and SIMD is faster, at least on x86.
*/
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_NBNXM_CLUSTERDISTANCEKERNELTYPE_H
#define GMX_NBNXM_CLUSTERDISTANCEKERNELTYPE_H
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/simd/simd.h"
#include "gromacs/utility/gmxassert.h"
-#include "atomdata.h"
#include "pairlistparams.h"
//! The types of kernel for calculating the distance between pairs of atom clusters
+++ /dev/null
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
- * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
- * and including many others, as listed in the AUTHORS file in the
- * top-level source directory and at http://www.gromacs.org.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version at http://www.gromacs.org.
- *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org.
- */
-
-#ifndef GMX_NBNXN_CONSTANTS_H
-#define GMX_NBNXN_CONSTANTS_H
-
-// Lower limit for square interaction distances in nonbonded kernels.
-// For smaller values we will overflow when calculating r^-1 or r^-12, but
-// to keep it simple we always apply the limit from the tougher r^-12 condition.
-#if GMX_DOUBLE
-// Some double precision SIMD architectures use single precision in the first
-// step, so although the double precision criterion would allow smaller rsq,
-// we need to stay in single precision with some margin for the N-R iterations.
-# define NBNXN_MIN_RSQ 1.0e-36
-#else
-// The worst intermediate value we might evaluate is r^-12, which
-// means we should ensure r^2 stays above pow(GMX_FLOAT_MAX,-1.0/6.0)*1.01 (some margin)
-# define NBNXN_MIN_RSQ 3.82e-07f // r > 6.2e-4
-#endif
-
-
-/* The number of clusters in a super-cluster, used for GPU */
-#define c_nbnxnGpuNumClusterPerSupercluster 8
-
-/* With GPU kernels we group cluster pairs in 4 to optimize memory usage
- * of integers containing 32 bits.
- */
-#define c_nbnxnGpuJgroupSize (32 / c_nbnxnGpuNumClusterPerSupercluster)
-
-#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief CUDA kernel for transforming position coordinates from rvec to nbnxm layout.
*
* TODO:
- * - improve/simplify/document use of cxy_na and na_round
* - rename kernel so naming matches with the other NBNXM kernels;
* - enable separate compilation unit
* \param[in] numColumns Extent of cell-level parallelism.
* \param[out] gm_xq Coordinates buffer in nbnxm layout.
- * \param[in] setFillerCoords Whether to set the coordinates of the filler particles.
+ * \tparam setFillerCoords Whether to set the coordinates of the filler particles.
* \param[in] gm_x Coordinates buffer.
* \param[in] gm_atomIndex Atom index mapping.
* \param[in] gm_numAtoms Array of number of atoms.
* \param[in] gm_cellIndex Array of cell indices.
- * \param[in] cellOffset Airst cell.
+ * \param[in] cellOffset First cell.
* \param[in] numAtomsPerCell Number of atoms per cell.
*/
+template<bool setFillerCoords>
static __global__ void nbnxn_gpu_x_to_nbat_x_kernel(int numColumns,
float4* __restrict__ gm_xq,
- bool setFillerCoords,
const float3* __restrict__ gm_x,
const int* __restrict__ gm_atomIndex,
const int* __restrict__ gm_numAtoms,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "nbnxm_cuda.h"
-#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
+#include "gromacs/gpu_utils/typecasts.cuh"
#include "gromacs/gpu_utils/vectype_ops.cuh"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/nbnxm/atomdata.h"
/*********************************/
/*! Returns the number of blocks to be used for the nonbonded GPU kernel. */
-static inline int calc_nb_kernel_nblock(int nwork_units, const gmx_device_info_t* dinfo)
+static inline int calc_nb_kernel_nblock(int nwork_units, const DeviceInformation* deviceInfo)
{
int max_grid_x_size;
- assert(dinfo);
+ assert(deviceInfo);
/* CUDA does not accept grid dimension of 0 (which can happen e.g. with an
empty domain) and that case should be handled before this point. */
assert(nwork_units > 0);
- max_grid_x_size = dinfo->prop.maxGridSize[0];
+ max_grid_x_size = deviceInfo->prop.maxGridSize[0];
/* do we exceed the grid x dimension limit? */
if (nwork_units > max_grid_x_size)
int evdwtype,
bool bDoEne,
bool bDoPrune,
- const gmx_device_info_t gmx_unused* devInfo)
+ const DeviceInformation gmx_unused* deviceInfo)
{
nbnxn_cu_kfunc_ptr_t res;
/* assert assumptions made by the kernels */
GMX_ASSERT(c_nbnxnGpuClusterSize * c_nbnxnGpuClusterSize / c_nbnxnGpuClusterpairSplit
- == devInfo->prop.warpSize,
+ == deviceInfo->prop.warpSize,
"The CUDA kernels require the "
"cluster_size_i*cluster_size_j/nbnxn_gpu_clusterpair_split to match the warp size "
"of the architecture targeted.");
/*! \brief Calculates the amount of shared memory required by the nonbonded kernel in use. */
static inline int calc_shmem_required_nonbonded(const int num_threads_z,
- const gmx_device_info_t gmx_unused* dinfo,
+ const DeviceInformation gmx_unused* deviceInfo,
const cu_nbparam_t* nbp)
{
int shmem;
- assert(dinfo);
+ assert(deviceInfo);
/* size of shmem (force-buffers/xq/atom type preloading) */
/* NOTE: with the default kernel on sm3.0 we need shmem only for pre-loading */
/* i-atom x+q in shared memory */
- shmem = c_numClPerSupercl * c_clSize * sizeof(float4);
+ shmem = c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(float4);
/* cj in shared memory, for each warp separately */
shmem += num_threads_z * c_nbnxnGpuClusterpairSplit * c_nbnxnGpuJgroupSize * sizeof(int);
if (nbp->vdwtype == evdwCuCUTCOMBGEOM || nbp->vdwtype == evdwCuCUTCOMBLB)
{
/* i-atom LJ combination parameters in shared memory */
- shmem += c_numClPerSupercl * c_clSize * sizeof(float2);
+ shmem += c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(float2);
}
else
{
/* i-atom types in shared memory */
- shmem += c_numClPerSupercl * c_clSize * sizeof(int);
+ shmem += c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(int);
}
return shmem;
* the local, this function records the event if called with the local stream as
* argument and inserts in the GPU stream a wait on the event on the nonlocal.
*/
-void nbnxnInsertNonlocalGpuDependency(const gmx_nbnxn_cuda_t* nb, const InteractionLocality interactionLocality)
+void nbnxnInsertNonlocalGpuDependency(const NbnxmGpu* nb, const InteractionLocality interactionLocality)
{
- cudaStream_t stream = nb->stream[interactionLocality];
+ const DeviceStream& deviceStream = *nb->deviceStreams[interactionLocality];
/* When we get here all misc operations issued in the local stream as well as
the local xq H2D are done,
{
if (interactionLocality == InteractionLocality::Local)
{
- cudaError_t stat = cudaEventRecord(nb->misc_ops_and_local_H2D_done, stream);
+ cudaError_t stat = cudaEventRecord(nb->misc_ops_and_local_H2D_done, deviceStream.stream());
CU_RET_ERR(stat, "cudaEventRecord on misc_ops_and_local_H2D_done failed");
}
else
{
- cudaError_t stat = cudaStreamWaitEvent(stream, nb->misc_ops_and_local_H2D_done, 0);
+ cudaError_t stat =
+ cudaStreamWaitEvent(deviceStream.stream(), nb->misc_ops_and_local_H2D_done, 0);
CU_RET_ERR(stat, "cudaStreamWaitEvent on misc_ops_and_local_H2D_done failed");
}
}
}
/*! \brief Launch asynchronously the xq buffer host to device copy. */
-void gpu_copy_xq_to_gpu(gmx_nbnxn_cuda_t* nb, const nbnxn_atomdata_t* nbatom, const AtomLocality atomLocality)
+void gpu_copy_xq_to_gpu(NbnxmGpu* nb, const nbnxn_atomdata_t* nbatom, const AtomLocality atomLocality)
{
GMX_ASSERT(nb, "Need a valid nbnxn_gpu object");
int adat_begin, adat_len; /* local/nonlocal offset and length used for xq and f */
- cu_atomdata_t* adat = nb->atdat;
- cu_plist_t* plist = nb->plist[iloc];
- cu_timers_t* t = nb->timers;
- cudaStream_t stream = nb->stream[iloc];
+ cu_atomdata_t* adat = nb->atdat;
+ cu_plist_t* plist = nb->plist[iloc];
+ cu_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
bool bDoTime = nb->bDoTime;
/* beginning of timed HtoD section */
if (bDoTime)
{
- t->xf[atomLocality].nb_h2d.openTimingRegion(stream);
+ t->xf[atomLocality].nb_h2d.openTimingRegion(deviceStream);
}
- cu_copy_H2D_async(adat->xq + adat_begin,
- static_cast<const void*>(nbatom->x().data() + adat_begin * 4),
- adat_len * sizeof(*adat->xq), stream);
+ static_assert(sizeof(adat->xq[0]) == sizeof(float4),
+ "The size of the xyzq buffer element should be equal to the size of float4.");
+ copyToDeviceBuffer(&adat->xq, reinterpret_cast<const float4*>(nbatom->x().data()) + adat_begin,
+ adat_begin, adat_len, deviceStream, GpuApiCallBehavior::Async, nullptr);
if (bDoTime)
{
- t->xf[atomLocality].nb_h2d.closeTimingRegion(stream);
+ t->xf[atomLocality].nb_h2d.closeTimingRegion(deviceStream);
}
/* When we get here all misc operations issued in the local stream as well as
the local x+q H2D (and all preceding) tasks are complete and synchronize
with this event in the non-local stream before launching the non-bonded kernel.
*/
-void gpu_launch_kernel(gmx_nbnxn_cuda_t* nb, const gmx::StepWorkload& stepWork, const InteractionLocality iloc)
+void gpu_launch_kernel(NbnxmGpu* nb, const gmx::StepWorkload& stepWork, const InteractionLocality iloc)
{
- cu_atomdata_t* adat = nb->atdat;
- cu_nbparam_t* nbp = nb->nbparam;
- cu_plist_t* plist = nb->plist[iloc];
- cu_timers_t* t = nb->timers;
- cudaStream_t stream = nb->stream[iloc];
+ cu_atomdata_t* adat = nb->atdat;
+ cu_nbparam_t* nbp = nb->nbparam;
+ cu_plist_t* plist = nb->plist[iloc];
+ cu_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
bool bDoTime = nb->bDoTime;
/* beginning of timed nonbonded calculation section */
if (bDoTime)
{
- t->interaction[iloc].nb_k.openTimingRegion(stream);
+ t->interaction[iloc].nb_k.openTimingRegion(deviceStream);
}
/* Kernel launch config:
* - The 1D block-grid contains as many blocks as super-clusters.
*/
int num_threads_z = 1;
- if (nb->dev_info->prop.major == 3 && nb->dev_info->prop.minor == 7)
+ if (nb->deviceContext_->deviceInfo().prop.major == 3 && nb->deviceContext_->deviceInfo().prop.minor == 7)
{
num_threads_z = 2;
}
- int nblock = calc_nb_kernel_nblock(plist->nsci, nb->dev_info);
+ int nblock = calc_nb_kernel_nblock(plist->nsci, &nb->deviceContext_->deviceInfo());
KernelLaunchConfig config;
- config.blockSize[0] = c_clSize;
- config.blockSize[1] = c_clSize;
- config.blockSize[2] = num_threads_z;
- config.gridSize[0] = nblock;
- config.sharedMemorySize = calc_shmem_required_nonbonded(num_threads_z, nb->dev_info, nbp);
- config.stream = stream;
+ config.blockSize[0] = c_clSize;
+ config.blockSize[1] = c_clSize;
+ config.blockSize[2] = num_threads_z;
+ config.gridSize[0] = nblock;
+ config.sharedMemorySize =
+ calc_shmem_required_nonbonded(num_threads_z, &nb->deviceContext_->deviceInfo(), nbp);
if (debug)
{
"\tGrid: %zux%zu\n\t#Super-clusters/clusters: %d/%d (%d)\n"
"\tShMem: %zu\n",
config.blockSize[0], config.blockSize[1], config.blockSize[2], config.gridSize[0],
- config.gridSize[1], plist->nsci * c_numClPerSupercl, c_numClPerSupercl, plist->na_c,
- config.sharedMemorySize);
+ config.gridSize[1], plist->nsci * c_nbnxnGpuNumClusterPerSupercluster,
+ c_nbnxnGpuNumClusterPerSupercluster, plist->na_c, config.sharedMemorySize);
}
auto* timingEvent = bDoTime ? t->interaction[iloc].nb_k.fetchNextEvent() : nullptr;
- const auto kernel = select_nbnxn_kernel(
- nbp->eeltype, nbp->vdwtype, stepWork.computeEnergy,
- (plist->haveFreshList && !nb->timers->interaction[iloc].didPrune), nb->dev_info);
+ const auto kernel =
+ select_nbnxn_kernel(nbp->eeltype, nbp->vdwtype, stepWork.computeEnergy,
+ (plist->haveFreshList && !nb->timers->interaction[iloc].didPrune),
+ &nb->deviceContext_->deviceInfo());
const auto kernelArgs =
prepareGpuKernelArguments(kernel, config, adat, nbp, plist, &stepWork.computeVirial);
- launchGpuKernel(kernel, config, timingEvent, "k_calc_nb", kernelArgs);
+ launchGpuKernel(kernel, config, deviceStream, timingEvent, "k_calc_nb", kernelArgs);
if (bDoTime)
{
- t->interaction[iloc].nb_k.closeTimingRegion(stream);
+ t->interaction[iloc].nb_k.closeTimingRegion(deviceStream);
}
if (GMX_NATIVE_WINDOWS)
{
/* Windows: force flushing WDDM queue */
- cudaStreamQuery(stream);
+ cudaStreamQuery(deviceStream.stream());
}
}
int shmem;
/* i-atom x in shared memory */
- shmem = c_numClPerSupercl * c_clSize * sizeof(float4);
+ shmem = c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(float4);
/* cj in shared memory, for each warp separately */
shmem += num_threads_z * c_nbnxnGpuClusterpairSplit * c_nbnxnGpuJgroupSize * sizeof(int);
return shmem;
}
-void gpu_launch_kernel_pruneonly(gmx_nbnxn_cuda_t* nb, const InteractionLocality iloc, const int numParts)
+void gpu_launch_kernel_pruneonly(NbnxmGpu* nb, const InteractionLocality iloc, const int numParts)
{
- cu_atomdata_t* adat = nb->atdat;
- cu_nbparam_t* nbp = nb->nbparam;
- cu_plist_t* plist = nb->plist[iloc];
- cu_timers_t* t = nb->timers;
- cudaStream_t stream = nb->stream[iloc];
+ cu_atomdata_t* adat = nb->atdat;
+ cu_nbparam_t* nbp = nb->nbparam;
+ cu_plist_t* plist = nb->plist[iloc];
+ cu_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
bool bDoTime = nb->bDoTime;
/* beginning of timed prune calculation section */
if (bDoTime)
{
- timer->openTimingRegion(stream);
+ timer->openTimingRegion(deviceStream);
}
/* Kernel launch config:
* and j-cluster concurrency, in x, y, and z, respectively.
* - The 1D block-grid contains as many blocks as super-clusters.
*/
- int num_threads_z = c_cudaPruneKernelJ4Concurrency;
- int nblock = calc_nb_kernel_nblock(numSciInPart, nb->dev_info);
+ int num_threads_z = c_cudaPruneKernelJ4Concurrency;
+ int nblock = calc_nb_kernel_nblock(numSciInPart, &nb->deviceContext_->deviceInfo());
KernelLaunchConfig config;
config.blockSize[0] = c_clSize;
config.blockSize[1] = c_clSize;
config.blockSize[2] = num_threads_z;
config.gridSize[0] = nblock;
config.sharedMemorySize = calc_shmem_required_prune(num_threads_z);
- config.stream = stream;
if (debug)
{
"\tGrid: %zux%zu\n\t#Super-clusters/clusters: %d/%d (%d)\n"
"\tShMem: %zu\n",
config.blockSize[0], config.blockSize[1], config.blockSize[2], config.gridSize[0],
- config.gridSize[1], numSciInPart * c_numClPerSupercl, c_numClPerSupercl,
- plist->na_c, config.sharedMemorySize);
+ config.gridSize[1], numSciInPart * c_nbnxnGpuNumClusterPerSupercluster,
+ c_nbnxnGpuNumClusterPerSupercluster, plist->na_c, config.sharedMemorySize);
}
auto* timingEvent = bDoTime ? timer->fetchNextEvent() : nullptr;
const auto kernel =
plist->haveFreshList ? nbnxn_kernel_prune_cuda<true> : nbnxn_kernel_prune_cuda<false>;
const auto kernelArgs = prepareGpuKernelArguments(kernel, config, adat, nbp, plist, &numParts, &part);
- launchGpuKernel(kernel, config, timingEvent, kernelName, kernelArgs);
+ launchGpuKernel(kernel, config, deviceStream, timingEvent, kernelName, kernelArgs);
/* TODO: consider a more elegant way to track which kernel has been called
(combined or separate 1st pass prune, rolling prune). */
if (bDoTime)
{
- timer->closeTimingRegion(stream);
+ timer->closeTimingRegion(deviceStream);
}
if (GMX_NATIVE_WINDOWS)
{
/* Windows: force flushing WDDM queue */
- cudaStreamQuery(stream);
+ cudaStreamQuery(deviceStream.stream());
}
}
-void gpu_launch_cpyback(gmx_nbnxn_cuda_t* nb,
+void gpu_launch_cpyback(NbnxmGpu* nb,
nbnxn_atomdata_t* nbatom,
const gmx::StepWorkload& stepWork,
const AtomLocality atomLocality)
const InteractionLocality iloc = gpuAtomToInteractionLocality(atomLocality);
/* extract the data */
- cu_atomdata_t* adat = nb->atdat;
- cu_timers_t* t = nb->timers;
- bool bDoTime = nb->bDoTime;
- cudaStream_t stream = nb->stream[iloc];
+ cu_atomdata_t* adat = nb->atdat;
+ cu_timers_t* t = nb->timers;
+ bool bDoTime = nb->bDoTime;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
/* don't launch non-local copy-back if there was no non-local work to do */
if ((iloc == InteractionLocality::NonLocal) && !haveGpuShortRangeWork(*nb, iloc))
/* beginning of timed D2H section */
if (bDoTime)
{
- t->xf[atomLocality].nb_d2h.openTimingRegion(stream);
+ t->xf[atomLocality].nb_d2h.openTimingRegion(deviceStream);
}
/* With DD the local D2H transfer can only start after the non-local
kernel has finished. */
if (iloc == InteractionLocality::Local && nb->bUseTwoStreams)
{
- stat = cudaStreamWaitEvent(stream, nb->nonlocal_done, 0);
+ stat = cudaStreamWaitEvent(deviceStream.stream(), nb->nonlocal_done, 0);
CU_RET_ERR(stat, "cudaStreamWaitEvent on nonlocal_done failed");
}
*/
if (!stepWork.useGpuFBufferOps)
{
- cu_copy_D2H_async(nbatom->out[0].f.data() + adat_begin * 3, adat->f + adat_begin,
- (adat_len) * sizeof(*adat->f), stream);
+ static_assert(
+ sizeof(adat->f[0]) == sizeof(float3),
+ "The size of the force buffer element should be equal to the size of float3.");
+ copyFromDeviceBuffer(reinterpret_cast<float3*>(nbatom->out[0].f.data()) + adat_begin, &adat->f,
+ adat_begin, adat_len, deviceStream, GpuApiCallBehavior::Async, nullptr);
}
/* After the non-local D2H is launched the nonlocal_done event can be
back first. */
if (iloc == InteractionLocality::NonLocal)
{
- stat = cudaEventRecord(nb->nonlocal_done, stream);
+ stat = cudaEventRecord(nb->nonlocal_done, deviceStream.stream());
CU_RET_ERR(stat, "cudaEventRecord on nonlocal_done failed");
}
/* DtoH fshift when virial is needed */
if (stepWork.computeVirial)
{
- cu_copy_D2H_async(nb->nbst.fshift, adat->fshift, SHIFTS * sizeof(*nb->nbst.fshift), stream);
+ static_assert(sizeof(nb->nbst.fshift[0]) == sizeof(adat->fshift[0]),
+ "Sizes of host- and device-side shift vectors should be the same.");
+ copyFromDeviceBuffer(nb->nbst.fshift, &adat->fshift, 0, SHIFTS, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
}
/* DtoH energies */
if (stepWork.computeEnergy)
{
- cu_copy_D2H_async(nb->nbst.e_lj, adat->e_lj, sizeof(*nb->nbst.e_lj), stream);
- cu_copy_D2H_async(nb->nbst.e_el, adat->e_el, sizeof(*nb->nbst.e_el), stream);
+ static_assert(sizeof(nb->nbst.e_lj[0]) == sizeof(adat->e_lj[0]),
+ "Sizes of host- and device-side LJ energy terms should be the same.");
+ copyFromDeviceBuffer(nb->nbst.e_lj, &adat->e_lj, 0, 1, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
+ static_assert(sizeof(nb->nbst.e_el[0]) == sizeof(adat->e_el[0]),
+ "Sizes of host- and device-side electrostatic energy terms should be the "
+ "same.");
+ copyFromDeviceBuffer(nb->nbst.e_el, &adat->e_el, 0, 1, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
}
}
if (bDoTime)
{
- t->xf[atomLocality].nb_d2h.closeTimingRegion(stream);
+ t->xf[atomLocality].nb_d2h.closeTimingRegion(deviceStream);
}
}
/* X buffer operations on GPU: performs conversion from rvec to nb format. */
void nbnxn_gpu_x_to_nbat_x(const Nbnxm::Grid& grid,
bool setFillerCoords,
- gmx_nbnxn_gpu_t* nb,
- DeviceBuffer<float> d_x,
+ NbnxmGpu* nb,
+ DeviceBuffer<gmx::RVec> d_x,
GpuEventSynchronizer* xReadyOnDevice,
const Nbnxm::AtomLocality locality,
int gridId,
const int numAtomsPerCell = grid.numAtomsPerCell();
Nbnxm::InteractionLocality interactionLoc = gpuAtomToInteractionLocality(locality);
- cudaStream_t stream = nb->stream[interactionLoc];
+ const DeviceStream& deviceStream = *nb->deviceStreams[interactionLoc];
int numAtoms = grid.srcAtomEnd() - grid.srcAtomBegin();
// avoid empty kernel launch, skip to inserting stream dependency
// ensure that coordinates are ready on the device before launching the kernel
GMX_ASSERT(xReadyOnDevice, "Need a valid GpuEventSynchronizer object");
- xReadyOnDevice->enqueueWaitEvent(stream);
+ xReadyOnDevice->enqueueWaitEvent(deviceStream);
KernelLaunchConfig config;
config.blockSize[0] = c_bufOpsThreadsPerBlock;
GMX_ASSERT(config.gridSize[0] > 0,
"Can not have empty grid, early return above avoids this");
config.sharedMemorySize = 0;
- config.stream = stream;
- auto kernelFn = nbnxn_gpu_x_to_nbat_x_kernel;
+ auto kernelFn = setFillerCoords ? nbnxn_gpu_x_to_nbat_x_kernel<true>
+ : nbnxn_gpu_x_to_nbat_x_kernel<false>;
float4* d_xq = adat->xq;
+ float3* d_xFloat3 = asFloat3(d_x);
const int* d_atomIndices = nb->atomIndices;
const int* d_cxy_na = &nb->cxy_na[numColumnsMax * gridId];
const int* d_cxy_ind = &nb->cxy_ind[numColumnsMax * gridId];
- const auto kernelArgs = prepareGpuKernelArguments(
- kernelFn, config, &numColumns, &d_xq, &setFillerCoords, &d_x, &d_atomIndices,
- &d_cxy_na, &d_cxy_ind, &cellOffset, &numAtomsPerCell);
- launchGpuKernel(kernelFn, config, nullptr, "XbufferOps", kernelArgs);
+ const auto kernelArgs = prepareGpuKernelArguments(kernelFn, config, &numColumns, &d_xq,
+ &d_xFloat3, &d_atomIndices, &d_cxy_na,
+ &d_cxy_ind, &cellOffset, &numAtomsPerCell);
+ launchGpuKernel(kernelFn, config, deviceStream, nullptr, "XbufferOps", kernelArgs);
}
- // TODO: note that this is not necessary when there are no local atoms, that is:
+ // TODO: note that this is not necessary when there astreamre no local atoms, that is:
// (numAtoms == 0 && interactionLoc == InteractionLocality::Local)
// but for now we avoid that optimization
nbnxnInsertNonlocalGpuDependency(nb, interactionLoc);
* forces only after Local stream already done so.
*/
void nbnxn_gpu_add_nbat_f_to_f(const AtomLocality atomLocality,
- DeviceBuffer<float> totalForcesDevice,
- gmx_nbnxn_gpu_t* nb,
+ DeviceBuffer<gmx::RVec> totalForcesDevice,
+ NbnxmGpu* nb,
void* pmeForcesDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
int atomStart,
GMX_ASSERT(numAtoms != 0, "Cannot call function with no atoms");
GMX_ASSERT(totalForcesDevice, "Need a valid totalForcesDevice pointer");
- const InteractionLocality iLocality = gpuAtomToInteractionLocality(atomLocality);
- cudaStream_t stream = nb->stream[iLocality];
- cu_atomdata_t* adat = nb->atdat;
+ const InteractionLocality iLocality = gpuAtomToInteractionLocality(atomLocality);
+ const DeviceStream& deviceStream = *nb->deviceStreams[iLocality];
+ cu_atomdata_t* adat = nb->atdat;
size_t gmx_used_in_debug numDependency = static_cast<size_t>((useGpuFPmeReduction == true))
+ static_cast<size_t>((accumulateForce == true));
// Enqueue wait on all dependencies passed
for (auto const synchronizer : dependencyList)
{
- synchronizer->enqueueWaitEvent(stream);
+ synchronizer->enqueueWaitEvent(deviceStream);
}
/* launch kernel */
config.gridSize[1] = 1;
config.gridSize[2] = 1;
config.sharedMemorySize = 0;
- config.stream = stream;
auto kernelFn = accumulateForce ? nbnxn_gpu_add_nbat_f_to_f_kernel<true, false>
: nbnxn_gpu_add_nbat_f_to_f_kernel<false, false>;
}
const float3* d_fNB = adat->f;
- const float3* d_fPme = (float3*)pmeForcesDevice;
- float3* d_fTotal = (float3*)totalForcesDevice;
+ const float3* d_fPme = static_cast<float3*>(pmeForcesDevice);
+ float3* d_fTotal = asFloat3(totalForcesDevice);
const int* d_cell = nb->cell;
const auto kernelArgs = prepareGpuKernelArguments(kernelFn, config, &d_fNB, &d_fPme, &d_fTotal,
&d_cell, &atomStart, &numAtoms);
- launchGpuKernel(kernelFn, config, nullptr, "FbufferOps", kernelArgs);
+ launchGpuKernel(kernelFn, config, deviceStream, nullptr, "FbufferOps", kernelArgs);
if (atomLocality == AtomLocality::Local)
{
GMX_ASSERT(nb->localFReductionDone != nullptr,
"localFReductionDone has to be a valid pointer");
- nb->localFReductionDone->markEvent(stream);
+ nb->localFReductionDone->markEvent(deviceStream);
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <stdio.h>
#include <stdlib.h>
-// TODO We would like to move this down, but the way gmx_nbnxn_gpu_t
+// TODO We would like to move this down, but the way NbnxmGpu
// is currently declared means this has to be before gpu_types.h
#include "nbnxm_cuda_types.h"
// TODO Remove this comment when the above order issue is resolved
#include "gromacs/gpu_utils/cudautils.cuh"
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/gpu_utils/gpueventsynchronizer.cuh"
#include "gromacs/gpu_utils/pmalloc_cuda.h"
static unsigned int gpu_min_ci_balanced_factor = 44;
/* Fw. decl. */
-static void nbnxn_cuda_clear_e_fshift(gmx_nbnxn_cuda_t* nb);
+static void nbnxn_cuda_clear_e_fshift(NbnxmGpu* nb);
/* Fw. decl, */
static void nbnxn_cuda_free_nbparam_table(cu_nbparam_t* nbparam);
and the table GPU array. If called with an already allocated table,
it just re-uploads the table.
*/
-static void init_ewald_coulomb_force_table(const EwaldCorrectionTables& tables, cu_nbparam_t* nbp)
+static void init_ewald_coulomb_force_table(const EwaldCorrectionTables& tables,
+ cu_nbparam_t* nbp,
+ const DeviceContext& deviceContext)
{
if (nbp->coulomb_tab != nullptr)
{
}
nbp->coulomb_tab_scale = tables.scale;
- initParamLookupTable(nbp->coulomb_tab, nbp->coulomb_tab_texobj, tables.tableF.data(),
- tables.tableF.size());
+ initParamLookupTable(&nbp->coulomb_tab, &nbp->coulomb_tab_texobj, tables.tableF.data(),
+ tables.tableF.size(), deviceContext);
}
/*! Initializes the atomdata structure first time, it only gets filled at
pair-search. */
-static void init_atomdata_first(cu_atomdata_t* ad, int ntypes)
+static void init_atomdata_first(cu_atomdata_t* ad, int ntypes, const DeviceContext& deviceContext)
{
- cudaError_t stat;
-
ad->ntypes = ntypes;
- stat = cudaMalloc((void**)&ad->shift_vec, SHIFTS * sizeof(*ad->shift_vec));
- CU_RET_ERR(stat, "cudaMalloc failed on ad->shift_vec");
+ allocateDeviceBuffer(&ad->shift_vec, SHIFTS, deviceContext);
ad->bShiftVecUploaded = false;
- stat = cudaMalloc((void**)&ad->fshift, SHIFTS * sizeof(*ad->fshift));
- CU_RET_ERR(stat, "cudaMalloc failed on ad->fshift");
-
- stat = cudaMalloc((void**)&ad->e_lj, sizeof(*ad->e_lj));
- CU_RET_ERR(stat, "cudaMalloc failed on ad->e_lj");
- stat = cudaMalloc((void**)&ad->e_el, sizeof(*ad->e_el));
- CU_RET_ERR(stat, "cudaMalloc failed on ad->e_el");
+ allocateDeviceBuffer(&ad->fshift, SHIFTS, deviceContext);
+ allocateDeviceBuffer(&ad->e_lj, 1, deviceContext);
+ allocateDeviceBuffer(&ad->e_el, 1, deviceContext);
/* initialize to nullptr poiters to data that is not allocated here and will
need reallocation in nbnxn_cuda_init_atomdata */
static void init_nbparam(cu_nbparam_t* nbp,
const interaction_const_t* ic,
const PairlistParams& listParams,
- const nbnxn_atomdata_t::Params& nbatParams)
+ const nbnxn_atomdata_t::Params& nbatParams,
+ const DeviceContext& deviceContext)
{
int ntypes;
if (nbp->eeltype == eelCuEWALD_TAB || nbp->eeltype == eelCuEWALD_TAB_TWIN)
{
GMX_RELEASE_ASSERT(ic->coulombEwaldTables, "Need valid Coulomb Ewald correction tables");
- init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp);
+ init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, deviceContext);
}
/* set up LJ parameter lookup table */
if (!useLjCombRule(nbp))
{
- initParamLookupTable(nbp->nbfp, nbp->nbfp_texobj, nbatParams.nbfp.data(), 2 * ntypes * ntypes);
+ initParamLookupTable(&nbp->nbfp, &nbp->nbfp_texobj, nbatParams.nbfp.data(),
+ 2 * ntypes * ntypes, deviceContext);
}
/* set up LJ-PME parameter lookup table */
if (ic->vdwtype == evdwPME)
{
- initParamLookupTable(nbp->nbfp_comb, nbp->nbfp_comb_texobj, nbatParams.nbfp_comb.data(), 2 * ntypes);
+ initParamLookupTable(&nbp->nbfp_comb, &nbp->nbfp_comb_texobj, nbatParams.nbfp_comb.data(),
+ 2 * ntypes, deviceContext);
}
}
{
return;
}
+ NbnxmGpu* nb = nbv->gpu_nbv;
cu_nbparam_t* nbp = nbv->gpu_nbv->nbparam;
set_cutoff_parameters(nbp, ic, nbv->pairlistSets().params());
nbp->eeltype = pick_ewald_kernel_type(*ic);
GMX_RELEASE_ASSERT(ic->coulombEwaldTables, "Need valid Coulomb Ewald correction tables");
- init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp);
+ init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, *nb->deviceContext_);
}
/*! Initializes the pair list data structure. */
}
/*! Initializes simulation constant data. */
-static void cuda_init_const(gmx_nbnxn_cuda_t* nb,
+static void cuda_init_const(NbnxmGpu* nb,
const interaction_const_t* ic,
const PairlistParams& listParams,
const nbnxn_atomdata_t::Params& nbatParams)
{
- init_atomdata_first(nb->atdat, nbatParams.numTypes);
- init_nbparam(nb->nbparam, ic, listParams, nbatParams);
+ init_atomdata_first(nb->atdat, nbatParams.numTypes, *nb->deviceContext_);
+ init_nbparam(nb->nbparam, ic, listParams, nbatParams, *nb->deviceContext_);
/* clear energy and shift force outputs */
nbnxn_cuda_clear_e_fshift(nb);
}
-gmx_nbnxn_cuda_t* gpu_init(const gmx_device_info_t* deviceInfo,
- const interaction_const_t* ic,
- const PairlistParams& listParams,
- const nbnxn_atomdata_t* nbat,
- int /*rank*/,
- gmx_bool bLocalAndNonlocal)
+NbnxmGpu* gpu_init(const gmx::DeviceStreamManager& deviceStreamManager,
+ const interaction_const_t* ic,
+ const PairlistParams& listParams,
+ const nbnxn_atomdata_t* nbat,
+ bool bLocalAndNonlocal)
{
cudaError_t stat;
- gmx_nbnxn_cuda_t* nb;
- snew(nb, 1);
+ auto nb = new NbnxmGpu();
+ nb->deviceContext_ = &deviceStreamManager.context();
snew(nb->atdat, 1);
snew(nb->nbparam, 1);
snew(nb->plist[InteractionLocality::Local], 1);
init_plist(nb->plist[InteractionLocality::Local]);
- /* set device info, just point it to the right GPU among the detected ones */
- nb->dev_info = deviceInfo;
-
/* local/non-local GPU streams */
- stat = cudaStreamCreate(&nb->stream[InteractionLocality::Local]);
- CU_RET_ERR(stat, "cudaStreamCreate on stream[InterationLocality::Local] failed");
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedLocal),
+ "Local non-bonded stream should be initialized to use GPU for non-bonded.");
+ nb->deviceStreams[InteractionLocality::Local] =
+ &deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedLocal);
if (nb->bUseTwoStreams)
{
init_plist(nb->plist[InteractionLocality::NonLocal]);
* priorities, because we are querying the priority range which in this
* case will be a single value.
*/
- int highest_priority;
- stat = cudaDeviceGetStreamPriorityRange(nullptr, &highest_priority);
- CU_RET_ERR(stat, "cudaDeviceGetStreamPriorityRange failed");
-
- stat = cudaStreamCreateWithPriority(&nb->stream[InteractionLocality::NonLocal],
- cudaStreamDefault, highest_priority);
- CU_RET_ERR(stat,
- "cudaStreamCreateWithPriority on stream[InteractionLocality::NonLocal] failed");
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedNonLocal),
+ "Non-local non-bonded stream should be initialized to use GPU for "
+ "non-bonded with domain decomposition.");
+ nb->deviceStreams[InteractionLocality::NonLocal] =
+ &deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedNonLocal);
+ ;
}
/* init events for sychronization (timing disabled for performance reasons!) */
return nb;
}
-void gpu_init_pairlist(gmx_nbnxn_cuda_t* nb, const NbnxnPairlistGpu* h_plist, const InteractionLocality iloc)
+void gpu_init_pairlist(NbnxmGpu* nb, const NbnxnPairlistGpu* h_plist, const InteractionLocality iloc)
{
- char sbuf[STRLEN];
- bool bDoTime = (nb->bDoTime && !h_plist->sci.empty());
- cudaStream_t stream = nb->stream[iloc];
- cu_plist_t* d_plist = nb->plist[iloc];
+ char sbuf[STRLEN];
+ bool bDoTime = (nb->bDoTime && !h_plist->sci.empty());
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
+ cu_plist_t* d_plist = nb->plist[iloc];
if (d_plist->na_c < 0)
{
if (bDoTime)
{
- iTimers.pl_h2d.openTimingRegion(stream);
+ iTimers.pl_h2d.openTimingRegion(deviceStream);
iTimers.didPairlistH2D = true;
}
- DeviceContext context = nullptr;
+ const DeviceContext& deviceContext = *nb->deviceContext_;
- reallocateDeviceBuffer(&d_plist->sci, h_plist->sci.size(), &d_plist->nsci, &d_plist->sci_nalloc, context);
- copyToDeviceBuffer(&d_plist->sci, h_plist->sci.data(), 0, h_plist->sci.size(), stream,
+ reallocateDeviceBuffer(&d_plist->sci, h_plist->sci.size(), &d_plist->nsci, &d_plist->sci_nalloc,
+ deviceContext);
+ copyToDeviceBuffer(&d_plist->sci, h_plist->sci.data(), 0, h_plist->sci.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
- reallocateDeviceBuffer(&d_plist->cj4, h_plist->cj4.size(), &d_plist->ncj4, &d_plist->cj4_nalloc, context);
- copyToDeviceBuffer(&d_plist->cj4, h_plist->cj4.data(), 0, h_plist->cj4.size(), stream,
+ reallocateDeviceBuffer(&d_plist->cj4, h_plist->cj4.size(), &d_plist->ncj4, &d_plist->cj4_nalloc,
+ deviceContext);
+ copyToDeviceBuffer(&d_plist->cj4, h_plist->cj4.data(), 0, h_plist->cj4.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
reallocateDeviceBuffer(&d_plist->imask, h_plist->cj4.size() * c_nbnxnGpuClusterpairSplit,
- &d_plist->nimask, &d_plist->imask_nalloc, context);
+ &d_plist->nimask, &d_plist->imask_nalloc, deviceContext);
reallocateDeviceBuffer(&d_plist->excl, h_plist->excl.size(), &d_plist->nexcl,
- &d_plist->excl_nalloc, context);
- copyToDeviceBuffer(&d_plist->excl, h_plist->excl.data(), 0, h_plist->excl.size(), stream,
+ &d_plist->excl_nalloc, deviceContext);
+ copyToDeviceBuffer(&d_plist->excl, h_plist->excl.data(), 0, h_plist->excl.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
if (bDoTime)
{
- iTimers.pl_h2d.closeTimingRegion(stream);
+ iTimers.pl_h2d.closeTimingRegion(deviceStream);
}
/* the next use of thist list we be the first one, so we need to prune */
d_plist->haveFreshList = true;
}
-void gpu_upload_shiftvec(gmx_nbnxn_cuda_t* nb, const nbnxn_atomdata_t* nbatom)
+void gpu_upload_shiftvec(NbnxmGpu* nb, const nbnxn_atomdata_t* nbatom)
{
- cu_atomdata_t* adat = nb->atdat;
- cudaStream_t ls = nb->stream[InteractionLocality::Local];
+ cu_atomdata_t* adat = nb->atdat;
+ const DeviceStream& localStream = *nb->deviceStreams[InteractionLocality::Local];
/* only if we have a dynamic box */
if (nbatom->bDynamicBox || !adat->bShiftVecUploaded)
{
- cu_copy_H2D_async(adat->shift_vec, nbatom->shift_vec.data(), SHIFTS * sizeof(*adat->shift_vec), ls);
+ static_assert(sizeof(adat->shift_vec[0]) == sizeof(nbatom->shift_vec[0]),
+ "Sizes of host- and device-side shift vectors should be the same.");
+ copyToDeviceBuffer(&adat->shift_vec, reinterpret_cast<const float3*>(nbatom->shift_vec.data()),
+ 0, SHIFTS, localStream, GpuApiCallBehavior::Async, nullptr);
adat->bShiftVecUploaded = true;
}
}
/*! Clears the first natoms_clear elements of the GPU nonbonded force output array. */
-static void nbnxn_cuda_clear_f(gmx_nbnxn_cuda_t* nb, int natoms_clear)
+static void nbnxn_cuda_clear_f(NbnxmGpu* nb, int natoms_clear)
{
- cudaError_t stat;
- cu_atomdata_t* adat = nb->atdat;
- cudaStream_t ls = nb->stream[InteractionLocality::Local];
-
- stat = cudaMemsetAsync(adat->f, 0, natoms_clear * sizeof(*adat->f), ls);
- CU_RET_ERR(stat, "cudaMemsetAsync on f falied");
+ cu_atomdata_t* adat = nb->atdat;
+ const DeviceStream& localStream = *nb->deviceStreams[InteractionLocality::Local];
+ clearDeviceBufferAsync(&adat->f, 0, natoms_clear, localStream);
}
/*! Clears nonbonded shift force output array and energy outputs on the GPU. */
-static void nbnxn_cuda_clear_e_fshift(gmx_nbnxn_cuda_t* nb)
+static void nbnxn_cuda_clear_e_fshift(NbnxmGpu* nb)
{
- cudaError_t stat;
- cu_atomdata_t* adat = nb->atdat;
- cudaStream_t ls = nb->stream[InteractionLocality::Local];
-
- stat = cudaMemsetAsync(adat->fshift, 0, SHIFTS * sizeof(*adat->fshift), ls);
- CU_RET_ERR(stat, "cudaMemsetAsync on fshift falied");
- stat = cudaMemsetAsync(adat->e_lj, 0, sizeof(*adat->e_lj), ls);
- CU_RET_ERR(stat, "cudaMemsetAsync on e_lj falied");
- stat = cudaMemsetAsync(adat->e_el, 0, sizeof(*adat->e_el), ls);
- CU_RET_ERR(stat, "cudaMemsetAsync on e_el falied");
+ cu_atomdata_t* adat = nb->atdat;
+ const DeviceStream& localStream = *nb->deviceStreams[InteractionLocality::Local];
+
+ clearDeviceBufferAsync(&adat->fshift, 0, SHIFTS, localStream);
+ clearDeviceBufferAsync(&adat->e_lj, 0, 1, localStream);
+ clearDeviceBufferAsync(&adat->e_el, 0, 1, localStream);
}
-void gpu_clear_outputs(gmx_nbnxn_cuda_t* nb, bool computeVirial)
+void gpu_clear_outputs(NbnxmGpu* nb, bool computeVirial)
{
nbnxn_cuda_clear_f(nb, nb->atdat->natoms);
/* clear shift force array and energies if the outputs were
}
}
-void gpu_init_atomdata(gmx_nbnxn_cuda_t* nb, const nbnxn_atomdata_t* nbat)
+void gpu_init_atomdata(NbnxmGpu* nb, const nbnxn_atomdata_t* nbat)
{
- cudaError_t stat;
- int nalloc, natoms;
- bool realloced;
- bool bDoTime = nb->bDoTime;
- cu_timers_t* timers = nb->timers;
- cu_atomdata_t* d_atdat = nb->atdat;
- cudaStream_t ls = nb->stream[InteractionLocality::Local];
+ int nalloc, natoms;
+ bool realloced;
+ bool bDoTime = nb->bDoTime;
+ cu_timers_t* timers = nb->timers;
+ cu_atomdata_t* d_atdat = nb->atdat;
+ const DeviceContext& deviceContext = *nb->deviceContext_;
+ const DeviceStream& localStream = *nb->deviceStreams[InteractionLocality::Local];
natoms = nbat->numAtoms();
realloced = false;
if (bDoTime)
{
/* time async copy */
- timers->atdat.openTimingRegion(ls);
+ timers->atdat.openTimingRegion(localStream);
}
/* need to reallocate if we have to copy more atoms than the amount of space
freeDeviceBuffer(&d_atdat->lj_comb);
}
- stat = cudaMalloc((void**)&d_atdat->f, nalloc * sizeof(*d_atdat->f));
- CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->f");
- stat = cudaMalloc((void**)&d_atdat->xq, nalloc * sizeof(*d_atdat->xq));
- CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->xq");
+ allocateDeviceBuffer(&d_atdat->f, nalloc, deviceContext);
+ allocateDeviceBuffer(&d_atdat->xq, nalloc, deviceContext);
if (useLjCombRule(nb->nbparam))
{
- stat = cudaMalloc((void**)&d_atdat->lj_comb, nalloc * sizeof(*d_atdat->lj_comb));
- CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->lj_comb");
+ allocateDeviceBuffer(&d_atdat->lj_comb, nalloc, deviceContext);
}
else
{
- stat = cudaMalloc((void**)&d_atdat->atom_types, nalloc * sizeof(*d_atdat->atom_types));
- CU_RET_ERR(stat, "cudaMalloc failed on d_atdat->atom_types");
+ allocateDeviceBuffer(&d_atdat->atom_types, nalloc, deviceContext);
}
d_atdat->nalloc = nalloc;
if (useLjCombRule(nb->nbparam))
{
- cu_copy_H2D_async(d_atdat->lj_comb, nbat->params().lj_comb.data(),
- natoms * sizeof(*d_atdat->lj_comb), ls);
+ static_assert(sizeof(d_atdat->lj_comb[0]) == sizeof(float2),
+ "Size of the LJ parameters element should be equal to the size of float2.");
+ copyToDeviceBuffer(&d_atdat->lj_comb,
+ reinterpret_cast<const float2*>(nbat->params().lj_comb.data()), 0,
+ natoms, localStream, GpuApiCallBehavior::Async, nullptr);
}
else
{
- cu_copy_H2D_async(d_atdat->atom_types, nbat->params().type.data(),
- natoms * sizeof(*d_atdat->atom_types), ls);
+ static_assert(sizeof(d_atdat->atom_types[0]) == sizeof(nbat->params().type[0]),
+ "Sizes of host- and device-side atom types should be the same.");
+ copyToDeviceBuffer(&d_atdat->atom_types, nbat->params().type.data(), 0, natoms, localStream,
+ GpuApiCallBehavior::Async, nullptr);
}
if (bDoTime)
{
- timers->atdat.closeTimingRegion(ls);
+ timers->atdat.closeTimingRegion(localStream);
}
}
{
if (nbparam->eeltype == eelCuEWALD_TAB || nbparam->eeltype == eelCuEWALD_TAB_TWIN)
{
- destroyParamLookupTable(nbparam->coulomb_tab, nbparam->coulomb_tab_texobj);
+ destroyParamLookupTable(&nbparam->coulomb_tab, nbparam->coulomb_tab_texobj);
}
}
-void gpu_free(gmx_nbnxn_cuda_t* nb)
+void gpu_free(NbnxmGpu* nb)
{
cudaError_t stat;
cu_atomdata_t* atdat;
CU_RET_ERR(stat, "cudaEventDestroy failed on timers->misc_ops_and_local_H2D_done");
delete nb->timers;
- if (nb->bDoTime)
- {
- /* The non-local counters/stream (second in the array) are needed only with DD. */
- for (int i = 0; i <= (nb->bUseTwoStreams ? 1 : 0); i++)
- {
- stat = cudaStreamDestroy(nb->stream[i]);
- CU_RET_ERR(stat, "cudaStreamDestroy failed on stream");
- }
- }
if (!useLjCombRule(nb->nbparam))
{
- destroyParamLookupTable(nbparam->nbfp, nbparam->nbfp_texobj);
+ destroyParamLookupTable(&nbparam->nbfp, nbparam->nbfp_texobj);
}
if (nbparam->vdwtype == evdwCuEWALDGEOM || nbparam->vdwtype == evdwCuEWALDLB)
{
- destroyParamLookupTable(nbparam->nbfp_comb, nbparam->nbfp_comb_texobj);
+ destroyParamLookupTable(&nbparam->nbfp_comb, nbparam->nbfp_comb_texobj);
}
- stat = cudaFree(atdat->shift_vec);
- CU_RET_ERR(stat, "cudaFree failed on atdat->shift_vec");
- stat = cudaFree(atdat->fshift);
- CU_RET_ERR(stat, "cudaFree failed on atdat->fshift");
+ freeDeviceBuffer(&atdat->shift_vec);
+ freeDeviceBuffer(&atdat->fshift);
- stat = cudaFree(atdat->e_lj);
- CU_RET_ERR(stat, "cudaFree failed on atdat->e_lj");
- stat = cudaFree(atdat->e_el);
- CU_RET_ERR(stat, "cudaFree failed on atdat->e_el");
+ freeDeviceBuffer(&atdat->e_lj);
+ freeDeviceBuffer(&atdat->e_el);
freeDeviceBuffer(&atdat->f);
freeDeviceBuffer(&atdat->xq);
sfree(atdat);
sfree(nbparam);
sfree(nb->timings);
- sfree(nb);
+ delete nb;
if (debug)
{
}
//! This function is documented in the header file
-gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(gmx_nbnxn_cuda_t* nb)
+gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(NbnxmGpu* nb)
{
return (nb != nullptr && nb->bDoTime) ? nb->timings : nullptr;
}
}
}
-int gpu_min_ci_balanced(gmx_nbnxn_cuda_t* nb)
+int gpu_min_ci_balanced(NbnxmGpu* nb)
{
- return nb != nullptr ? gpu_min_ci_balanced_factor * nb->dev_info->prop.multiProcessorCount : 0;
+ return nb != nullptr ? gpu_min_ci_balanced_factor * nb->deviceContext_->deviceInfo().prop.multiProcessorCount
+ : 0;
}
-gmx_bool gpu_is_kernel_ewald_analytical(const gmx_nbnxn_cuda_t* nb)
+gmx_bool gpu_is_kernel_ewald_analytical(const NbnxmGpu* nb)
{
return ((nb->nbparam->eeltype == eelCuEWALD_ANA) || (nb->nbparam->eeltype == eelCuEWALD_ANA_TWIN));
}
-void* gpu_get_command_stream(gmx_nbnxn_gpu_t* nb, const InteractionLocality iloc)
-{
- assert(nb);
-
- return static_cast<void*>(&nb->stream[iloc]);
-}
-
-void* gpu_get_xq(gmx_nbnxn_gpu_t* nb)
+void* gpu_get_xq(NbnxmGpu* nb)
{
assert(nb);
return static_cast<void*>(nb->atdat->xq);
}
-void* gpu_get_f(gmx_nbnxn_gpu_t* nb)
+DeviceBuffer<gmx::RVec> gpu_get_f(NbnxmGpu* nb)
{
assert(nb);
- return static_cast<void*>(nb->atdat->f);
+ return reinterpret_cast<DeviceBuffer<gmx::RVec>>(nb->atdat->f);
}
-rvec* gpu_get_fshift(gmx_nbnxn_gpu_t* nb)
+DeviceBuffer<gmx::RVec> gpu_get_fshift(NbnxmGpu* nb)
{
assert(nb);
- return reinterpret_cast<rvec*>(nb->atdat->fshift);
+ return reinterpret_cast<DeviceBuffer<gmx::RVec>>(nb->atdat->fshift);
}
/* Initialization for X buffer operations on GPU. */
/* TODO Remove explicit pinning from host arrays from here and manage in a more natural way*/
-void nbnxn_gpu_init_x_to_nbat_x(const Nbnxm::GridSet& gridSet, gmx_nbnxn_gpu_t* gpu_nbv)
+void nbnxn_gpu_init_x_to_nbat_x(const Nbnxm::GridSet& gridSet, NbnxmGpu* gpu_nbv)
{
- cudaStream_t stream = gpu_nbv->stream[InteractionLocality::Local];
- bool bDoTime = gpu_nbv->bDoTime;
- const int maxNumColumns = gridSet.numColumnsMax();
+ const DeviceStream& deviceStream = *gpu_nbv->deviceStreams[InteractionLocality::Local];
+ bool bDoTime = gpu_nbv->bDoTime;
+ const int maxNumColumns = gridSet.numColumnsMax();
reallocateDeviceBuffer(&gpu_nbv->cxy_na, maxNumColumns * gridSet.grids().size(),
- &gpu_nbv->ncxy_na, &gpu_nbv->ncxy_na_alloc, nullptr);
+ &gpu_nbv->ncxy_na, &gpu_nbv->ncxy_na_alloc, *gpu_nbv->deviceContext_);
reallocateDeviceBuffer(&gpu_nbv->cxy_ind, maxNumColumns * gridSet.grids().size(),
- &gpu_nbv->ncxy_ind, &gpu_nbv->ncxy_ind_alloc, nullptr);
+ &gpu_nbv->ncxy_ind, &gpu_nbv->ncxy_ind_alloc, *gpu_nbv->deviceContext_);
for (unsigned int g = 0; g < gridSet.grids().size(); g++)
{
const int* cxy_ind = grid.cxy_ind().data();
reallocateDeviceBuffer(&gpu_nbv->atomIndices, atomIndicesSize, &gpu_nbv->atomIndicesSize,
- &gpu_nbv->atomIndicesSize_alloc, nullptr);
+ &gpu_nbv->atomIndicesSize_alloc, *gpu_nbv->deviceContext_);
if (atomIndicesSize > 0)
{
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(deviceStream);
}
- copyToDeviceBuffer(&gpu_nbv->atomIndices, atomIndices, 0, atomIndicesSize, stream,
+ copyToDeviceBuffer(&gpu_nbv->atomIndices, atomIndices, 0, atomIndicesSize, deviceStream,
GpuApiCallBehavior::Async, nullptr);
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(deviceStream);
}
}
{
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(deviceStream);
}
int* destPtr = &gpu_nbv->cxy_na[maxNumColumns * g];
- copyToDeviceBuffer(&destPtr, cxy_na, 0, numColumns, stream, GpuApiCallBehavior::Async, nullptr);
+ copyToDeviceBuffer(&destPtr, cxy_na, 0, numColumns, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(deviceStream);
}
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.openTimingRegion(deviceStream);
}
destPtr = &gpu_nbv->cxy_ind[maxNumColumns * g];
- copyToDeviceBuffer(&destPtr, cxy_ind, 0, numColumns, stream, GpuApiCallBehavior::Async, nullptr);
+ copyToDeviceBuffer(&destPtr, cxy_ind, 0, numColumns, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
if (bDoTime)
{
- gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(stream);
+ gpu_nbv->timers->xf[AtomLocality::Local].nb_h2d.closeTimingRegion(deviceStream);
}
}
}
/* Initialization for F buffer operations on GPU. */
void nbnxn_gpu_init_add_nbat_f_to_f(const int* cell,
- gmx_nbnxn_gpu_t* gpu_nbv,
+ NbnxmGpu* gpu_nbv,
int natoms_total,
GpuEventSynchronizer* const localReductionDone)
{
- cudaStream_t stream = gpu_nbv->stream[InteractionLocality::Local];
+ const DeviceStream& deviceStream = *gpu_nbv->deviceStreams[InteractionLocality::Local];
GMX_ASSERT(localReductionDone, "localReductionDone should be a valid pointer");
gpu_nbv->localFReductionDone = localReductionDone;
if (natoms_total > 0)
{
- reallocateDeviceBuffer(&gpu_nbv->cell, natoms_total, &gpu_nbv->ncell, &gpu_nbv->ncell_alloc, nullptr);
- copyToDeviceBuffer(&gpu_nbv->cell, cell, 0, natoms_total, stream, GpuApiCallBehavior::Async, nullptr);
+ reallocateDeviceBuffer(&gpu_nbv->cell, natoms_total, &gpu_nbv->ncell, &gpu_nbv->ncell_alloc,
+ *gpu_nbv->deviceContext_);
+ copyToDeviceBuffer(&gpu_nbv->cell, cell, 0, natoms_total, deviceStream,
+ GpuApiCallBehavior::Async, nullptr);
}
return;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
unsigned int wexcl, imask, mask_ji;
float4 xqbuf;
float3 xi, xj, rv, f_ij, fcj_buf;
- float3 fci_buf[c_numClPerSupercl]; /* i force buffer */
+ float3 fci_buf[c_nbnxnGpuNumClusterPerSupercluster]; /* i force buffer */
nbnxn_sci_t nb_sci;
- /*! i-cluster interaction mask for a super-cluster with all c_numClPerSupercl=8 bits set */
- const unsigned superClInteractionMask = ((1U << c_numClPerSupercl) - 1U);
+ /*! i-cluster interaction mask for a super-cluster with all c_nbnxnGpuNumClusterPerSupercluster=8 bits set */
+ const unsigned superClInteractionMask = ((1U << c_nbnxnGpuNumClusterPerSupercluster) - 1U);
/*********************************************************************
* Set up shared memory pointers.
/* shmem buffer for i x+q pre-loading */
float4* xqib = (float4*)sm_nextSlotPtr;
- sm_nextSlotPtr += (c_numClPerSupercl * c_clSize * sizeof(*xqib));
+ sm_nextSlotPtr += (c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(*xqib));
/* shmem buffer for cj, for each warp separately */
int* cjs = (int*)(sm_nextSlotPtr);
# ifndef LJ_COMB
/* shmem buffer for i atom-type pre-loading */
int* atib = (int*)sm_nextSlotPtr;
- sm_nextSlotPtr += (c_numClPerSupercl * c_clSize * sizeof(*atib));
+ sm_nextSlotPtr += (c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(*atib));
# else
/* shmem buffer for i-atom LJ combination rule parameters */
float2* ljcpib = (float2*)sm_nextSlotPtr;
- sm_nextSlotPtr += (c_numClPerSupercl * c_clSize * sizeof(*ljcpib));
+ sm_nextSlotPtr += (c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(*ljcpib));
# endif
/*********************************************************************/
if (tidxz == 0)
{
/* Pre-load i-atom x and q into shared memory */
- ci = sci * c_numClPerSupercl + tidxj;
+ ci = sci * c_nbnxnGpuNumClusterPerSupercluster + tidxj;
ai = ci * c_clSize + tidxi;
float* shiftptr = (float*)&shift_vec[nb_sci.shift];
}
__syncthreads();
- for (i = 0; i < c_numClPerSupercl; i++)
+ for (i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
fci_buf[i] = make_float3(0.0f);
}
E_el = 0.0f;
# ifdef EXCLUSION_FORCES /* Ewald or RF */
- if (nb_sci.shift == CENTRAL && pl_cj4[cij4_start].cj[0] == sci * c_numClPerSupercl)
+ if (nb_sci.shift == CENTRAL && pl_cj4[cij4_start].cj[0] == sci * c_nbnxnGpuNumClusterPerSupercluster)
{
/* we have the diagonal: add the charge and LJ self interaction energy term */
- for (i = 0; i < c_numClPerSupercl; i++)
+ for (i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
# if defined EL_EWALD_ANY || defined EL_RF || defined EL_CUTOFF
qi = xqib[i * c_clSize + tidxi].w;
# ifdef LJ_EWALD
# if DISABLE_CUDA_TEXTURES
- E_lj += LDG(
- &nbparam.nbfp[atom_types[(sci * c_numClPerSupercl + i) * c_clSize + tidxi] * (ntypes + 1) * 2]);
+ E_lj += LDG(&nbparam.nbfp[atom_types[(sci * c_nbnxnGpuNumClusterPerSupercluster + i) * c_clSize + tidxi]
+ * (ntypes + 1) * 2]);
# else
E_lj += tex1Dfetch<float>(
nbparam.nbfp_texobj,
- atom_types[(sci * c_numClPerSupercl + i) * c_clSize + tidxi] * (ntypes + 1) * 2);
+ atom_types[(sci * c_nbnxnGpuNumClusterPerSupercluster + i) * c_clSize + tidxi]
+ * (ntypes + 1) * 2);
# endif
# endif
}
Tested with up to nvcc 7.5 */
for (jm = 0; jm < c_nbnxnGpuJgroupSize; jm++)
{
- if (imask & (superClInteractionMask << (jm * c_numClPerSupercl)))
+ if (imask & (superClInteractionMask << (jm * c_nbnxnGpuNumClusterPerSupercluster)))
{
- mask_ji = (1U << (jm * c_numClPerSupercl));
+ mask_ji = (1U << (jm * c_nbnxnGpuNumClusterPerSupercluster));
cj = cjs[jm + (tidxj & 4) * c_nbnxnGpuJgroupSize / c_splitClSize];
aj = cj * c_clSize + tidxj;
# if !defined PRUNE_NBL
# pragma unroll 8
# endif
- for (i = 0; i < c_numClPerSupercl; i++)
+ for (i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
if (imask & mask_ji)
{
- ci = sci * c_numClPerSupercl + i; /* i cluster index */
+ ci = sci * c_nbnxnGpuNumClusterPerSupercluster + i; /* i cluster index */
/* all threads load an atom from i cluster ci into shmem! */
xqbuf = xqib[i * c_clSize + tidxi];
# endif /* LJ_COMB */
// Ensure distance do not become so small that r^-12 overflows
- r2 = max(r2, NBNXN_MIN_RSQ);
+ r2 = max(r2, c_nbnxnMinDistanceSquared);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;
float fshift_buf = 0.0f;
/* reduce i forces */
- for (i = 0; i < c_numClPerSupercl; i++)
+ for (i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
- ai = (sci * c_numClPerSupercl + i) * c_clSize + tidxi;
+ ai = (sci * c_nbnxnGpuNumClusterPerSupercluster + i) * c_clSize + tidxi;
reduce_force_i_warp_shfl(fci_buf[i], f, &fshift_buf, bCalcFshift, tidxj, ai, c_fullWarpMask);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* shmem buffer for i x+q pre-loading */
float4* xib = (float4*)sm_nextSlotPtr;
- sm_nextSlotPtr += (c_numClPerSupercl * c_clSize * sizeof(*xib));
+ sm_nextSlotPtr += (c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(*xib));
/* shmem buffer for cj, for each warp separately */
int* cjs = (int*)(sm_nextSlotPtr);
if (tidxz == 0)
{
/* Pre-load i-atom x and q into shared memory */
- int ci = sci * c_numClPerSupercl + tidxj;
+ int ci = sci * c_nbnxnGpuNumClusterPerSupercluster + tidxj;
int ai = ci * c_clSize + tidxi;
/* We don't need q, but using float4 in shmem avoids bank conflicts.
# pragma unroll 4
for (int jm = 0; jm < c_nbnxnGpuJgroupSize; jm++)
{
- if (imaskCheck & (superClInteractionMask << (jm * c_numClPerSupercl)))
+ if (imaskCheck & (superClInteractionMask << (jm * c_nbnxnGpuNumClusterPerSupercluster)))
{
- unsigned int mask_ji = (1U << (jm * c_numClPerSupercl));
+ unsigned int mask_ji = (1U << (jm * c_nbnxnGpuNumClusterPerSupercluster));
int cj = cjs[jm + (tidxj & 4) * c_nbnxnGpuJgroupSize / c_splitClSize];
int aj = cj * c_clSize + tidxj;
float3 xj = make_float3(tmp.x, tmp.y, tmp.z);
# pragma unroll 8
- for (int i = 0; i < c_numClPerSupercl; i++)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
if (imaskCheck & mask_ji)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
static const int __device__ c_splitClSize = c_clSize / c_nbnxnGpuClusterpairSplit;
/*! \brief Stride in the force accumualation buffer */
static const int __device__ c_fbufStride = c_clSizeSq;
-/*! \brief i-cluster interaction mask for a super-cluster with all c_numClPerSupercl=8 bits set */
-static const unsigned __device__ superClInteractionMask = ((1U << c_numClPerSupercl) - 1U);
+/*! \brief i-cluster interaction mask for a super-cluster with all c_nbnxnGpuNumClusterPerSupercluster=8 bits set */
+static const unsigned __device__ superClInteractionMask =
+ ((1U << c_nbnxnGpuNumClusterPerSupercluster) - 1U);
static const float __device__ c_oneSixth = 0.16666667f;
static const float __device__ c_oneTwelveth = 0.08333333f;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2012, The GROMACS development team.
- * Copyright (c) 2013-2019, by the GROMACS development team, led by
+ * Copyright (c) 2013-2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/cuda_arch_utils.cuh"
#include "gromacs/gpu_utils/cudautils.cuh"
#include "gromacs/gpu_utils/devicebuffer.h"
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gputraits.cuh"
#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/nbnxm/gpu_types_common.h"
/* TODO: consider moving this to kernel_utils */
/* Convenience defines */
-/*! \brief number of clusters per supercluster. */
-static const int c_numClPerSupercl = c_nbnxnGpuNumClusterPerSupercluster;
/*! \brief cluster size = number of atoms per cluster. */
-static const int c_clSize = c_nbnxnGpuClusterSize;
+static constexpr int c_clSize = c_nbnxnGpuClusterSize;
/*! \brief Electrostatic CUDA kernel flavors.
*
/*! \cond */
typedef struct cu_atomdata cu_atomdata_t;
typedef struct cu_nbparam cu_nbparam_t;
-typedef struct nb_staging nb_staging_t;
/*! \endcond */
* The energies/shift forces get downloaded here first, before getting added
* to the CPU-side aggregate values.
*/
-struct nb_staging
+struct nb_staging_t
{
- float* e_lj; /**< LJ energy */
- float* e_el; /**< electrostatic energy */
- float3* fshift; /**< shift forces */
+ //! LJ energy
+ float* e_lj = nullptr;
+ //! electrostatic energy
+ float* e_el = nullptr;
+ //! shift forces
+ float3* fshift = nullptr;
};
/** \internal
*/
struct cu_atomdata
{
- int natoms; /**< number of atoms */
- int natoms_local; /**< number of local atoms */
- int nalloc; /**< allocation size for the atom data (xq, f) */
-
- float4* xq; /**< atom coordinates + charges, size natoms */
- float3* f; /**< force output array, size natoms */
-
- float* e_lj; /**< LJ energy output, size 1 */
- float* e_el; /**< Electrostatics energy input, size 1 */
-
- float3* fshift; /**< shift forces */
-
- int ntypes; /**< number of atom types */
- int* atom_types; /**< atom type indices, size natoms */
- float2* lj_comb; /**< sqrt(c6),sqrt(c12) size natoms */
-
- float3* shift_vec; /**< shifts */
- bool bShiftVecUploaded; /**< true if the shift vector has been uploaded */
+ //! number of atoms
+ int natoms;
+ //! number of local atoms
+ int natoms_local;
+ //! allocation size for the atom data (xq, f)
+ int nalloc;
+
+ //! atom coordinates + charges, size natoms
+ DeviceBuffer<float4> xq;
+ //! force output array, size natoms
+ DeviceBuffer<float3> f;
+
+ //! LJ energy output, size 1
+ DeviceBuffer<float> e_lj;
+ //! Electrostatics energy input, size 1
+ DeviceBuffer<float> e_el;
+
+ //! shift forces
+ DeviceBuffer<float3> fshift;
+
+ //! number of atom types
+ int ntypes;
+ //! atom type indices, size natoms
+ DeviceBuffer<int> atom_types;
+ //! sqrt(c6),sqrt(c12) size natoms
+ DeviceBuffer<float2> lj_comb;
+
+ //! shifts
+ DeviceBuffer<float3> shift_vec;
+ //! true if the shift vector has been uploaded
+ bool bShiftVecUploaded;
};
/** \internal
struct cu_nbparam
{
- int eeltype; /**< type of electrostatics, takes values from #eelCu */
- int vdwtype; /**< type of VdW impl., takes values from #evdwCu */
-
- float epsfac; /**< charge multiplication factor */
- float c_rf; /**< Reaction-field/plain cutoff electrostatics const. */
- float two_k_rf; /**< Reaction-field electrostatics constant */
- float ewald_beta; /**< Ewald/PME parameter */
- float sh_ewald; /**< Ewald/PME correction term substracted from the direct-space potential */
- float sh_lj_ewald; /**< LJ-Ewald/PME correction term added to the correction potential */
- float ewaldcoeff_lj; /**< LJ-Ewald/PME coefficient */
-
- float rcoulomb_sq; /**< Coulomb cut-off squared */
-
- float rvdw_sq; /**< VdW cut-off squared */
- float rvdw_switch; /**< VdW switched cut-off */
- float rlistOuter_sq; /**< Full, outer pair-list cut-off squared */
- float rlistInner_sq; /**< Inner, dynamic pruned pair-list cut-off squared */
- bool useDynamicPruning; /**< True if we use dynamic pair-list pruning */
-
- shift_consts_t dispersion_shift; /**< VdW shift dispersion constants */
- shift_consts_t repulsion_shift; /**< VdW shift repulsion constants */
- switch_consts_t vdw_switch; /**< VdW switch constants */
+ //! type of electrostatics, takes values from #eelCu
+ int eeltype;
+ //! type of VdW impl., takes values from #evdwCu
+ int vdwtype;
+
+ //! charge multiplication factor
+ float epsfac;
+ //! Reaction-field/plain cutoff electrostatics const.
+ float c_rf;
+ //! Reaction-field electrostatics constant
+ float two_k_rf;
+ //! Ewald/PME parameter
+ float ewald_beta;
+ //! Ewald/PME correction term substracted from the direct-space potential
+ float sh_ewald;
+ //! LJ-Ewald/PME correction term added to the correction potential
+ float sh_lj_ewald;
+ //! LJ-Ewald/PME coefficient
+ float ewaldcoeff_lj;
+
+ //! Coulomb cut-off squared
+ float rcoulomb_sq;
+
+ //! VdW cut-off squared
+ float rvdw_sq;
+ //! VdW switched cut-off
+ float rvdw_switch;
+ //! Full, outer pair-list cut-off squared
+ float rlistOuter_sq;
+ //! Inner, dynamic pruned pair-list cut-off squared
+ float rlistInner_sq;
+ //! True if we use dynamic pair-list pruning
+ bool useDynamicPruning;
+
+ //! VdW shift dispersion constants
+ shift_consts_t dispersion_shift;
+ //! VdW shift repulsion constants
+ shift_consts_t repulsion_shift;
+ //! VdW switch constants
+ switch_consts_t vdw_switch;
/* LJ non-bonded parameters - accessed through texture memory */
- float* nbfp; /**< nonbonded parameter table with C6/C12 pairs per atom type-pair, 2*ntype^2 elements */
- cudaTextureObject_t nbfp_texobj; /**< texture object bound to nbfp */
- float* nbfp_comb; /**< nonbonded parameter table per atom type, 2*ntype elements */
- cudaTextureObject_t nbfp_comb_texobj; /**< texture object bound to nbfp_texobj */
+ //! nonbonded parameter table with C6/C12 pairs per atom type-pair, 2*ntype^2 elements
+ float* nbfp;
+ //! texture object bound to nbfp
+ cudaTextureObject_t nbfp_texobj;
+ //! nonbonded parameter table per atom type, 2*ntype elements
+ float* nbfp_comb;
+ //! texture object bound to nbfp_texobj
+ cudaTextureObject_t nbfp_comb_texobj;
/* Ewald Coulomb force table data - accessed through texture memory */
- float coulomb_tab_scale; /**< table scale/spacing */
- float* coulomb_tab; /**< pointer to the table in the device memory */
- cudaTextureObject_t coulomb_tab_texobj; /**< texture object bound to coulomb_tab */
+ //! table scale/spacing
+ float coulomb_tab_scale;
+ //! pointer to the table in the device memory
+ float* coulomb_tab;
+ //! texture object bound to coulomb_tab
+ cudaTextureObject_t coulomb_tab_texobj;
};
/** \internal
class GpuEventSynchronizer;
-/** \internal
+/*! \internal
* \brief Main data structure for CUDA nonbonded force calculations.
*/
-struct gmx_nbnxn_cuda_t
+struct NbnxmGpu
{
- //! CUDA device information
- const gmx_device_info_t* dev_info;
- //! true if doing both local/non-local NB work on GPU
- bool bUseTwoStreams;
- //! atom data
- cu_atomdata_t* atdat;
- //! f buf ops cell index mapping
- int* cell;
- //! number of indices in cell buffer
- int ncell;
- //! number of indices allocated in cell buffer
- int ncell_alloc;
- //! array of atom indices
- int* atomIndices;
- //! size of atom indices
- int atomIndicesSize;
- //! size of atom indices allocated in device buffer
- int atomIndicesSize_alloc;
- //! x buf ops num of atoms
- int* cxy_na;
- //! number of elements in cxy_na
- int ncxy_na;
- //! number of elements allocated allocated in device buffer
- int ncxy_na_alloc;
- //! x buf ops cell index mapping
- int* cxy_ind;
- //! number of elements in cxy_ind
- int ncxy_ind;
- //! number of elements allocated allocated in device buffer
- int ncxy_ind_alloc;
- //! parameters required for the non-bonded calc.
- cu_nbparam_t* nbparam;
- //! pair-list data structures (local and non-local)
- gmx::EnumerationArray<Nbnxm::InteractionLocality, cu_plist_t*> plist;
- //! staging area where fshift/energies get downloaded
+ /*! \brief GPU device context.
+ *
+ * \todo Make it constant reference, once NbnxmGpu is a proper class.
+ */
+ const DeviceContext* deviceContext_;
+ /*! \brief true if doing both local/non-local NB work on GPU */
+ bool bUseTwoStreams = false;
+ /*! \brief atom data */
+ cu_atomdata_t* atdat = nullptr;
+ /*! \brief f buf ops cell index mapping */
+ int* cell = nullptr;
+ /*! \brief number of indices in cell buffer */
+ int ncell = 0;
+ /*! \brief number of indices allocated in cell buffer */
+ int ncell_alloc = 0;
+ /*! \brief array of atom indices */
+ int* atomIndices = nullptr;
+ /*! \brief size of atom indices */
+ int atomIndicesSize = 0;
+ /*! \brief size of atom indices allocated in device buffer */
+ int atomIndicesSize_alloc = 0;
+ /*! \brief x buf ops num of atoms */
+ int* cxy_na = nullptr;
+ /*! \brief number of elements in cxy_na */
+ int ncxy_na = 0;
+ /*! \brief number of elements allocated allocated in device buffer */
+ int ncxy_na_alloc = 0;
+ /*! \brief x buf ops cell index mapping */
+ int* cxy_ind = nullptr;
+ /*! \brief number of elements in cxy_ind */
+ int ncxy_ind = 0;
+ /*! \brief number of elements allocated allocated in device buffer */
+ int ncxy_ind_alloc = 0;
+ /*! \brief parameters required for the non-bonded calc. */
+ cu_nbparam_t* nbparam = nullptr;
+ /*! \brief pair-list data structures (local and non-local) */
+ gmx::EnumerationArray<Nbnxm::InteractionLocality, cu_plist_t*> plist = { { nullptr } };
+ /*! \brief staging area where fshift/energies get downloaded */
nb_staging_t nbst;
- //! local and non-local GPU streams
- gmx::EnumerationArray<Nbnxm::InteractionLocality, cudaStream_t> stream;
-
- /** events used for synchronization */
- cudaEvent_t nonlocal_done; /**< event triggered when the non-local non-bonded kernel
- is done (and the local transfer can proceed) */
- cudaEvent_t misc_ops_and_local_H2D_done; /**< event triggered when the tasks issued in
- the local stream that need to precede the
- non-local force or buffer operation calculations are
- done (e.g. f buffer 0-ing, local x/q H2D, buffer op
- initialization in local stream that is required also
- by nonlocal stream ) */
-
- //! True if there has been local/nonlocal GPU work, either bonded or nonbonded, scheduled
- // to be executed in the current domain. As long as bonded work is not split up into
- // local/nonlocal, if there is bonded GPU work, both flags will be true.
- gmx::EnumerationArray<Nbnxm::InteractionLocality, bool> haveWork;
-
- /*! \brief Pointer to event synchronizer triggered when the local GPU buffer ops / reduction is complete
+ /*! \brief local and non-local GPU streams */
+ gmx::EnumerationArray<Nbnxm::InteractionLocality, const DeviceStream*> deviceStreams;
+
+ /*! \brief Events used for synchronization */
+ /*! \{ */
+ /*! \brief Event triggered when the non-local non-bonded
+ * kernel is done (and the local transfer can proceed) */
+ cudaEvent_t nonlocal_done = nullptr;
+ /*! \brief Event triggered when the tasks issued in the local
+ * stream that need to precede the non-local force or buffer
+ * operation calculations are done (e.g. f buffer 0-ing, local
+ * x/q H2D, buffer op initialization in local stream that is
+ * required also by nonlocal stream ) */
+ cudaEvent_t misc_ops_and_local_H2D_done = nullptr;
+ /*! \} */
+
+ /*! \brief True if there is work for the current domain in the
+ * respective locality.
+ *
+ * This includes local/nonlocal GPU work, either bonded or
+ * nonbonded, scheduled to be executed in the current
+ * domain. As long as bonded work is not split up into
+ * local/nonlocal, if there is bonded GPU work, both flags
+ * will be true. */
+ gmx::EnumerationArray<Nbnxm::InteractionLocality, bool> haveWork = { { false } };
+
+ /*! \brief Pointer to event synchronizer triggered when the local
+ * GPU buffer ops / reduction is complete
*
- * \note That the synchronizer is managed outside of this module in StatePropagatorDataGpu.
+ * \note That the synchronizer is managed outside of this module
+ * in StatePropagatorDataGpu.
*/
- GpuEventSynchronizer* localFReductionDone;
+ GpuEventSynchronizer* localFReductionDone = nullptr;
- GpuEventSynchronizer* xNonLocalCopyD2HDone; /**< event triggered when
- non-local coordinate buffer has been
- copied from device to host*/
+ /*! \brief Event triggered when non-local coordinate buffer
+ * has been copied from device to host. */
+ GpuEventSynchronizer* xNonLocalCopyD2HDone = nullptr;
/* NOTE: With current CUDA versions (<=5.0) timing doesn't work with multiple
* concurrent streams, so we won't time if both l/nl work is done on GPUs.
* Timer init/uninit is still done even with timing off so only the condition
* setting bDoTime needs to be change if this CUDA "feature" gets fixed. */
- //! True if event-based timing is enabled.
- bool bDoTime;
- //! CUDA event-based timers.
- cu_timers_t* timers;
- //! Timing data. TODO: deprecate this and query timers for accumulated data instead
- gmx_wallclock_gpu_nbnxn_t* timings;
+ /*! \brief True if event-based timing is enabled. */
+ bool bDoTime = false;
+ /*! \brief CUDA event-based timers. */
+ cu_timers_t* timers = nullptr;
+ /*! \brief Timing data. TODO: deprecate this and query timers for accumulated data instead */
+ gmx_wallclock_gpu_nbnxn_t* timings = nullptr;
};
#endif /* NBNXN_CUDA_TYPES_H */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//NOLINTNEXTLINE(misc-definitions-in-headers)
-void setupGpuShortRangeWork(gmx_nbnxn_gpu_t* nb,
- const gmx::GpuBonded* gpuBonded,
- const gmx::InteractionLocality iLocality)
+void setupGpuShortRangeWork(NbnxmGpu* nb, const gmx::GpuBonded* gpuBonded, const gmx::InteractionLocality iLocality)
{
GMX_ASSERT(nb, "Need a valid nbnxn_gpu object");
* \param[inout] nb Pointer to the nonbonded GPU data structure
* \param[in] iLocality Interaction locality identifier
*/
-static bool haveGpuShortRangeWork(const gmx_nbnxn_gpu_t& nb, const gmx::InteractionLocality iLocality)
+static bool haveGpuShortRangeWork(const NbnxmGpu& nb, const gmx::InteractionLocality iLocality)
{
return nb.haveWork[iLocality];
}
//NOLINTNEXTLINE(misc-definitions-in-headers)
-bool haveGpuShortRangeWork(const gmx_nbnxn_gpu_t* nb, const gmx::AtomLocality aLocality)
+bool haveGpuShortRangeWork(const NbnxmGpu* nb, const gmx::AtomLocality aLocality)
{
GMX_ASSERT(nb, "Need a valid nbnxn_gpu object");
* \todo Move into shared source file with gmx_compile_cpp_as_cuda
*/
//NOLINTNEXTLINE(misc-definitions-in-headers)
-bool gpu_try_finish_task(gmx_nbnxn_gpu_t* nb,
+bool gpu_try_finish_task(NbnxmGpu* nb,
const gmx::StepWorkload& stepWork,
const AtomLocality aloc,
real* e_lj,
// GpuTaskCompletion::Wait mode the timing is expected to be done in the caller.
wallcycle_start_nocount(wcycle, ewcWAIT_GPU_NB_L);
- if (!haveStreamTasksCompleted(nb->stream[iLocality]))
+ if (!haveStreamTasksCompleted(*nb->deviceStreams[iLocality]))
{
wallcycle_stop(wcycle, ewcWAIT_GPU_NB_L);
}
else if (haveResultToWaitFor)
{
- gpuStreamSynchronize(nb->stream[iLocality]);
+ nb->deviceStreams[iLocality]->synchronize();
}
// TODO: this needs to be moved later because conditional wait could brake timing
// with a future OpenCL implementation, but with CUDA timing is anyway disabled
// in all cases where we skip the wait.
- gpu_accumulate_timings(nb->timings, nb->timers, nb->plist[iLocality], aloc, stepWork,
- nb->bDoTime != 0);
+ gpu_accumulate_timings(nb->timings, nb->timers, nb->plist[iLocality], aloc, stepWork, nb->bDoTime);
if (stepWork.computeEnergy || stepWork.computeVirial)
{
* \return The number of cycles the gpu wait took
*/
//NOLINTNEXTLINE(misc-definitions-in-headers) TODO: move into source file
-float gpu_wait_finish_task(gmx_nbnxn_gpu_t* nb,
+float gpu_wait_finish_task(NbnxmGpu* nb,
const gmx::StepWorkload& stepWork,
AtomLocality aloc,
real* e_lj,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* local part of the force array also depends on the non-local kernel.
* The skip of the local kernel is taken care of separately.
*/
-static inline bool canSkipNonbondedWork(const gmx_nbnxn_gpu_t& nb, InteractionLocality iloc)
+static inline bool canSkipNonbondedWork(const NbnxmGpu& nb, InteractionLocality iloc)
{
assert(nb.plist[iloc]);
return (iloc == InteractionLocality::NonLocal && nb.plist[iloc]->nsci == 0);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
+#include "gromacs/gpu_utils/devicebuffer_datatype.h"
#include "gromacs/gpu_utils/gpu_macros.h"
-#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/locality.h"
-#include "gpu_types.h"
-
-struct NbnxnPairlistGpu;
+struct NbnxmGpu;
+struct gmx_gpu_info_t;
+struct DeviceInformation;
+struct gmx_wallclock_gpu_nbnxn_t;
struct nbnxn_atomdata_t;
+struct NbnxnPairlistGpu;
struct PairlistParams;
-struct gmx_wallclock_gpu_nbnxn_t;
-struct gmx_gpu_info_t;
-struct gmx_device_info_t;
+struct interaction_const_t;
+
+class DeviceStream;
+
+namespace gmx
+{
+class DeviceStreamManager;
+}
namespace Nbnxm
{
/** Initializes the data structures related to GPU nonbonded calculations. */
GPU_FUNC_QUALIFIER
-gmx_nbnxn_gpu_t* gpu_init(const gmx_device_info_t gmx_unused* deviceInfo,
- const interaction_const_t gmx_unused* ic,
- const PairlistParams gmx_unused& listParams,
- const nbnxn_atomdata_t gmx_unused* nbat,
- int gmx_unused rank,
- /* true if both local and non-local are done on GPU */
- gmx_bool gmx_unused bLocalAndNonlocal) GPU_FUNC_TERM_WITH_RETURN(nullptr);
+NbnxmGpu* gpu_init(const gmx::DeviceStreamManager gmx_unused& deviceStreamManager,
+ const interaction_const_t gmx_unused* ic,
+ const PairlistParams gmx_unused& listParams,
+ const nbnxn_atomdata_t gmx_unused* nbat,
+ /* true if both local and non-local are done on GPU */
+ bool gmx_unused bLocalAndNonlocal) GPU_FUNC_TERM_WITH_RETURN(nullptr);
/** Initializes pair-list data for GPU, called at every pair search step. */
GPU_FUNC_QUALIFIER
-void gpu_init_pairlist(gmx_nbnxn_gpu_t gmx_unused* nb,
+void gpu_init_pairlist(NbnxmGpu gmx_unused* nb,
const struct NbnxnPairlistGpu gmx_unused* h_nblist,
gmx::InteractionLocality gmx_unused iloc) GPU_FUNC_TERM;
/** Initializes atom-data on the GPU, called at every pair search step. */
GPU_FUNC_QUALIFIER
-void gpu_init_atomdata(gmx_nbnxn_gpu_t gmx_unused* nb, const nbnxn_atomdata_t gmx_unused* nbat) GPU_FUNC_TERM;
+void gpu_init_atomdata(NbnxmGpu gmx_unused* nb, const nbnxn_atomdata_t gmx_unused* nbat) GPU_FUNC_TERM;
/*! \brief Re-generate the GPU Ewald force table, resets rlist, and update the
* electrostatic type switching to twin cut-off (or back) if needed.
/** Uploads shift vector to the GPU if the box is dynamic (otherwise just returns). */
GPU_FUNC_QUALIFIER
-void gpu_upload_shiftvec(gmx_nbnxn_gpu_t gmx_unused* nb, const nbnxn_atomdata_t gmx_unused* nbatom) GPU_FUNC_TERM;
+void gpu_upload_shiftvec(NbnxmGpu gmx_unused* nb, const nbnxn_atomdata_t gmx_unused* nbatom) GPU_FUNC_TERM;
/** Clears GPU outputs: nonbonded force, shift force and energy. */
GPU_FUNC_QUALIFIER
-void gpu_clear_outputs(gmx_nbnxn_gpu_t gmx_unused* nb, bool gmx_unused computeVirial) GPU_FUNC_TERM;
+void gpu_clear_outputs(NbnxmGpu gmx_unused* nb, bool gmx_unused computeVirial) GPU_FUNC_TERM;
/** Frees all GPU resources used for the nonbonded calculations. */
GPU_FUNC_QUALIFIER
-void gpu_free(gmx_nbnxn_gpu_t gmx_unused* nb) GPU_FUNC_TERM;
+void gpu_free(NbnxmGpu gmx_unused* nb) GPU_FUNC_TERM;
/** Returns the GPU timings structure or NULL if GPU is not used or timing is off. */
GPU_FUNC_QUALIFIER
-struct gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(gmx_nbnxn_gpu_t gmx_unused* nb)
+struct gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(NbnxmGpu gmx_unused* nb)
GPU_FUNC_TERM_WITH_RETURN(nullptr);
/** Resets nonbonded GPU timings. */
/** Calculates the minimum size of proximity lists to improve SM load balance
* with GPU non-bonded kernels. */
GPU_FUNC_QUALIFIER
-int gpu_min_ci_balanced(gmx_nbnxn_gpu_t gmx_unused* nb) GPU_FUNC_TERM_WITH_RETURN(-1);
+int gpu_min_ci_balanced(NbnxmGpu gmx_unused* nb) GPU_FUNC_TERM_WITH_RETURN(-1);
/** Returns if analytical Ewald GPU kernels are used. */
GPU_FUNC_QUALIFIER
-gmx_bool gpu_is_kernel_ewald_analytical(const gmx_nbnxn_gpu_t gmx_unused* nb)
- GPU_FUNC_TERM_WITH_RETURN(FALSE);
+gmx_bool gpu_is_kernel_ewald_analytical(const NbnxmGpu gmx_unused* nb) GPU_FUNC_TERM_WITH_RETURN(FALSE);
/** Returns an opaque pointer to the GPU command stream
* Note: CUDA only.
*/
CUDA_FUNC_QUALIFIER
-void* gpu_get_command_stream(gmx_nbnxn_gpu_t gmx_unused* nb, gmx::InteractionLocality gmx_unused iloc)
+const DeviceStream* gpu_get_command_stream(NbnxmGpu gmx_unused* nb, gmx::InteractionLocality gmx_unused iloc)
CUDA_FUNC_TERM_WITH_RETURN(nullptr);
/** Returns an opaque pointer to the GPU coordinate+charge array
* Note: CUDA only.
*/
CUDA_FUNC_QUALIFIER
-void* gpu_get_xq(gmx_nbnxn_gpu_t gmx_unused* nb) CUDA_FUNC_TERM_WITH_RETURN(nullptr);
+void* gpu_get_xq(NbnxmGpu gmx_unused* nb) CUDA_FUNC_TERM_WITH_RETURN(nullptr);
/** Returns an opaque pointer to the GPU force array
* Note: CUDA only.
*/
CUDA_FUNC_QUALIFIER
-void* gpu_get_f(gmx_nbnxn_gpu_t gmx_unused* nb) CUDA_FUNC_TERM_WITH_RETURN(nullptr);
+DeviceBuffer<gmx::RVec> gpu_get_f(NbnxmGpu gmx_unused* nb)
+ CUDA_FUNC_TERM_WITH_RETURN(DeviceBuffer<gmx::RVec>{});
/** Returns an opaque pointer to the GPU shift force array
* Note: CUDA only.
*/
CUDA_FUNC_QUALIFIER
-rvec* gpu_get_fshift(gmx_nbnxn_gpu_t gmx_unused* nb) CUDA_FUNC_TERM_WITH_RETURN(nullptr);
+DeviceBuffer<gmx::RVec> gpu_get_fshift(NbnxmGpu gmx_unused* nb)
+ CUDA_FUNC_TERM_WITH_RETURN(DeviceBuffer<gmx::RVec>{});
} // namespace Nbnxm
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
-#include "gpu_types.h"
+struct NbnxmGpu;
/*! \brief Handles any JIT compilation of nbnxn kernels for the selected device */
-OPENCL_FUNC_QUALIFIER void nbnxn_gpu_compile_kernels(gmx_nbnxn_gpu_t gmx_unused* nb) OPENCL_FUNC_TERM;
+OPENCL_FUNC_QUALIFIER void nbnxn_gpu_compile_kernels(NbnxmGpu gmx_unused* nb) OPENCL_FUNC_TERM;
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
struct XFTransfers
{
- GpuRegionTimer nb_h2d; /**< timer for x/q H2D transfers (l/nl, every step) */
- GpuRegionTimer nb_d2h; /**< timer for f D2H transfer (l/nl, every step) */
+ //! timer for x/q H2D transfers (l/nl, every step)
+ GpuRegionTimer nb_h2d;
+ //! timer for f D2H transfer (l/nl, every step)
+ GpuRegionTimer nb_d2h;
};
/*! \internal
*/
struct Interaction
{
- GpuRegionTimer pl_h2d; /**< timer for pair-list H2D transfers (l/nl, every PS step) */
- bool didPairlistH2D = false; /**< true when a pair-list transfer has been done at this step */
- GpuRegionTimer nb_k; /**< timer for non-bonded kernels (l/nl, every step) */
- GpuRegionTimer prune_k; /**< timer for the 1st pass list pruning kernel (l/nl, every PS step) */
- bool didPrune = false; /**< true when we timed pruning and the timings need to be accounted for */
- GpuRegionTimer rollingPrune_k; /**< timer for rolling pruning kernels (l/nl, frequency depends on chunk size) */
- bool didRollingPrune =
- false; /**< true when we timed rolling pruning (at the previous step) and the timings need to be accounted for */
+ //! timer for pair-list H2D transfers (l/nl, every PS step)
+ GpuRegionTimer pl_h2d;
+ //! true when a pair-list transfer has been done at this step
+ bool didPairlistH2D = false;
+ //! timer for non-bonded kernels (l/nl, every step)
+ GpuRegionTimer nb_k;
+ //! timer for the 1st pass list pruning kernel (l/nl, every PS step)
+ GpuRegionTimer prune_k;
+ //! true when we timed pruning and the timings need to be accounted for
+ bool didPrune = false;
+ //! timer for rolling pruning kernels (l/nl, frequency depends on chunk size)
+ GpuRegionTimer rollingPrune_k;
+ //! true when we timed rolling pruning (at the previous step) and the timings need to be accounted for
+ bool didRollingPrune = false;
};
//! timer for atom data transfer (every PS step)
gmx::EnumerationArray<InteractionLocality, Nbnxm::gpu_timers_t::Interaction> interaction;
};
+/*! \internal
+ * \brief GPU pair list structure */
struct gpu_plist
{
- int na_c; /**< number of atoms per cluster */
-
- int nsci; /**< size of sci, # of i clusters in the list */
- int sci_nalloc; /**< allocation size of sci */
- DeviceBuffer<nbnxn_sci_t> sci; /**< list of i-cluster ("super-clusters") */
-
- int ncj4; /**< total # of 4*j clusters */
- int cj4_nalloc; /**< allocation size of cj4 */
- DeviceBuffer<nbnxn_cj4_t> cj4; /**< 4*j cluster list, contains j cluster number
- and index into the i cluster list */
- int nimask; /**< # of 4*j clusters * # of warps */
- int imask_nalloc; /**< allocation size of imask */
- DeviceBuffer<unsigned int> imask; /**< imask for 2 warps for each 4*j cluster group */
- DeviceBuffer<nbnxn_excl_t> excl; /**< atom interaction bits */
- int nexcl; /**< count for excl */
- int excl_nalloc; /**< allocation size of excl */
+ //! number of atoms per cluster
+ int na_c;
+
+ //! size of sci, # of i clusters in the list
+ int nsci;
+ //! allocation size of sci
+ int sci_nalloc;
+ //! list of i-cluster ("super-clusters")
+ DeviceBuffer<nbnxn_sci_t> sci;
+
+ //! total # of 4*j clusters
+ int ncj4;
+ //! allocation size of cj4
+ int cj4_nalloc;
+ //! 4*j cluster list, contains j cluster number and index into the i cluster list
+ DeviceBuffer<nbnxn_cj4_t> cj4;
+ //! # of 4*j clusters * # of warps
+ int nimask;
+ //! allocation size of imask
+ int imask_nalloc;
+ //! imask for 2 warps for each 4*j cluster group
+ DeviceBuffer<unsigned int> imask;
+ //! atom interaction bits
+ DeviceBuffer<nbnxn_excl_t> excl;
+ //! count for excl
+ int nexcl;
+ //! allocation size of excl
+ int excl_nalloc;
/* parameter+variables for normal and rolling pruning */
- bool haveFreshList; /**< true after search, indictes that initial pruning with outer prunning is needed */
- int rollingPruningNumParts; /**< the number of parts/steps over which one cyle of roling pruning takes places */
- int rollingPruningPart; /**< the next part to which the roling pruning needs to be applied */
+ //! true after search, indictes that initial pruning with outer prunning is needed
+ bool haveFreshList;
+ //! the number of parts/steps over which one cyle of roling pruning takes places
+ int rollingPruningNumParts;
+ //! the next part to which the roling pruning needs to be applied
+ int rollingPruningPart;
};
} // namespace Nbnxm
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/updategroupscog.h"
#include "gromacs/mdtypes/forcerec.h" // only for GET_CGINFO_*
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/simd/simd.h"
#include "gromacs/simd/vector_operations.h"
-#include "atomdata.h"
#include "boundingboxes.h"
#include "gridsetdata.h"
#include "nbnxm_geometry.h"
//! Returns a pointer for SIMD storing of a Corner object
float* ptr() { return &x; }
- float x; //!< x coordinate
- float y; //!< y coordinate
- float z; //!< z coordinate
- float padding; //!< padding, unused, but should be set to avoid operations on unitialized data
+ //! x coordinate
+ float x;
+ //! y coordinate
+ float y;
+ //! z coordinate
+ float z;
+ //! padding, unused, but should be set to avoid operations on unitialized data
+ float padding;
};
- Corner lower; //!< lower, along x and y and z, corner
- Corner upper; //!< upper, along x and y and z, corner
+ //! lower, along x and y and z, corner
+ Corner lower;
+ //! upper, along x and y and z, corner
+ Corner upper;
};
/*! \internal
*/
struct BoundingBox1D
{
- float lower; //!< lower bound
- float upper; //!< upper bound
+ //! lower bound
+ float lower;
+ //! upper bound
+ float upper;
};
} // namespace Nbnxm
//! Constructs the cluster/cell geometry given the type of pairlist
Geometry(PairlistType pairlistType);
- bool isSimple; //!< Is this grid simple (CPU) or hierarchical (GPU)
- int numAtomsICluster; //!< Number of atoms per cluster
- int numAtomsJCluster; //!< Number of atoms for list j-clusters
- int numAtomsPerCell; //!< Number of atoms per cell
- int numAtomsICluster2Log; //!< 2log of na_c
+ //! Is this grid simple (CPU) or hierarchical (GPU)
+ bool isSimple;
+ //! Number of atoms per cluster
+ int numAtomsICluster;
+ //! Number of atoms for list j-clusters
+ int numAtomsJCluster;
+ //! Number of atoms per cell
+ int numAtomsPerCell;
+ //! 2log of na_c
+ int numAtomsICluster2Log;
};
- // The physical dimensions of a grid
+ //! The physical dimensions of a grid \internal
struct Dimensions
{
//! The lower corner of the (local) grid
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdlib/updategroupscog.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/utility/fatalerror.h"
-#include "atomdata.h"
-
namespace Nbnxm
{
return numGrids;
}
-GridSet::DomainSetup::DomainSetup(const int ePBC,
+GridSet::DomainSetup::DomainSetup(const PbcType pbcType,
const bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* ddZones) :
- ePBC(ePBC),
+ pbcType(pbcType),
doTestParticleInsertion(doTestParticleInsertion),
haveMultipleDomains(numDDCells != nullptr),
zones(ddZones)
}
}
-GridSet::GridSet(const int ePBC,
+GridSet::GridSet(const PbcType pbcType,
const bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* ddZones,
const bool haveFep,
const int numThreads,
gmx::PinningPolicy pinningPolicy) :
- domainSetup_(ePBC, doTestParticleInsertion, numDDCells, ddZones),
+ domainSetup_(pbcType, doTestParticleInsertion, numDDCells, ddZones),
grids_(numGrids(domainSetup_), Grid(pairlistType, haveFep_)),
haveFep_(haveFep),
numRealAtomsLocal_(0),
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct nbnxn_atomdata_t;
enum class PairlistType;
+enum class PbcType : int;
namespace gmx
{
struct DomainSetup
{
//! Constructor, without DD \p numDDCells and \p ddZones should be nullptr
- DomainSetup(int ePBC,
+ DomainSetup(PbcType pbcType,
bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* ddZones);
//! The type of PBC
- int ePBC;
+ PbcType pbcType;
//! Tells whether we are doing test-particle insertion
bool doTestParticleInsertion;
//! Are there multiple domains?
};
//! Constructs a grid set for 1 or multiple DD zones, when numDDCells!=nullptr
- GridSet(int ePBC,
+ GridSet(PbcType pbcType,
bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* ddZones,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <vector>
+#include "gromacs/gpu_utils/hostallocator.h"
namespace Nbnxm
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vectypes.h"
/* nbnxn_atomdata_t and nbnxn_pairlist_t could be forward declared, but that requires modifications in all SIMD kernel files */
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/utility/real.h"
-#include "atomdata.h"
#include "pairlist.h"
struct interaction_const_t;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/forceoutput.h"
+#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/utility/real.h"
#include "kernel_common.h"
+#include "nbnxm_gpu.h"
#include "nbnxm_simd.h"
#include "pairlistset.h"
#include "pairlistsets.h"
kernel_data.flags = (donb_flags & ~(GMX_NONBONDED_DO_FORCE | GMX_NONBONDED_DO_SHIFTFORCE))
| GMX_NONBONDED_DO_FOREIGNLAMBDA;
kernel_data.lambda = lam_i;
+ kernel_data.dvdl = dvdl_nb;
kernel_data.energygrp_elec = enerd->foreign_grpp.ener[egCOULSR].data();
kernel_data.energygrp_vdw = enerd->foreign_grpp.ener[egLJSR].data();
- /* Note that we add to kernel_data.dvdl, but ignore the result */
for (size_t i = 0; i < enerd->enerpart_lambda.size(); i++)
{
+ std::fill(std::begin(dvdl_nb), std::end(dvdl_nb), 0);
for (int j = 0; j < efptNR; j++)
{
lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i - 1]);
sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
+ enerd->dhdlLambda[i] += dvdl_nb[efptVDW] + dvdl_nb[efptCOUL];
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < enerd->enerpart_lambda.size(); i++)
+ {
+ enerd->dhdlLambda[i] += dvdl_nb[efptVDW] + dvdl_nb[efptCOUL];
}
}
wallcycle_sub_stop(wcycle_, ewcsNONBONDED_FEP);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/functions.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/simulation_workload.h"
#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/pbcutil/ishift.h"
#include "gromacs/utility/fatalerror.h"
-static const int c_numClPerSupercl = c_nbnxnGpuNumClusterPerSupercluster;
-static const int c_clSize = c_nbnxnGpuClusterSize;
+static constexpr int c_clSize = c_nbnxnGpuClusterSize;
void nbnxn_kernel_gpu_ref(const NbnxnPairlistGpu* nbl,
const nbnxn_atomdata_t* nbat,
vctot = 0;
Vvdwtot = 0;
- if (nbln.shift == CENTRAL && nbl->cj4[cj4_ind0].cj[0] == sci * c_numClPerSupercl)
+ if (nbln.shift == CENTRAL && nbl->cj4[cj4_ind0].cj[0] == sci * c_nbnxnGpuNumClusterPerSupercluster)
{
/* we have the diagonal:
* add the charge self interaction energy term
*/
- for (im = 0; im < c_numClPerSupercl; im++)
+ for (im = 0; im < c_nbnxnGpuNumClusterPerSupercluster; im++)
{
- ci = sci * c_numClPerSupercl + im;
+ ci = sci * c_nbnxnGpuNumClusterPerSupercluster + im;
for (ic = 0; ic < c_clSize; ic++)
{
ia = ci * c_clSize + ic;
{
cj = nbl->cj4[cj4_ind].cj[jm];
- for (im = 0; im < c_numClPerSupercl; im++)
+ for (im = 0; im < c_nbnxnGpuNumClusterPerSupercluster; im++)
{
/* We're only using the first imask,
* but here imei[1].imask is identical.
*/
- if ((nbl->cj4[cj4_ind].imei[0].imask >> (jm * c_numClPerSupercl + im)) & 1)
+ if ((nbl->cj4[cj4_ind].imei[0].imask >> (jm * c_nbnxnGpuNumClusterPerSupercluster + im))
+ & 1)
{
gmx_bool within_rlist;
- ci = sci * c_numClPerSupercl + im;
+ ci = sci * c_nbnxnGpuNumClusterPerSupercluster + im;
within_rlist = FALSE;
npair = 0;
c_nbnxnGpuClusterSize / c_nbnxnGpuClusterpairSplit;
int_bit = static_cast<real>(
(excl[jc / clusterPerSplit]->pair[(jc & (clusterPerSplit - 1)) * c_clSize + ic]
- >> (jm * c_numClPerSupercl + im))
+ >> (jm * c_nbnxnGpuNumClusterPerSupercluster + im))
& 1);
js = ja * nbat->xstride;
}
// Ensure distance do not become so small that r^-12 overflows
- rsq = std::max(rsq, NBNXN_MIN_RSQ);
+ rsq = std::max(rsq, c_nbnxnMinDistanceSquared);
rinv = gmx::invsqrt(rsq);
rinvsq = rinv * rinv;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ *
+ * \brief
+ * Declares GPU reference kernel
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
-#ifndef _nbnxn_kernel_gpu_ref_h
-#define _nbnxn_kernel_gpu_ref_h
+#ifndef GMX_NBNXM_KERNELS_REFERENCE_KERNEL_GPU_REF_H
+#define GMX_NBNXM_KERNELS_REFERENCE_KERNEL_GPU_REF_H
#include "gromacs/math/vectypes.h"
-#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/real.h"
struct NbnxnPairlistGpu;
struct nbnxn_atomdata_t;
+struct interaction_const_t;
+struct t_forcerec;
namespace gmx
{
class StepWorkload;
}
-/* Reference (slow) kernel for nb n vs n GPU type pair lists */
+//! Reference (slow) kernel for nb n vs n GPU type pair lists
void nbnxn_kernel_gpu_ref(const NbnxnPairlistGpu* nbl,
const nbnxn_atomdata_t* nbat,
const interaction_const_t* iconst,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 The GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ *
+ * \brief
+ * Declares CPU reference kernels
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
+#ifndef GMX_NBNXM_KERNELS_REFERENCE_KERNEL_REF_H
+#define GMX_NBNXM_KERNELS_REFERENCE_KERNEL_REF_H
#include "gromacs/nbnxm/kernel_common.h"
-/* Declare all the different kernel functions.
- */
+//! All the different CPU reference kernel functions.
+//! \{
nbk_func_noener nbnxn_kernel_ElecRF_VdwLJ_F_ref;
nbk_func_noener nbnxn_kernel_ElecRF_VdwLJFsw_F_ref;
nbk_func_noener nbnxn_kernel_ElecRF_VdwLJPsw_F_ref;
nbk_func_ener nbnxn_kernel_ElecQSTabTwinCut_VdwLJPsw_VgrpF_ref;
nbk_func_ener nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VgrpF_ref;
nbk_func_ener nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombLB_VgrpF_ref;
+//! \}
#ifdef INCLUDE_KERNELFUNCTION_TABLES
-/* Declare and define the kernel function pointer lookup tables.
+/*! \brief Declare and define the kernel function pointer lookup tables.
+ *
* The minor index of the array goes over both the LJ combination rules,
* which is only supported by plain cut-off, and the LJ switch/PME functions.
* For the C reference kernels, unlike the SIMD kernels, there is not much
* advantage in using combination rules, so we (re-)use the same kernel.
*/
+//! \{
static p_nbk_func_noener nbnxn_kernel_noener_ref[coulktNR][vdwktNR_ref] = {
{ nbnxn_kernel_ElecRF_VdwLJ_F_ref, nbnxn_kernel_ElecRF_VdwLJ_F_ref, nbnxn_kernel_ElecRF_VdwLJ_F_ref,
nbnxn_kernel_ElecRF_VdwLJFsw_F_ref, nbnxn_kernel_ElecRF_VdwLJPsw_F_ref,
nbnxn_kernel_ElecQSTabTwinCut_VdwLJPsw_VgrpF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VgrpF_ref,
nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombLB_VgrpF_ref }
};
+//! \}
#endif /* INCLUDE_KERNELFUNCTION_TABLES */
+
+#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Ensure the distances do not fall below the limit where r^-12 overflows.
// This should never happen for normal interactions.
- rsq = std::max(rsq, NBNXN_MIN_RSQ);
+ rsq = std::max(rsq, c_nbnxnMinDistanceSquared);
#ifdef COUNT_PAIRS
npair++;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2020, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+if (GMX_USE_SIMD_KERNELS)
+ file(GLOB KERNEL_SOURCES
+ kernel_ElecEwTwinCut_VdwLJCombGeom_F.cpp
+ kernel_ElecEwTwinCut_VdwLJCombGeom_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_F.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_F.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_F.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_F.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_F.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_VgrpF.cpp
+ kernel_ElecEw_VdwLJCombGeom_F.cpp
+ kernel_ElecEw_VdwLJCombGeom_VF.cpp
+ kernel_ElecEw_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecEw_VdwLJCombLB_F.cpp
+ kernel_ElecEw_VdwLJCombLB_VF.cpp
+ kernel_ElecEw_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_F.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecEw_VdwLJ_F.cpp
+ kernel_ElecEw_VdwLJFSw_F.cpp
+ kernel_ElecEw_VdwLJFSw_VF.cpp
+ kernel_ElecEw_VdwLJFSw_VgrpF.cpp
+ kernel_ElecEw_VdwLJPSw_F.cpp
+ kernel_ElecEw_VdwLJPSw_VF.cpp
+ kernel_ElecEw_VdwLJPSw_VgrpF.cpp
+ kernel_ElecEw_VdwLJ_VF.cpp
+ kernel_ElecEw_VdwLJ_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_F.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_VF.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJCombLB_F.cpp
+ kernel_ElecQSTab_VdwLJCombLB_VF.cpp
+ kernel_ElecQSTab_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_F.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJ_F.cpp
+ kernel_ElecQSTab_VdwLJFSw_F.cpp
+ kernel_ElecQSTab_VdwLJFSw_VF.cpp
+ kernel_ElecQSTab_VdwLJFSw_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJPSw_F.cpp
+ kernel_ElecQSTab_VdwLJPSw_VF.cpp
+ kernel_ElecQSTab_VdwLJPSw_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJ_VF.cpp
+ kernel_ElecQSTab_VdwLJ_VgrpF.cpp
+ kernel_ElecRF_VdwLJCombGeom_F.cpp
+ kernel_ElecRF_VdwLJCombGeom_VF.cpp
+ kernel_ElecRF_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecRF_VdwLJCombLB_F.cpp
+ kernel_ElecRF_VdwLJCombLB_VF.cpp
+ kernel_ElecRF_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_F.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecRF_VdwLJ_F.cpp
+ kernel_ElecRF_VdwLJFSw_F.cpp
+ kernel_ElecRF_VdwLJFSw_VF.cpp
+ kernel_ElecRF_VdwLJFSw_VgrpF.cpp
+ kernel_ElecRF_VdwLJPSw_F.cpp
+ kernel_ElecRF_VdwLJPSw_VF.cpp
+ kernel_ElecRF_VdwLJPSw_VgrpF.cpp
+ kernel_ElecRF_VdwLJ_VF.cpp
+ kernel_ElecRF_VdwLJ_VgrpF.cpp
+ kernel_prune.cpp
+ )
+endif()
+
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${KERNEL_SOURCES} PARENT_SCOPE)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif
#ifdef LJ_EWALD_GEOM
real lj_ewaldcoeff2, lj_ewaldcoeff6_6;
- SimdReal mone_S, half_S, lje_c2_S, lje_c6_6_S;
+ SimdReal half_S, lje_c2_S, lje_c6_6_S;
#endif
#ifdef LJ_COMB_LB
# endif
#endif
#ifdef LJ_EWALD_GEOM
- mone_S = SimdReal(-1.0);
half_S = SimdReal(0.5);
lj_ewaldcoeff2 = ic->ewaldcoeff_lj * ic->ewaldcoeff_lj;
lj_ewaldcoeff6_6 = lj_ewaldcoeff2 * lj_ewaldcoeff2 * lj_ewaldcoeff2 / 6;
rcvdw2_S = SimdReal(ic->rvdw * ic->rvdw);
#endif
- minRsq_S = SimdReal(NBNXN_MIN_RSQ);
+ minRsq_S = SimdReal(c_nbnxnMinDistanceSquared);
const real* gmx_restrict q = nbatParams.q.data();
const real facel = ic->epsfac;
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2020, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+if (GMX_USE_SIMD_KERNELS)
+ file(GLOB KERNEL_SOURCES
+ kernel_ElecEwTwinCut_VdwLJCombGeom_F.cpp
+ kernel_ElecEwTwinCut_VdwLJCombGeom_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_F.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_F.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_F.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_F.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJFSw_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_F.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJPSw_VgrpF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_VF.cpp
+ kernel_ElecEwTwinCut_VdwLJ_VgrpF.cpp
+ kernel_ElecEw_VdwLJCombGeom_F.cpp
+ kernel_ElecEw_VdwLJCombGeom_VF.cpp
+ kernel_ElecEw_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecEw_VdwLJCombLB_F.cpp
+ kernel_ElecEw_VdwLJCombLB_VF.cpp
+ kernel_ElecEw_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_F.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecEw_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecEw_VdwLJ_F.cpp
+ kernel_ElecEw_VdwLJFSw_F.cpp
+ kernel_ElecEw_VdwLJFSw_VF.cpp
+ kernel_ElecEw_VdwLJFSw_VgrpF.cpp
+ kernel_ElecEw_VdwLJPSw_F.cpp
+ kernel_ElecEw_VdwLJPSw_VF.cpp
+ kernel_ElecEw_VdwLJPSw_VgrpF.cpp
+ kernel_ElecEw_VdwLJ_VF.cpp
+ kernel_ElecEw_VdwLJ_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJFSw_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_F.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJPSw_VgrpF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_VF.cpp
+ kernel_ElecQSTabTwinCut_VdwLJ_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_F.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_VF.cpp
+ kernel_ElecQSTab_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJCombLB_F.cpp
+ kernel_ElecQSTab_VdwLJCombLB_VF.cpp
+ kernel_ElecQSTab_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_F.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecQSTab_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJ_F.cpp
+ kernel_ElecQSTab_VdwLJFSw_F.cpp
+ kernel_ElecQSTab_VdwLJFSw_VF.cpp
+ kernel_ElecQSTab_VdwLJFSw_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJPSw_F.cpp
+ kernel_ElecQSTab_VdwLJPSw_VF.cpp
+ kernel_ElecQSTab_VdwLJPSw_VgrpF.cpp
+ kernel_ElecQSTab_VdwLJ_VF.cpp
+ kernel_ElecQSTab_VdwLJ_VgrpF.cpp
+ kernel_ElecRF_VdwLJCombGeom_F.cpp
+ kernel_ElecRF_VdwLJCombGeom_VF.cpp
+ kernel_ElecRF_VdwLJCombGeom_VgrpF.cpp
+ kernel_ElecRF_VdwLJCombLB_F.cpp
+ kernel_ElecRF_VdwLJCombLB_VF.cpp
+ kernel_ElecRF_VdwLJCombLB_VgrpF.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_F.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_VF.cpp
+ kernel_ElecRF_VdwLJEwCombGeom_VgrpF.cpp
+ kernel_ElecRF_VdwLJ_F.cpp
+ kernel_ElecRF_VdwLJFSw_F.cpp
+ kernel_ElecRF_VdwLJFSw_VF.cpp
+ kernel_ElecRF_VdwLJFSw_VgrpF.cpp
+ kernel_ElecRF_VdwLJPSw_F.cpp
+ kernel_ElecRF_VdwLJPSw_VF.cpp
+ kernel_ElecRF_VdwLJPSw_VgrpF.cpp
+ kernel_ElecRF_VdwLJ_VF.cpp
+ kernel_ElecRF_VdwLJ_VgrpF.cpp
+ kernel_prune.cpp
+ )
+endif()
+
+set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${KERNEL_SOURCES} PARENT_SCOPE)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif
#ifdef LJ_EWALD_GEOM
real lj_ewaldcoeff2, lj_ewaldcoeff6_6;
- SimdReal mone_S, half_S, lje_c2_S, lje_c6_6_S;
+ SimdReal half_S, lje_c2_S, lje_c6_6_S;
#endif
#ifdef LJ_COMB_LB
# endif
#endif
#ifdef LJ_EWALD_GEOM
- mone_S = SimdReal(-1.0);
half_S = SimdReal(0.5);
lj_ewaldcoeff2 = ic->ewaldcoeff_lj * ic->ewaldcoeff_lj;
lj_ewaldcoeff6_6 = lj_ewaldcoeff2 * lj_ewaldcoeff2 * lj_ewaldcoeff2 / 6;
rcvdw2_S = SimdReal(ic->rvdw * ic->rvdw);
#endif
- minRsq_S = SimdReal(NBNXN_MIN_RSQ);
+ minRsq_S = SimdReal(c_nbnxnMinDistanceSquared);
const real* gmx_restrict q = nbatParams.q.data();
const real facel = ic->epsfac;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "nbnxm.h"
#include "gromacs/domdec/domdec_struct.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/timing/wallcycle.h"
-#include "atomdata.h"
+#include "nbnxm_gpu.h"
#include "pairlistsets.h"
#include "pairsearch.h"
void nonbonded_verlet_t::convertCoordinatesGpu(const gmx::AtomLocality locality,
const bool fillLocal,
- DeviceBuffer<float> d_x,
+ DeviceBuffer<gmx::RVec> d_x,
GpuEventSynchronizer* xReadyOnDevice)
{
wallcycle_start(wcycle_, ewcNB_XF_BUF_OPS);
/* Skip the reduction if there was no short-range GPU work to do
* (either NB or both NB and bonded work). */
- if (!pairlistIsSimple() && !haveGpuShortRangeWork(locality))
+ if (!pairlistIsSimple() && !Nbnxm::haveGpuShortRangeWork(gpu_nbv, locality))
{
return;
}
}
void nonbonded_verlet_t::atomdata_add_nbat_f_to_f_gpu(const gmx::AtomLocality locality,
- DeviceBuffer<float> totalForcesDevice,
+ DeviceBuffer<gmx::RVec> totalForcesDevice,
void* forcesPmeDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
bool useGpuFPmeReduction,
/* Skip the reduction if there was no short-range GPU work to do
* (either NB or both NB and bonded work). */
- if (!pairlistIsSimple() && !haveGpuShortRangeWork(locality))
+ if (!pairlistIsSimple() && !Nbnxm::haveGpuShortRangeWork(gpu_nbv, locality))
{
return;
}
pairlistSets_->changePairlistRadii(rlistOuter, rlistInner);
}
+void nonbonded_verlet_t::setupGpuShortRangeWork(const gmx::GpuBonded* gpuBonded,
+ const gmx::InteractionLocality iLocality)
+{
+ if (useGpu() && !emulateGpu())
+ {
+ Nbnxm::setupGpuShortRangeWork(gpu_nbv, gpuBonded, iLocality);
+ }
+}
+
void nonbonded_verlet_t::atomdata_init_copy_x_to_nbat_x_gpu()
{
Nbnxm::nbnxn_gpu_init_x_to_nbat_x(pairSearch_->gridSet(), gpu_nbv);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdtypes/locality.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/enumerationhelpers.h"
-#include "gromacs/utility/range.h"
#include "gromacs/utility/real.h"
-// TODO: Remove this include
-#include "nbnxm_gpu.h"
-
-struct gmx_device_info_t;
+struct DeviceInformation;
struct gmx_domdec_zones_t;
struct gmx_enerdata_t;
struct gmx_hw_info_t;
struct gmx_mtop_t;
+struct NbnxmGpu;
struct gmx_wallcycle;
struct interaction_const_t;
+struct nbnxn_atomdata_t;
struct nonbonded_verlet_t;
class PairSearch;
class PairlistSets;
-struct t_blocka;
struct t_commrec;
struct t_lambda;
struct t_mdatoms;
struct t_forcerec;
struct t_inputrec;
-/*! \brief Switch for whether to use GPU for buffer ops*/
-enum class BufferOpsUseGpu
-{
- True,
- False
-};
-
class GpuEventSynchronizer;
namespace gmx
{
+class DeviceStreamManager;
class ForceWithShiftForces;
+class GpuBonded;
+template<typename>
+class ListOfLists;
class MDLogger;
+template<typename>
+class Range;
+class StepWorkload;
class UpdateGroupsCog;
} // namespace gmx
std::unique_ptr<PairSearch> pairSearch,
std::unique_ptr<nbnxn_atomdata_t> nbat,
const Nbnxm::KernelSetup& kernelSetup,
- gmx_nbnxn_gpu_t* gpu_nbv,
+ NbnxmGpu* gpu_nbv,
gmx_wallcycle* wcycle);
~nonbonded_verlet_t();
//! Returns the index position of the atoms on the search grid
gmx::ArrayRef<const int> getGridIndices() const;
- //! Constructs the pairlist for the given locality
- void constructPairlist(gmx::InteractionLocality iLocality, const t_blocka* excl, int64_t step, t_nrnb* nrnb);
+ /*! \brief Constructs the pairlist for the given locality
+ *
+ * When there are no non-self exclusions, \p exclusions can be empty.
+ * Otherwise the number of lists in \p exclusions should match the number
+ * of atoms when not using DD, or the total number of atoms in the i-zones
+ * when using DD.
+ *
+ * \param[in] iLocality The interaction locality: local or non-local
+ * \param[in] exclusions Lists of exclusions for every atom.
+ * \param[in] step Used to set the list creation step
+ * \param[in,out] nrnb Flop accounting struct, can be nullptr
+ */
+ void constructPairlist(gmx::InteractionLocality iLocality,
+ const gmx::ListOfLists<int>& exclusions,
+ int64_t step,
+ t_nrnb* nrnb);
//! Updates all the atom properties in Nbnxm
void setAtomProperties(const t_mdatoms& mdatoms, gmx::ArrayRef<const int> atomInfo);
* \param[in] d_x GPU coordinates buffer in plain rvec format to be transformed.
* \param[in] xReadyOnDevice Event synchronizer indicating that the coordinates are ready in the device memory.
*/
- void convertCoordinatesGpu(gmx::AtomLocality locality,
- bool fillLocal,
- DeviceBuffer<float> d_x,
- GpuEventSynchronizer* xReadyOnDevice);
+ void convertCoordinatesGpu(gmx::AtomLocality locality,
+ bool fillLocal,
+ DeviceBuffer<gmx::RVec> d_x,
+ GpuEventSynchronizer* xReadyOnDevice);
//! Init for GPU version of setup coordinates in Nbnxm
void atomdata_init_copy_x_to_nbat_x_gpu();
* \param [in] accumulateForce If the total force buffer already contains data
*/
void atomdata_add_nbat_f_to_f_gpu(gmx::AtomLocality locality,
- DeviceBuffer<float> totalForcesDevice,
+ DeviceBuffer<gmx::RVec> totalForcesDevice,
void* forcesPmeDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> dependencyList,
bool useGpuFPmeReduction,
void changePairlistRadii(real rlistOuter, real rlistInner);
//! Set up internal flags that indicate what type of short-range work there is.
- void setupGpuShortRangeWork(const gmx::GpuBonded* gpuBonded, const gmx::InteractionLocality iLocality)
- {
- if (useGpu() && !emulateGpu())
- {
- Nbnxm::setupGpuShortRangeWork(gpu_nbv, gpuBonded, iLocality);
- }
- }
-
- //! Returns true if there is GPU short-range work for the given atom locality.
- bool haveGpuShortRangeWork(const gmx::AtomLocality aLocality)
- {
- return ((useGpu() && !emulateGpu()) && Nbnxm::haveGpuShortRangeWork(gpu_nbv, aLocality));
- }
+ void setupGpuShortRangeWork(const gmx::GpuBonded* gpuBonded, gmx::InteractionLocality iLocality);
// TODO: Make all data members private
public:
public:
//! GPU Nbnxm data, only used with a physical GPU (TODO: use unique_ptr)
- gmx_nbnxn_gpu_t* gpu_nbv;
+ NbnxmGpu* gpu_nbv;
};
namespace Nbnxm
{
/*! \brief Creates an Nbnxm object */
-std::unique_ptr<nonbonded_verlet_t> init_nb_verlet(const gmx::MDLogger& mdlog,
- gmx_bool bFEP_NonBonded,
- const t_inputrec* ir,
- const t_forcerec* fr,
- const t_commrec* cr,
- const gmx_hw_info_t& hardwareInfo,
- const gmx_device_info_t* deviceInfo,
- const gmx_mtop_t* mtop,
- matrix box,
- gmx_wallcycle* wcycle);
+std::unique_ptr<nonbonded_verlet_t> init_nb_verlet(const gmx::MDLogger& mdlog,
+ const t_inputrec* ir,
+ const t_forcerec* fr,
+ const t_commrec* cr,
+ const gmx_hw_info_t& hardwareInfo,
+ bool useGpuForNonbonded,
+ const gmx::DeviceStreamManager* deviceStreamManager,
+ const gmx_mtop_t* mtop,
+ matrix box,
+ gmx_wallcycle* wcycle);
} // namespace Nbnxm
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-
+/*! \internal \file
+ *
+ * \brief
+ * Declares the geometry-related functionality
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
#ifndef GMX_NBNXM_NBNXM_GEOMETRY_H
#define GMX_NBNXM_NBNXM_GEOMETRY_H
#include "pairlist.h"
-/* Returns the base-2 log of n.
+/*! \copybrief Returns the base-2 log of n.
+ * *
* Generates a fatal error when n is not an integer power of 2.
*/
static inline int get_2log(int n)
namespace Nbnxm
{
-/* The nbnxn i-cluster size in atoms for each nbnxn kernel type */
+/*! \brief The nbnxn i-cluster size in atoms for each nbnxn kernel type */
static constexpr gmx::EnumerationArray<KernelType, int> IClusterSizePerKernelType = {
{ 0, c_nbnxnCpuIClusterSize, c_nbnxnCpuIClusterSize, c_nbnxnCpuIClusterSize,
c_nbnxnGpuClusterSize, c_nbnxnGpuClusterSize }
};
-/* The nbnxn j-cluster size in atoms for each nbnxn kernel type */
+/*! \brief The nbnxn j-cluster size in atoms for each nbnxn kernel type */
static constexpr gmx::EnumerationArray<KernelType, int> JClusterSizePerKernelType = {
{ 0, c_nbnxnCpuIClusterSize,
#if GMX_SIMD
c_nbnxnGpuClusterSize, c_nbnxnGpuClusterSize / 2 }
};
-/* Returns whether the pair-list corresponding to nb_kernel_type is simple */
+/*! \brief Returns whether the pair-list corresponding to nb_kernel_type is simple */
static inline bool kernelTypeUsesSimplePairlist(const KernelType kernelType)
{
return (kernelType == KernelType::Cpu4x4_PlainC || kernelType == KernelType::Cpu4xN_Simd_4xN
|| kernelType == KernelType::Cpu4xN_Simd_2xNN);
}
+//! Returns whether a SIMD kernel is in use
static inline bool kernelTypeIsSimd(const KernelType kernelType)
{
return (kernelType == KernelType::Cpu4xN_Simd_4xN || kernelType == KernelType::Cpu4xN_Simd_2xNN);
} // namespace Nbnxm
-/* Returns the effective list radius of the pair-list
+/*! \brief Returns the effective list radius of the pair-list
*
* Due to the cluster size the effective pair-list is longer than
* that of a simple atom pair-list. This function gives the extra distance.
*/
real nbnxn_get_rlist_effective_inc(int jClusterSize, real atomDensity);
-/* Returns the effective list radius of the pair-list
+/*! \brief Returns the effective list radius of the pair-list
*
* Due to the cluster size the effective pair-list is longer than
* that of a simple atom pair-list. This function gives the extra distance.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gpu_utils/gpu_macros.h"
#include "gromacs/math/vectypes.h"
#include "gromacs/mdtypes/locality.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
-#include "atomdata.h"
-#include "gpu_types.h"
-
struct interaction_const_t;
struct nbnxn_atomdata_t;
struct gmx_wallcycle;
* \param [in] aloc Atom locality flag.
*/
GPU_FUNC_QUALIFIER
-void gpu_copy_xq_to_gpu(gmx_nbnxn_gpu_t gmx_unused* nb,
+void gpu_copy_xq_to_gpu(NbnxmGpu gmx_unused* nb,
const struct nbnxn_atomdata_t gmx_unused* nbdata,
gmx::AtomLocality gmx_unused aloc) GPU_FUNC_TERM;
*
*/
GPU_FUNC_QUALIFIER
-void gpu_launch_kernel(gmx_nbnxn_gpu_t gmx_unused* nb,
+void gpu_launch_kernel(NbnxmGpu gmx_unused* nb,
const gmx::StepWorkload gmx_unused& stepWork,
gmx::InteractionLocality gmx_unused iloc) GPU_FUNC_TERM;
* \param [in] numParts Number of parts the pair list is split into in the rolling kernel.
*/
GPU_FUNC_QUALIFIER
-void gpu_launch_kernel_pruneonly(gmx_nbnxn_gpu_t gmx_unused* nb,
+void gpu_launch_kernel_pruneonly(NbnxmGpu gmx_unused* nb,
gmx::InteractionLocality gmx_unused iloc,
int gmx_unused numParts) GPU_FUNC_TERM;
* (and energies/shift forces if required).
*/
GPU_FUNC_QUALIFIER
-void gpu_launch_cpyback(gmx_nbnxn_gpu_t gmx_unused* nb,
+void gpu_launch_cpyback(NbnxmGpu gmx_unused* nb,
nbnxn_atomdata_t gmx_unused* nbatom,
const gmx::StepWorkload gmx_unused& stepWork,
gmx::AtomLocality gmx_unused aloc) GPU_FUNC_TERM;
* \returns True if the nonbonded tasks associated with \p aloc locality have completed
*/
GPU_FUNC_QUALIFIER
-bool gpu_try_finish_task(gmx_nbnxn_gpu_t gmx_unused* nb,
+bool gpu_try_finish_task(NbnxmGpu gmx_unused* nb,
const gmx::StepWorkload gmx_unused& stepWork,
gmx::AtomLocality gmx_unused aloc,
real gmx_unused* e_lj,
* \param[out] shiftForces Shift forces buffer to accumulate into
* \param[out] wcycle Pointer to wallcycle data structure */
GPU_FUNC_QUALIFIER
-float gpu_wait_finish_task(gmx_nbnxn_gpu_t gmx_unused* nb,
+float gpu_wait_finish_task(NbnxmGpu gmx_unused* nb,
const gmx::StepWorkload gmx_unused& stepWork,
gmx::AtomLocality gmx_unused aloc,
real gmx_unused* e_lj,
* Called on the NS step and performs (re-)allocations and memory copies. !*/
CUDA_FUNC_QUALIFIER
void nbnxn_gpu_init_x_to_nbat_x(const Nbnxm::GridSet gmx_unused& gridSet,
- gmx_nbnxn_gpu_t gmx_unused* gpu_nbv) CUDA_FUNC_TERM;
+ NbnxmGpu gmx_unused* gpu_nbv) CUDA_FUNC_TERM;
/*! \brief X buffer operations on GPU: performs conversion from rvec to nb format.
*
CUDA_FUNC_QUALIFIER
void nbnxn_gpu_x_to_nbat_x(const Nbnxm::Grid gmx_unused& grid,
bool gmx_unused setFillerCoords,
- gmx_nbnxn_gpu_t gmx_unused* gpu_nbv,
- DeviceBuffer<float> gmx_unused d_x,
+ NbnxmGpu gmx_unused* gpu_nbv,
+ DeviceBuffer<gmx::RVec> gmx_unused d_x,
GpuEventSynchronizer gmx_unused* xReadyOnDevice,
gmx::AtomLocality gmx_unused locality,
int gmx_unused gridId,
* \param[in] interactionLocality Local or NonLocal sync point
*/
CUDA_FUNC_QUALIFIER
-void nbnxnInsertNonlocalGpuDependency(const gmx_nbnxn_gpu_t gmx_unused* nb,
+void nbnxnInsertNonlocalGpuDependency(const NbnxmGpu gmx_unused* nb,
gmx::InteractionLocality gmx_unused interactionLocality) CUDA_FUNC_TERM;
/*! \brief Set up internal flags that indicate what type of short-range work there is.
* \param[in] iLocality Interaction locality identifier
*/
GPU_FUNC_QUALIFIER
-void setupGpuShortRangeWork(gmx_nbnxn_gpu_t gmx_unused* nb,
+void setupGpuShortRangeWork(NbnxmGpu gmx_unused* nb,
const gmx::GpuBonded gmx_unused* gpuBonded,
gmx::InteractionLocality gmx_unused iLocality) GPU_FUNC_TERM;
* \param[in] aLocality Atom locality identifier
*/
GPU_FUNC_QUALIFIER
-bool haveGpuShortRangeWork(const gmx_nbnxn_gpu_t gmx_unused* nb, gmx::AtomLocality gmx_unused aLocality)
+bool haveGpuShortRangeWork(const NbnxmGpu gmx_unused* nb, gmx::AtomLocality gmx_unused aLocality)
GPU_FUNC_TERM_WITH_RETURN(false);
/*! \brief Initialization for F buffer operations on GPU */
CUDA_FUNC_QUALIFIER
void nbnxn_gpu_init_add_nbat_f_to_f(const int gmx_unused* cell,
- gmx_nbnxn_gpu_t gmx_unused* gpu_nbv,
+ NbnxmGpu gmx_unused* gpu_nbv,
int gmx_unused natoms_total,
GpuEventSynchronizer gmx_unused* localReductionDone) CUDA_FUNC_TERM;
*/
CUDA_FUNC_QUALIFIER
void nbnxn_gpu_add_nbat_f_to_f(gmx::AtomLocality gmx_unused atomLocality,
- DeviceBuffer<float> gmx_unused totalForcesDevice,
- gmx_nbnxn_gpu_t gmx_unused* gpu_nbv,
+ DeviceBuffer<gmx::RVec> gmx_unused totalForcesDevice,
+ NbnxmGpu gmx_unused* gpu_nbv,
void gmx_unused* pmeForcesDevice,
gmx::ArrayRef<GpuEventSynchronizer* const> gmx_unused dependencyList,
int gmx_unused atomStart,
* \param[in] nb The nonbonded data GPU structure
*/
CUDA_FUNC_QUALIFIER
-void nbnxn_wait_x_on_device(gmx_nbnxn_gpu_t gmx_unused* nb) CUDA_FUNC_TERM;
+void nbnxn_wait_x_on_device(NbnxmGpu gmx_unused* nb) CUDA_FUNC_TERM;
} // namespace Nbnxm
#endif
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
+#include "gromacs/mdtypes/interaction_const.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/nbnxm/nbnxm.h"
#include "gromacs/nbnxm/pairlist_tuning.h"
#include "gromacs/simd/simd.h"
+#include "gromacs/topology/mtop_util.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/logger.h"
-#include "atomdata.h"
-#include "gpu_types.h"
#include "grid.h"
#include "nbnxm_geometry.h"
#include "nbnxm_simd.h"
{
/*! \brief Gets and returns the minimum i-list count for balacing based on the GPU used or env.var. when set */
-static int getMinimumIlistCountForGpuBalancing(gmx_nbnxn_gpu_t* nbnxmGpu)
+static int getMinimumIlistCountForGpuBalancing(NbnxmGpu* nbnxmGpu)
{
int minimumIlistCount;
return minimumIlistCount;
}
-std::unique_ptr<nonbonded_verlet_t> init_nb_verlet(const gmx::MDLogger& mdlog,
- gmx_bool bFEP_NonBonded,
- const t_inputrec* ir,
- const t_forcerec* fr,
- const t_commrec* cr,
- const gmx_hw_info_t& hardwareInfo,
- const gmx_device_info_t* deviceInfo,
- const gmx_mtop_t* mtop,
- matrix box,
- gmx_wallcycle* wcycle)
+std::unique_ptr<nonbonded_verlet_t> init_nb_verlet(const gmx::MDLogger& mdlog,
+ const t_inputrec* ir,
+ const t_forcerec* fr,
+ const t_commrec* cr,
+ const gmx_hw_info_t& hardwareInfo,
+ const bool useGpuForNonbonded,
+ const gmx::DeviceStreamManager* deviceStreamManager,
+ const gmx_mtop_t* mtop,
+ matrix box,
+ gmx_wallcycle* wcycle)
{
const bool emulateGpu = (getenv("GMX_EMULATE_GPU") != nullptr);
- const bool useGpu = deviceInfo != nullptr;
- GMX_RELEASE_ASSERT(!(emulateGpu && useGpu),
+ GMX_RELEASE_ASSERT(!(emulateGpu && useGpuForNonbonded),
"When GPU emulation is active, there cannot be a GPU assignment");
NonbondedResource nonbondedResource;
- if (useGpu)
+ if (useGpuForNonbonded)
{
nonbondedResource = NonbondedResource::Gpu;
}
Nbnxm::KernelSetup kernelSetup = pick_nbnxn_kernel(mdlog, fr->use_simd_kernels, hardwareInfo,
nonbondedResource, ir, fr->bNonbonded);
- const bool haveMultipleDomains = (DOMAINDECOMP(cr) && cr->dd->nnodes > 1);
+ const bool haveMultipleDomains = havePPDomainDecomposition(cr);
- PairlistParams pairlistParams(kernelSetup.kernelType, bFEP_NonBonded, ir->rlist,
- havePPDomainDecomposition(cr));
+ bool bFEP_NonBonded = (fr->efep != efepNO) && haveFepPerturbedNBInteractions(mtop);
+ PairlistParams pairlistParams(kernelSetup.kernelType, bFEP_NonBonded, ir->rlist, haveMultipleDomains);
setupDynamicPairlistPruning(mdlog, ir, mtop, box, fr->ic, &pairlistParams);
enbnxninitcombrule = enbnxninitcombruleNONE;
}
- auto pinPolicy = (useGpu ? gmx::PinningPolicy::PinnedIfSupported : gmx::PinningPolicy::CannotBePinned);
+ auto pinPolicy = (useGpuForNonbonded ? gmx::PinningPolicy::PinnedIfSupported
+ : gmx::PinningPolicy::CannotBePinned);
auto nbat = std::make_unique<nbnxn_atomdata_t>(pinPolicy);
}
nbnxn_atomdata_init(mdlog, nbat.get(), kernelSetup.kernelType, enbnxninitcombrule, fr->ntype,
fr->nbfp, mimimumNumEnergyGroupNonbonded,
- (useGpu || emulateGpu) ? 1 : gmx_omp_nthreads_get(emntNonbonded));
+ (useGpuForNonbonded || emulateGpu) ? 1 : gmx_omp_nthreads_get(emntNonbonded));
- gmx_nbnxn_gpu_t* gpu_nbv = nullptr;
- int minimumIlistCountForGpuBalancing = 0;
- if (useGpu)
+ NbnxmGpu* gpu_nbv = nullptr;
+ int minimumIlistCountForGpuBalancing = 0;
+ if (useGpuForNonbonded)
{
/* init the NxN GPU data; the last argument tells whether we'll have
* both local and non-local NB calculation on GPU */
- gpu_nbv = gpu_init(deviceInfo, fr->ic, pairlistParams, nbat.get(), cr->nodeid, haveMultipleDomains);
+ GMX_RELEASE_ASSERT(
+ (deviceStreamManager != nullptr),
+ "Device stream manager should be initialized in order to use GPU for non-bonded.");
+ gpu_nbv = gpu_init(*deviceStreamManager, fr->ic, pairlistParams, nbat.get(), haveMultipleDomains);
minimumIlistCountForGpuBalancing = getMinimumIlistCountForGpuBalancing(gpu_nbv);
}
minimumIlistCountForGpuBalancing);
auto pairSearch = std::make_unique<PairSearch>(
- ir->ePBC, EI_TPI(ir->eI), DOMAINDECOMP(cr) ? &cr->dd->nc : nullptr,
+ ir->pbcType, EI_TPI(ir->eI), DOMAINDECOMP(cr) ? &cr->dd->numCells : nullptr,
DOMAINDECOMP(cr) ? domdec_zones(cr->dd) : nullptr, pairlistParams.pairlistType,
bFEP_NonBonded, gmx_omp_nthreads_get(emntPairsearch), pinPolicy);
std::unique_ptr<PairSearch> pairSearch,
std::unique_ptr<nbnxn_atomdata_t> nbat_in,
const Nbnxm::KernelSetup& kernelSetup,
- gmx_nbnxn_gpu_t* gpu_nbv_ptr,
+ NbnxmGpu* gpu_nbv_ptr,
gmx_wallcycle* wcycle) :
pairlistSets_(std::move(pairlistSets)),
pairSearch_(std::move(pairSearch)),
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-
+/*! \internal \file
+ *
+ * \brief
+ * Defines constants used to know which Nbnxm kernel flavours (4xn or 2xnn)
+ * can be supported by the SIMD layer in use.
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
#ifndef GMX_NBNXM_NBNXM_SIMD_H
#define GMX_NBNXM_NBNXM_SIMD_H
+#include "config.h"
+
#include "gromacs/math/vectypes.h"
#include "gromacs/simd/simd.h"
#include "gromacs/utility/real.h"
-#if GMX_SIMD
-/* The nbnxn SIMD 4xN and 2x(N+N) kernels can be added independently.
+#if GMX_SIMD && GMX_USE_SIMD_KERNELS
+/*! \brief The nbnxn SIMD 4xN and 2x(N+N) kernels can be added independently.
* Currently the 2xNN SIMD kernels only make sense with:
* 8-way SIMD: 4x4 setup, works with AVX-256 in single precision
* 16-way SIMD: 4x8 setup, works with Intel MIC in single precision
# error "No SIMD kernel type defined"
# endif
-#endif // GMX_SIMD
+#endif // GMX_SIMD && GMX_USE_SIMD_KERNELS
-#endif /* _nbnxn_simd_h */
+#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
string(REGEX REPLACE ".*=" "" ELEC_NAME "${ELEC_DEF}")
string(REGEX REPLACE ".*=" "" VDW_NAME "${VDW_DEF}")
set(OBJ_FILE nbnxm_ocl_kernel${ELEC_NAME}${VDW_NAME}_${VENDOR}.o)
+ # The constants below duplicate various others (e.g. from pairlist.h)
+ # but as the kernels compiled here are not used for production,
+ # it will be OK if the values would fall out of sync.
add_custom_command(OUTPUT ${OBJ_FILE} COMMAND ${OCL_COMPILER}
${CMAKE_CURRENT_SOURCE_DIR}/nbnxm_ocl_kernels.cl ${CLANG_TIDY_ARGS}
-Xclang -finclude-default-header -D_${VENDOR}_SOURCE_
-DGMX_OCL_FASTGEN ${ELEC_DEF} ${VDW_DEF}
- -DNBNXN_GPU_CLUSTER_SIZE=${CLUSTER_SIZE} -DIATYPE_SHMEM
+ -Dc_nbnxnGpuClusterSize=${CLUSTER_SIZE}
+ -Dc_nbnxnMinDistanceSquared=3.82e-07F
+ -Dc_nbnxnGpuNumClusterPerSupercluster=8
+ -Dc_nbnxnGpuJgroupSize=4
+ -DIATYPE_SHMEM
-c -I ${CMAKE_SOURCE_DIR}/src -std=cl1.2
-Weverything -Wno-conversion -Wno-missing-variable-declarations -Wno-used-but-marked-unused
-Wno-cast-align -Wno-incompatible-pointer-types
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "thread_mpi/atomic.h"
+#include "gromacs/gpu_utils/device_context.h"
#include "gromacs/gpu_utils/gputraits_ocl.h"
#include "gromacs/gpu_utils/oclutils.h"
#include "gromacs/hardware/hw_info.h"
/*! \brief Convenience constants */
//@{
-static const int c_numClPerSupercl = c_nbnxnGpuNumClusterPerSupercluster;
-static const int c_clSize = c_nbnxnGpuClusterSize;
+static constexpr int c_clSize = c_nbnxnGpuClusterSize;
//@}
*/
static inline void validate_global_work_size(const KernelLaunchConfig& config,
int work_dim,
- const gmx_device_info_t* dinfo)
+ const DeviceInformation* dinfo)
{
cl_uint device_size_t_size_bits;
cl_uint host_size_t_size_bits;
- assert(dinfo);
+ GMX_ASSERT(dinfo, "Need a valid device info object");
size_t global_work_size[3];
GMX_ASSERT(work_dim <= 3, "Not supporting hyper-grids just yet");
* OpenCL kernel objects are cached in nb. If the requested kernel is not
* found in the cache, it will be created and the cache will be updated.
*/
-static inline cl_kernel select_nbnxn_kernel(gmx_nbnxn_ocl_t* nb, int eeltype, int evdwtype, bool bDoEne, bool bDoPrune)
+static inline cl_kernel select_nbnxn_kernel(NbnxmGpu* nb, int eeltype, int evdwtype, bool bDoEne, bool bDoPrune)
{
const char* kernel_name_to_run;
cl_kernel* kernel_ptr;
cl_int cl_error;
- assert(eeltype < eelOclNR);
- assert(evdwtype < evdwOclNR);
+ GMX_ASSERT(eeltype < eelOclNR,
+ "The electrostatics type requested is not implemented in the OpenCL kernels.");
+ GMX_ASSERT(evdwtype < evdwOclNR,
+ "The VdW type requested is not implemented in the OpenCL kernels.");
if (bDoEne)
{
if (nullptr == kernel_ptr[0])
{
*kernel_ptr = clCreateKernel(nb->dev_rundata->program, kernel_name_to_run, &cl_error);
- assert(cl_error == CL_SUCCESS);
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clCreateKernel failed: " + ocl_get_error_string(cl_error)).c_str());
}
- // TODO: handle errors
return *kernel_ptr;
}
/* size of shmem (force-buffers/xq/atom type preloading) */
/* NOTE: with the default kernel on sm3.0 we need shmem only for pre-loading */
/* i-atom x+q in shared memory */
- shmem = c_numClPerSupercl * c_clSize * sizeof(float) * 4; /* xqib */
+ shmem = c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(float) * 4; /* xqib */
/* cj in shared memory, for both warps separately
* TODO: in the "nowarp kernels we load cj only once so the factor 2 is not needed.
*/
if (useLjCombRule(vdwType))
{
/* i-atom LJ combination parameters in shared memory */
- shmem += c_numClPerSupercl * c_clSize * 2 * sizeof(float); /* atib abused for ljcp, float2 */
+ shmem += c_nbnxnGpuNumClusterPerSupercluster * c_clSize * 2
+ * sizeof(float); /* atib abused for ljcp, float2 */
}
else
{
/* i-atom types in shared memory */
- shmem += c_numClPerSupercl * c_clSize * sizeof(int); /* atib */
+ shmem += c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(int); /* atib */
}
}
/* force reduction buffers in shared memory */
/* Release event and reset it to 0. It is ok to release it as enqueuewaitforevents performs implicit retain for events. */
cl_error = clReleaseEvent(*ocl_event);
- assert(CL_SUCCESS == cl_error);
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clReleaseEvent failed: " + ocl_get_error_string(cl_error)).c_str());
*ocl_event = nullptr;
}
/*! \brief Launch asynchronously the xq buffer host to device copy. */
-void gpu_copy_xq_to_gpu(gmx_nbnxn_ocl_t* nb, const nbnxn_atomdata_t* nbatom, const AtomLocality atomLocality)
+void gpu_copy_xq_to_gpu(NbnxmGpu* nb, const nbnxn_atomdata_t* nbatom, const AtomLocality atomLocality)
{
GMX_ASSERT(nb, "Need a valid nbnxn_gpu object");
/* local/nonlocal offset and length used for xq and f */
int adat_begin, adat_len;
- cl_atomdata_t* adat = nb->atdat;
- cl_plist_t* plist = nb->plist[iloc];
- cl_timers_t* t = nb->timers;
- cl_command_queue stream = nb->stream[iloc];
+ cl_atomdata_t* adat = nb->atdat;
+ cl_plist_t* plist = nb->plist[iloc];
+ cl_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
- bool bDoTime = (nb->bDoTime) != 0;
+ bool bDoTime = nb->bDoTime;
/* Don't launch the non-local H2D copy if there is no dependent
work to do: neither non-local nor other (e.g. bonded) work
/* beginning of timed HtoD section */
if (bDoTime)
{
- t->xf[atomLocality].nb_h2d.openTimingRegion(stream);
+ t->xf[atomLocality].nb_h2d.openTimingRegion(deviceStream);
}
/* HtoD x, q */
- ocl_copy_H2D_async(adat->xq, nbatom->x().data() + adat_begin * 4,
- adat_begin * sizeof(float) * 4, adat_len * sizeof(float) * 4, stream,
+ ocl_copy_H2D_async(adat->xq, nbatom->x().data() + adat_begin * 4, adat_begin * sizeof(float) * 4,
+ adat_len * sizeof(float) * 4, deviceStream.stream(),
bDoTime ? t->xf[atomLocality].nb_h2d.fetchNextEvent() : nullptr);
if (bDoTime)
{
- t->xf[atomLocality].nb_h2d.closeTimingRegion(stream);
+ t->xf[atomLocality].nb_h2d.closeTimingRegion(deviceStream);
}
/* When we get here all misc operations issues in the local stream as well as
if (iloc == InteractionLocality::Local)
{
cl_int gmx_used_in_debug cl_error = clEnqueueMarkerWithWaitList(
- stream, 0, nullptr, &(nb->misc_ops_and_local_H2D_done));
- assert(CL_SUCCESS == cl_error);
+ deviceStream.stream(), 0, nullptr, &(nb->misc_ops_and_local_H2D_done));
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clEnqueueMarkerWithWaitList failed: " + ocl_get_error_string(cl_error)).c_str());
/* Based on the v1.2 section 5.13 of the OpenCL spec, a flush is needed
* in the local stream in order to be able to sync with the above event
* from the non-local stream.
*/
- cl_error = clFlush(stream);
- assert(CL_SUCCESS == cl_error);
+ cl_error = clFlush(deviceStream.stream());
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clFlush failed: " + ocl_get_error_string(cl_error)).c_str());
}
else
{
- sync_ocl_event(stream, &(nb->misc_ops_and_local_H2D_done));
+ sync_ocl_event(deviceStream.stream(), &(nb->misc_ops_and_local_H2D_done));
}
}
}
misc_ops_done event to record the point in time when the above operations
are finished and synchronize with this event in the non-local stream.
*/
-void gpu_launch_kernel(gmx_nbnxn_ocl_t* nb, const gmx::StepWorkload& stepWork, const Nbnxm::InteractionLocality iloc)
+void gpu_launch_kernel(NbnxmGpu* nb, const gmx::StepWorkload& stepWork, const Nbnxm::InteractionLocality iloc)
{
- cl_atomdata_t* adat = nb->atdat;
- cl_nbparam_t* nbp = nb->nbparam;
- cl_plist_t* plist = nb->plist[iloc];
- cl_timers_t* t = nb->timers;
- cl_command_queue stream = nb->stream[iloc];
+ cl_atomdata_t* adat = nb->atdat;
+ cl_nbparam_t* nbp = nb->nbparam;
+ cl_plist_t* plist = nb->plist[iloc];
+ cl_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
- bool bDoTime = (nb->bDoTime) != 0;
+ bool bDoTime = nb->bDoTime;
cl_nbparam_params_t nbparams_params;
/* beginning of timed nonbonded calculation section */
if (bDoTime)
{
- t->interaction[iloc].nb_k.openTimingRegion(stream);
+ t->interaction[iloc].nb_k.openTimingRegion(deviceStream);
}
/* kernel launch config */
KernelLaunchConfig config;
config.sharedMemorySize = calc_shmem_required_nonbonded(nbp->vdwtype, nb->bPrefetchLjParam);
- config.stream = stream;
config.blockSize[0] = c_clSize;
config.blockSize[1] = c_clSize;
config.gridSize[0] = plist->nsci;
- validate_global_work_size(config, 3, nb->dev_info);
+ validate_global_work_size(config, 3, &nb->deviceContext_->deviceInfo());
if (debug)
{
"Global work size : %zux%zu\n\t#Super-clusters/clusters: %d/%d (%d)\n",
config.blockSize[0], config.blockSize[1], config.blockSize[2],
config.blockSize[0] * config.gridSize[0], config.blockSize[1] * config.gridSize[1],
- plist->nsci * c_numClPerSupercl, c_numClPerSupercl, plist->na_c);
+ plist->nsci * c_nbnxnGpuNumClusterPerSupercluster,
+ c_nbnxnGpuNumClusterPerSupercluster, plist->na_c);
}
fillin_ocl_structures(nbp, &nbparams_params);
&adat->fshift, &adat->lj_comb, &adat->shift_vec, &nbp->nbfp_climg2d, &nbp->nbfp_comb_climg2d,
&nbp->coulomb_tab_climg2d, &plist->sci, &plist->cj4, &plist->excl, &computeFshift);
- launchGpuKernel(kernel, config, timingEvent, kernelName, kernelArgs);
+ launchGpuKernel(kernel, config, deviceStream, timingEvent, kernelName, kernelArgs);
}
else
{
&adat->e_el, &adat->fshift, &adat->atom_types, &adat->shift_vec, &nbp->nbfp_climg2d,
&nbp->nbfp_comb_climg2d, &nbp->coulomb_tab_climg2d, &plist->sci, &plist->cj4,
&plist->excl, &computeFshift);
- launchGpuKernel(kernel, config, timingEvent, kernelName, kernelArgs);
+ launchGpuKernel(kernel, config, deviceStream, timingEvent, kernelName, kernelArgs);
}
if (bDoTime)
{
- t->interaction[iloc].nb_k.closeTimingRegion(stream);
+ t->interaction[iloc].nb_k.closeTimingRegion(deviceStream);
}
}
int shmem;
/* i-atom x in shared memory (for convenience we load all 4 components including q) */
- shmem = c_numClPerSupercl * c_clSize * sizeof(float) * 4;
+ shmem = c_nbnxnGpuNumClusterPerSupercluster * c_clSize * sizeof(float) * 4;
/* cj in shared memory, for each warp separately
* Note: only need to load once per wavefront, but to keep the code simple,
* for now we load twice on AMD.
* Launch the pairlist prune only kernel for the given locality.
* \p numParts tells in how many parts, i.e. calls the list will be pruned.
*/
-void gpu_launch_kernel_pruneonly(gmx_nbnxn_gpu_t* nb, const InteractionLocality iloc, const int numParts)
+void gpu_launch_kernel_pruneonly(NbnxmGpu* nb, const InteractionLocality iloc, const int numParts)
{
- cl_atomdata_t* adat = nb->atdat;
- cl_nbparam_t* nbp = nb->nbparam;
- cl_plist_t* plist = nb->plist[iloc];
- cl_timers_t* t = nb->timers;
- cl_command_queue stream = nb->stream[iloc];
- bool bDoTime = nb->bDoTime == CL_TRUE;
+ cl_atomdata_t* adat = nb->atdat;
+ cl_nbparam_t* nbp = nb->nbparam;
+ cl_plist_t* plist = nb->plist[iloc];
+ cl_timers_t* t = nb->timers;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
+ bool bDoTime = nb->bDoTime;
if (plist->haveFreshList)
{
/* beginning of timed prune calculation section */
if (bDoTime)
{
- timer->openTimingRegion(stream);
+ timer->openTimingRegion(deviceStream);
}
/* Kernel launch config:
* and j-cluster concurrency, in x, y, and z, respectively.
* - The 1D block-grid contains as many blocks as super-clusters.
*/
- int num_threads_z = getOclPruneKernelJ4Concurrency(nb->dev_info->vendor_e);
+ int num_threads_z = c_oclPruneKernelJ4ConcurrencyDEFAULT;
+
/* kernel launch config */
KernelLaunchConfig config;
config.sharedMemorySize = calc_shmem_required_prune(num_threads_z);
- config.stream = stream;
config.blockSize[0] = c_clSize;
config.blockSize[1] = c_clSize;
config.blockSize[2] = num_threads_z;
config.gridSize[0] = numSciInPart;
- validate_global_work_size(config, 3, nb->dev_info);
+ validate_global_work_size(config, 3, &nb->deviceContext_->deviceInfo());
if (debug)
{
"\tShMem: %zu\n",
config.blockSize[0], config.blockSize[1], config.blockSize[2],
config.blockSize[0] * config.gridSize[0], config.blockSize[1] * config.gridSize[1],
- plist->nsci * c_numClPerSupercl, c_numClPerSupercl, plist->na_c, config.sharedMemorySize);
+ plist->nsci * c_nbnxnGpuNumClusterPerSupercluster,
+ c_nbnxnGpuNumClusterPerSupercluster, plist->na_c, config.sharedMemorySize);
}
cl_nbparam_params_t nbparams_params;
const auto kernelArgs = prepareGpuKernelArguments(pruneKernel, config, &nbparams_params,
&adat->xq, &adat->shift_vec, &plist->sci,
&plist->cj4, &plist->imask, &numParts, &part);
- launchGpuKernel(pruneKernel, config, timingEvent, kernelName, kernelArgs);
+ launchGpuKernel(pruneKernel, config, deviceStream, timingEvent, kernelName, kernelArgs);
if (plist->haveFreshList)
{
if (bDoTime)
{
- timer->closeTimingRegion(stream);
+ timer->closeTimingRegion(deviceStream);
}
}
* Launch asynchronously the download of nonbonded forces from the GPU
* (and energies/shift forces if required).
*/
-void gpu_launch_cpyback(gmx_nbnxn_ocl_t* nb,
+void gpu_launch_cpyback(NbnxmGpu* nb,
struct nbnxn_atomdata_t* nbatom,
const gmx::StepWorkload& stepWork,
const AtomLocality aloc)
/* determine interaction locality from atom locality */
const InteractionLocality iloc = gpuAtomToInteractionLocality(aloc);
- cl_atomdata_t* adat = nb->atdat;
- cl_timers_t* t = nb->timers;
- bool bDoTime = nb->bDoTime == CL_TRUE;
- cl_command_queue stream = nb->stream[iloc];
+ cl_atomdata_t* adat = nb->atdat;
+ cl_timers_t* t = nb->timers;
+ bool bDoTime = nb->bDoTime;
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
/* don't launch non-local copy-back if there was no non-local work to do */
if ((iloc == InteractionLocality::NonLocal) && !haveGpuShortRangeWork(*nb, iloc))
/* beginning of timed D2H section */
if (bDoTime)
{
- t->xf[aloc].nb_d2h.openTimingRegion(stream);
+ t->xf[aloc].nb_d2h.openTimingRegion(deviceStream);
}
/* With DD the local D2H transfer can only start after the non-local
has been launched. */
if (iloc == InteractionLocality::Local && nb->bNonLocalStreamActive)
{
- sync_ocl_event(stream, &(nb->nonlocal_done));
+ sync_ocl_event(deviceStream.stream(), &(nb->nonlocal_done));
}
/* DtoH f */
- ocl_copy_D2H_async(nbatom->out[0].f.data() + adat_begin * 3, adat->f,
- adat_begin * 3 * sizeof(float), (adat_len)*adat->f_elem_size, stream,
+ ocl_copy_D2H_async(nbatom->out[0].f.data() + adat_begin * DIM, adat->f,
+ adat_begin * DIM * sizeof(nbatom->out[0].f[0]),
+ adat_len * DIM * sizeof(nbatom->out[0].f[0]), deviceStream.stream(),
bDoTime ? t->xf[aloc].nb_d2h.fetchNextEvent() : nullptr);
/* kick off work */
- cl_error = clFlush(stream);
- assert(CL_SUCCESS == cl_error);
+ cl_error = clFlush(deviceStream.stream());
+ GMX_ASSERT(cl_error == CL_SUCCESS, ("clFlush failed: " + ocl_get_error_string(cl_error)).c_str());
/* After the non-local D2H is launched the nonlocal_done event can be
recorded which signals that the local D2H can proceed. This event is not
data back first. */
if (iloc == InteractionLocality::NonLocal)
{
- cl_error = clEnqueueMarkerWithWaitList(stream, 0, nullptr, &(nb->nonlocal_done));
- assert(CL_SUCCESS == cl_error);
+ cl_error = clEnqueueMarkerWithWaitList(deviceStream.stream(), 0, nullptr, &(nb->nonlocal_done));
+ GMX_ASSERT(cl_error == CL_SUCCESS,
+ ("clEnqueueMarkerWithWaitList failed: " + ocl_get_error_string(cl_error)).c_str());
nb->bNonLocalStreamActive = CL_TRUE;
}
/* DtoH fshift when virial is needed */
if (stepWork.computeVirial)
{
- ocl_copy_D2H_async(nb->nbst.fshift, adat->fshift, 0, SHIFTS * adat->fshift_elem_size,
- stream, bDoTime ? t->xf[aloc].nb_d2h.fetchNextEvent() : nullptr);
+ ocl_copy_D2H_async(nb->nbst.fshift, adat->fshift, 0,
+ SHIFTS * sizeof(nb->nbst.fshift[0]), deviceStream.stream(),
+ bDoTime ? t->xf[aloc].nb_d2h.fetchNextEvent() : nullptr);
}
/* DtoH energies */
if (stepWork.computeEnergy)
{
- ocl_copy_D2H_async(nb->nbst.e_lj, adat->e_lj, 0, sizeof(float), stream,
+ ocl_copy_D2H_async(nb->nbst.e_lj, adat->e_lj, 0, sizeof(float), deviceStream.stream(),
bDoTime ? t->xf[aloc].nb_d2h.fetchNextEvent() : nullptr);
- ocl_copy_D2H_async(nb->nbst.e_el, adat->e_el, 0, sizeof(float), stream,
+ ocl_copy_D2H_async(nb->nbst.e_el, adat->e_el, 0, sizeof(float), deviceStream.stream(),
bDoTime ? t->xf[aloc].nb_d2h.fetchNextEvent() : nullptr);
}
}
if (bDoTime)
{
- t->xf[aloc].nb_d2h.closeTimingRegion(stream);
+ t->xf[aloc].nb_d2h.closeTimingRegion(deviceStream);
}
}
/* OpenCL: By default, use analytical Ewald
* TODO: tabulated does not work, it needs fixing, see init_nbparam() in nbnxn_ocl_data_mgmt.cpp
*
- * TODO: decide if dev_info parameter should be added to recognize NVIDIA CC>=3.0 devices.
- *
*/
/* By default use analytical Ewald. */
bUseAnalyticalEwald = true;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ *
+ * \brief
+ * Declares constants for OpenCL code
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
#ifndef NBNXN_OPENCL_CONSTS_H
#define NBNXN_OPENCL_CONSTS_H
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cmath>
-// TODO We would like to move this down, but the way gmx_nbnxn_gpu_t
-// is currently declared means this has to be before gpu_types.h
-#include "nbnxm_ocl_types.h"
-
-// TODO Remove this comment when the above order issue is resolved
+#include "gromacs/gpu_utils/device_stream_manager.h"
#include "gromacs/gpu_utils/gpu_utils.h"
#include "gromacs/gpu_utils/oclutils.h"
#include "gromacs/hardware/gpu_hw_info.h"
#include "gromacs/utility/smalloc.h"
#include "nbnxm_ocl_internal.h"
+#include "nbnxm_ocl_types.h"
namespace Nbnxm
{
* If called with an already allocated table, it just re-uploads the
* table.
*/
-static void init_ewald_coulomb_force_table(const EwaldCorrectionTables& tables,
- cl_nbparam_t* nbp,
- const gmx_device_runtime_data_t* runData)
+static void init_ewald_coulomb_force_table(const EwaldCorrectionTables& tables,
+ cl_nbparam_t* nbp,
+ const DeviceContext& deviceContext)
{
- cl_mem coul_tab;
-
- cl_int cl_error;
-
if (nbp->coulomb_tab_climg2d != nullptr)
{
freeDeviceBuffer(&(nbp->coulomb_tab_climg2d));
}
- /* Switched from using textures to using buffers */
- // TODO: decide which alternative is most efficient - textures or buffers.
- /*
- cl_image_format array_format;
-
- array_format.image_channel_data_type = CL_FLOAT;
- array_format.image_channel_order = CL_R;
+ DeviceBuffer<real> coulomb_tab;
- coul_tab = clCreateImage2D(runData->context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
- &array_format, tabsize, 1, 0, ftmp, &cl_error);
- */
+ initParamLookupTable(&coulomb_tab, nullptr, tables.tableF.data(), tables.tableF.size(), deviceContext);
- coul_tab = clCreateBuffer(
- runData->context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR,
- tables.tableF.size() * sizeof(cl_float), const_cast<real*>(tables.tableF.data()), &cl_error);
- GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
- ("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
-
- nbp->coulomb_tab_climg2d = coul_tab;
+ nbp->coulomb_tab_climg2d = coulomb_tab;
nbp->coulomb_tab_scale = tables.scale;
}
/*! \brief Initializes the atomdata structure first time, it only gets filled at
pair-search.
*/
-static void init_atomdata_first(cl_atomdata_t* ad, int ntypes, gmx_device_runtime_data_t* runData)
+static void init_atomdata_first(cl_atomdata_t* ad, int ntypes, const DeviceContext& deviceContext)
{
cl_int cl_error;
ad->ntypes = ntypes;
- /* An element of the shift_vec device buffer has the same size as one element
- of the host side shift_vec buffer. */
- ad->shift_vec_elem_size = sizeof(*nbnxn_atomdata_t::shift_vec.data());
-
- ad->shift_vec = clCreateBuffer(runData->context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
- SHIFTS * ad->shift_vec_elem_size, nullptr, &cl_error);
+ ad->shift_vec = clCreateBuffer(deviceContext.context(), CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
+ SHIFTS * sizeof(nbnxn_atomdata_t::shift_vec[0]), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
ad->bShiftVecUploaded = CL_FALSE;
- /* An element of the fshift device buffer has the same size as one element
- of the host side fshift buffer. */
- ad->fshift_elem_size = sizeof(*cl_nb_staging_t::fshift);
-
- ad->fshift = clCreateBuffer(runData->context, CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
- SHIFTS * ad->fshift_elem_size, nullptr, &cl_error);
+ ad->fshift = clCreateBuffer(deviceContext.context(), CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
+ SHIFTS * sizeof(nb_staging_t::fshift[0]), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
- ad->e_lj = clCreateBuffer(runData->context, CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
+ ad->e_lj = clCreateBuffer(deviceContext.context(), CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
sizeof(float), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
- ad->e_el = clCreateBuffer(runData->context, CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
+ ad->e_el = clCreateBuffer(deviceContext.context(), CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
sizeof(float), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
/*! \brief Initializes the nonbonded parameter data structure.
*/
-static void init_nbparam(cl_nbparam_t* nbp,
- const interaction_const_t* ic,
- const PairlistParams& listParams,
- const nbnxn_atomdata_t::Params& nbatParams,
- const gmx_device_runtime_data_t* runData)
+static void init_nbparam(cl_nbparam_t* nbp,
+ const interaction_const_t* ic,
+ const PairlistParams& listParams,
+ const nbnxn_atomdata_t::Params& nbatParams,
+ const DeviceContext& deviceContext)
{
cl_int cl_error;
if (nbp->eeltype == eelOclEWALD_TAB || nbp->eeltype == eelOclEWALD_TAB_TWIN)
{
GMX_RELEASE_ASSERT(ic->coulombEwaldTables, "Need valid Coulomb Ewald correction tables");
- init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, runData);
+ init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, deviceContext);
}
else
- // TODO: improvement needed.
- // The image2d is created here even if eeltype is not eelCuEWALD_TAB or eelCuEWALD_TAB_TWIN
- // because the OpenCL kernels don't accept nullptr values for image2D parameters.
{
- /* Switched from using textures to using buffers */
- // TODO: decide which alternative is most efficient - textures or buffers.
- /*
- cl_image_format array_format;
-
- array_format.image_channel_data_type = CL_FLOAT;
- array_format.image_channel_order = CL_R;
-
- nbp->coulomb_tab_climg2d = clCreateImage2D(runData->context, CL_MEM_READ_WRITE,
- &array_format, 1, 1, 0, nullptr, &cl_error);
- */
-
- nbp->coulomb_tab_climg2d = clCreateBuffer(runData->context, CL_MEM_READ_ONLY,
+ nbp->coulomb_tab_climg2d = clCreateBuffer(deviceContext.context(), CL_MEM_READ_ONLY,
sizeof(cl_float), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
const int nnbfp_comb = 2 * nbatParams.numTypes;
{
- /* Switched from using textures to using buffers */
- // TODO: decide which alternative is most efficient - textures or buffers.
- /*
- cl_image_format array_format;
-
- array_format.image_channel_data_type = CL_FLOAT;
- array_format.image_channel_order = CL_R;
-
- nbp->nbfp_climg2d = clCreateImage2D(runData->context, CL_MEM_READ_ONLY |
- CL_MEM_COPY_HOST_PTR, &array_format, nnbfp, 1, 0, nbat->nbfp, &cl_error);
- */
-
- nbp->nbfp_climg2d = clCreateBuffer(
- runData->context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR,
- nnbfp * sizeof(cl_float), const_cast<float*>(nbatParams.nbfp.data()), &cl_error);
- GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
- ("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
+ /* set up LJ parameter lookup table */
+ DeviceBuffer<real> nbfp;
+ initParamLookupTable(&nbfp, nullptr, nbatParams.nbfp.data(), nnbfp, deviceContext);
+ nbp->nbfp_climg2d = nbfp;
if (ic->vdwtype == evdwPME)
{
- /* Switched from using textures to using buffers */
- // TODO: decide which alternative is most efficient - textures or buffers.
- /* nbp->nbfp_comb_climg2d = clCreateImage2D(runData->context, CL_MEM_READ_WRITE |
- CL_MEM_COPY_HOST_PTR, &array_format, nnbfp_comb, 1, 0, nbat->nbfp_comb, &cl_error);*/
- nbp->nbfp_comb_climg2d = clCreateBuffer(
- runData->context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR,
- nnbfp_comb * sizeof(cl_float), const_cast<float*>(nbatParams.nbfp_comb.data()),
- &cl_error);
- GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
- ("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
- }
- else
- {
- // TODO: improvement needed.
- // The image2d is created here even if vdwtype is not evdwPME because the OpenCL kernels
- // don't accept nullptr values for image2D parameters.
- /* Switched from using textures to using buffers */
- // TODO: decide which alternative is most efficient - textures or buffers.
- /* nbp->nbfp_comb_climg2d = clCreateImage2D(runData->context, CL_MEM_READ_WRITE,
- &array_format, 1, 1, 0, nullptr, &cl_error);*/
- nbp->nbfp_comb_climg2d = clCreateBuffer(runData->context, CL_MEM_READ_ONLY,
- sizeof(cl_float), nullptr, &cl_error);
- GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
- ("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
+ DeviceBuffer<float> nbfp_comb;
+ initParamLookupTable(&nbfp_comb, nullptr, nbatParams.nbfp_comb.data(), nnbfp_comb, deviceContext);
+ nbp->nbfp_comb_climg2d = nbfp_comb;
}
}
}
{
return;
}
- gmx_nbnxn_ocl_t* nb = nbv->gpu_nbv;
- cl_nbparam_t* nbp = nb->nbparam;
+ NbnxmGpu* nb = nbv->gpu_nbv;
+ cl_nbparam_t* nbp = nb->nbparam;
set_cutoff_parameters(nbp, ic, nbv->pairlistSets().params());
nbp->eeltype = nbnxn_gpu_pick_ewald_kernel_type(*ic);
GMX_RELEASE_ASSERT(ic->coulombEwaldTables, "Need valid Coulomb Ewald correction tables");
- init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, nb->dev_rundata);
+ init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, *nb->deviceContext_);
}
/*! \brief Initializes the pair list data structure.
t->dynamicPruneTime.t = 0.0;
}
-
-//! OpenCL notification callback function
-static void CL_CALLBACK ocl_notify_fn(const char* pErrInfo,
- const void gmx_unused* private_info,
- size_t gmx_unused cb,
- void gmx_unused* user_data)
-{
- if (pErrInfo != nullptr)
- {
- printf("%s\n", pErrInfo); // Print error/hint
- }
-}
-
-/*! \brief Creates context for OpenCL GPU given by \p mygpu
- *
- * A fatal error results if creation fails.
- *
- * \param[inout] runtimeData runtime data including program and context
- * \param[in] devInfo device info struct
- * \param[in] rank MPI rank (for error reporting)
- */
-static void nbnxn_gpu_create_context(gmx_device_runtime_data_t* runtimeData,
- const gmx_device_info_t* devInfo,
- int rank)
-{
- cl_context_properties context_properties[5];
- cl_platform_id platform_id;
- cl_device_id device_id;
- cl_context context;
- cl_int cl_error;
-
- assert(runtimeData != nullptr);
- assert(devInfo != nullptr);
-
- platform_id = devInfo->ocl_gpu_id.ocl_platform_id;
- device_id = devInfo->ocl_gpu_id.ocl_device_id;
-
- int i = 0;
- context_properties[i++] = CL_CONTEXT_PLATFORM;
- context_properties[i++] = reinterpret_cast<cl_context_properties>(platform_id);
- if (getenv("GMX_OCL_SHOW_DIAGNOSTICS"))
- {
- context_properties[i++] = CL_CONTEXT_SHOW_DIAGNOSTICS_INTEL;
- context_properties[i++] =
- CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL | CL_CONTEXT_DIAGNOSTICS_LEVEL_NEUTRAL_INTEL;
- }
- context_properties[i++] = 0; /* Terminates the list of properties */
-
- context = clCreateContext(context_properties, 1, &device_id, ocl_notify_fn, nullptr, &cl_error);
- if (CL_SUCCESS != cl_error)
- {
- gmx_fatal(FARGS, "On rank %d failed to create context for GPU #%s:\n OpenCL error %d: %s",
- rank, devInfo->device_name, cl_error, ocl_get_error_string(cl_error).c_str());
- }
-
- runtimeData->context = context;
-}
-
/*! \brief Initializes the OpenCL kernel pointers of the nbnxn_ocl_ptr_t input data structure. */
-static cl_kernel nbnxn_gpu_create_kernel(gmx_nbnxn_ocl_t* nb, const char* kernel_name)
+static cl_kernel nbnxn_gpu_create_kernel(NbnxmGpu* nb, const char* kernel_name)
{
cl_kernel kernel;
cl_int cl_error;
if (CL_SUCCESS != cl_error)
{
gmx_fatal(FARGS, "Failed to create kernel '%s' for GPU #%s: OpenCL error %d", kernel_name,
- nb->dev_info->device_name, cl_error);
+ nb->deviceContext_->deviceInfo().device_name, cl_error);
}
return kernel;
/*! \brief Clears nonbonded shift force output array and energy outputs on the GPU.
*/
-static void nbnxn_ocl_clear_e_fshift(gmx_nbnxn_ocl_t* nb)
+static void nbnxn_ocl_clear_e_fshift(NbnxmGpu* nb)
{
cl_int cl_error;
cl_atomdata_t* adat = nb->atdat;
- cl_command_queue ls = nb->stream[InteractionLocality::Local];
+ cl_command_queue ls = nb->deviceStreams[InteractionLocality::Local]->stream();
size_t local_work_size[3] = { 1, 1, 1 };
size_t global_work_size[3] = { 1, 1, 1 };
}
/*! \brief Initializes the OpenCL kernel pointers of the nbnxn_ocl_ptr_t input data structure. */
-static void nbnxn_gpu_init_kernels(gmx_nbnxn_ocl_t* nb)
+static void nbnxn_gpu_init_kernels(NbnxmGpu* nb)
{
/* Init to 0 main kernel arrays */
/* They will be later on initialized in select_nbnxn_kernel */
* Initializes members of the atomdata and nbparam structs and
* clears e/fshift output buffers.
*/
-static void nbnxn_ocl_init_const(gmx_nbnxn_ocl_t* nb,
+static void nbnxn_ocl_init_const(cl_atomdata_t* atomData,
+ cl_nbparam_t* nbParams,
const interaction_const_t* ic,
const PairlistParams& listParams,
- const nbnxn_atomdata_t::Params& nbatParams)
+ const nbnxn_atomdata_t::Params& nbatParams,
+ const DeviceContext& deviceContext)
{
- init_atomdata_first(nb->atdat, nbatParams.numTypes, nb->dev_rundata);
- init_nbparam(nb->nbparam, ic, listParams, nbatParams, nb->dev_rundata);
+ init_atomdata_first(atomData, nbatParams.numTypes, deviceContext);
+ init_nbparam(nbParams, ic, listParams, nbatParams, deviceContext);
}
//! This function is documented in the header file
-gmx_nbnxn_ocl_t* gpu_init(const gmx_device_info_t* deviceInfo,
- const interaction_const_t* ic,
- const PairlistParams& listParams,
- const nbnxn_atomdata_t* nbat,
- const int rank,
- const gmx_bool bLocalAndNonlocal)
+NbnxmGpu* gpu_init(const gmx::DeviceStreamManager& deviceStreamManager,
+ const interaction_const_t* ic,
+ const PairlistParams& listParams,
+ const nbnxn_atomdata_t* nbat,
+ const bool bLocalAndNonlocal)
{
- gmx_nbnxn_ocl_t* nb;
- cl_int cl_error;
- cl_command_queue_properties queue_properties;
-
- assert(ic);
+ GMX_ASSERT(ic, "Need a valid interaction constants object");
- snew(nb, 1);
+ auto nb = new NbnxmGpu();
+ nb->deviceContext_ = &deviceStreamManager.context();
snew(nb->atdat, 1);
snew(nb->nbparam, 1);
snew(nb->plist[InteractionLocality::Local], 1);
snew(nb->plist[InteractionLocality::NonLocal], 1);
}
- nb->bUseTwoStreams = static_cast<cl_bool>(bLocalAndNonlocal);
+ nb->bUseTwoStreams = bLocalAndNonlocal;
nb->timers = new cl_timers_t();
snew(nb->timings, 1);
/* set device info, just point it to the right GPU among the detected ones */
- nb->dev_info = deviceInfo;
- snew(nb->dev_rundata, 1);
+ nb->dev_rundata = new gmx_device_runtime_data_t();
/* init nbst */
pmalloc(reinterpret_cast<void**>(&nb->nbst.e_lj), sizeof(*nb->nbst.e_lj));
init_plist(nb->plist[InteractionLocality::Local]);
/* OpenCL timing disabled if GMX_DISABLE_GPU_TIMING is defined. */
- nb->bDoTime = static_cast<cl_bool>(getenv("GMX_DISABLE_GPU_TIMING") == nullptr);
-
- /* Create queues only after bDoTime has been initialized */
- if (nb->bDoTime)
- {
- queue_properties = CL_QUEUE_PROFILING_ENABLE;
- }
- else
- {
- queue_properties = 0;
- }
-
- nbnxn_gpu_create_context(nb->dev_rundata, nb->dev_info, rank);
+ nb->bDoTime = (getenv("GMX_DISABLE_GPU_TIMING") == nullptr);
/* local/non-local GPU streams */
- nb->stream[InteractionLocality::Local] = clCreateCommandQueue(
- nb->dev_rundata->context, nb->dev_info->ocl_gpu_id.ocl_device_id, queue_properties, &cl_error);
- if (CL_SUCCESS != cl_error)
- {
- gmx_fatal(FARGS, "On rank %d failed to create context for GPU #%s: OpenCL error %d", rank,
- nb->dev_info->device_name, cl_error);
- }
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedLocal),
+ "Local non-bonded stream should be initialized to use GPU for non-bonded.");
+ nb->deviceStreams[InteractionLocality::Local] =
+ &deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedLocal);
if (nb->bUseTwoStreams)
{
init_plist(nb->plist[InteractionLocality::NonLocal]);
- nb->stream[InteractionLocality::NonLocal] =
- clCreateCommandQueue(nb->dev_rundata->context, nb->dev_info->ocl_gpu_id.ocl_device_id,
- queue_properties, &cl_error);
- if (CL_SUCCESS != cl_error)
- {
- gmx_fatal(FARGS, "On rank %d failed to create context for GPU #%s: OpenCL error %d",
- rank, nb->dev_info->device_name, cl_error);
- }
+ GMX_RELEASE_ASSERT(deviceStreamManager.streamIsValid(gmx::DeviceStreamType::NonBondedNonLocal),
+ "Non-local non-bonded stream should be initialized to use GPU for "
+ "non-bonded with domain decomposition.");
+ nb->deviceStreams[InteractionLocality::NonLocal] =
+ &deviceStreamManager.stream(gmx::DeviceStreamType::NonBondedNonLocal);
}
if (nb->bDoTime)
init_timings(nb->timings);
}
- nbnxn_ocl_init_const(nb, ic, listParams, nbat->params());
+ nbnxn_ocl_init_const(nb->atdat, nb->nbparam, ic, listParams, nbat->params(), *nb->deviceContext_);
/* Enable LJ param manual prefetch for AMD or Intel or if we request through env. var.
* TODO: decide about NVIDIA
*/
nb->bPrefetchLjParam = (getenv("GMX_OCL_DISABLE_I_PREFETCH") == nullptr)
- && ((nb->dev_info->vendor_e == OCL_VENDOR_AMD)
- || (nb->dev_info->vendor_e == OCL_VENDOR_INTEL)
+ && ((nb->deviceContext_->deviceInfo().deviceVendor == DeviceVendor::Amd)
+ || (nb->deviceContext_->deviceInfo().deviceVendor == DeviceVendor::Intel)
|| (getenv("GMX_OCL_ENABLE_I_PREFETCH") != nullptr));
/* NOTE: in CUDA we pick L1 cache configuration for the nbnxn kernels here,
/*! \brief Clears the first natoms_clear elements of the GPU nonbonded force output array.
*/
-static void nbnxn_ocl_clear_f(gmx_nbnxn_ocl_t* nb, int natoms_clear)
+static void nbnxn_ocl_clear_f(NbnxmGpu* nb, int natoms_clear)
{
if (natoms_clear == 0)
{
cl_int gmx_used_in_debug cl_error;
cl_atomdata_t* atomData = nb->atdat;
- cl_command_queue ls = nb->stream[InteractionLocality::Local];
+ cl_command_queue ls = nb->deviceStreams[InteractionLocality::Local]->stream();
cl_float value = 0.0F;
cl_error = clEnqueueFillBuffer(ls, atomData->f, &value, sizeof(cl_float), 0,
}
//! This function is documented in the header file
-void gpu_clear_outputs(gmx_nbnxn_ocl_t* nb, bool computeVirial)
+void gpu_clear_outputs(NbnxmGpu* nb, bool computeVirial)
{
nbnxn_ocl_clear_f(nb, nb->atdat->natoms);
/* clear shift force array and energies if the outputs were
/* kick off buffer clearing kernel to ensure concurrency with constraints/update */
cl_int gmx_unused cl_error;
- cl_error = clFlush(nb->stream[InteractionLocality::Local]);
- assert(CL_SUCCESS == cl_error);
+ cl_error = clFlush(nb->deviceStreams[InteractionLocality::Local]->stream());
+ GMX_ASSERT(cl_error == CL_SUCCESS, ("clFlush failed: " + ocl_get_error_string(cl_error)).c_str());
}
//! This function is documented in the header file
-void gpu_init_pairlist(gmx_nbnxn_ocl_t* nb, const NbnxnPairlistGpu* h_plist, const InteractionLocality iloc)
+void gpu_init_pairlist(NbnxmGpu* nb, const NbnxnPairlistGpu* h_plist, const InteractionLocality iloc)
{
char sbuf[STRLEN];
// Timing accumulation should happen only if there was work to do
// because getLastRangeTime() gets skipped with empty lists later
// which leads to the counter not being reset.
- bool bDoTime = ((nb->bDoTime == CL_TRUE) && !h_plist->sci.empty());
- cl_command_queue stream = nb->stream[iloc];
- cl_plist_t* d_plist = nb->plist[iloc];
+ bool bDoTime = (nb->bDoTime && !h_plist->sci.empty());
+ const DeviceStream& deviceStream = *nb->deviceStreams[iloc];
+ cl_plist_t* d_plist = nb->plist[iloc];
if (d_plist->na_c < 0)
{
if (bDoTime)
{
- iTimers.pl_h2d.openTimingRegion(stream);
+ iTimers.pl_h2d.openTimingRegion(deviceStream);
iTimers.didPairlistH2D = true;
}
// TODO most of this function is same in CUDA and OpenCL, move into the header
- DeviceContext context = nb->dev_rundata->context;
+ const DeviceContext& deviceContext = *nb->deviceContext_;
- reallocateDeviceBuffer(&d_plist->sci, h_plist->sci.size(), &d_plist->nsci, &d_plist->sci_nalloc, context);
- copyToDeviceBuffer(&d_plist->sci, h_plist->sci.data(), 0, h_plist->sci.size(), stream,
+ reallocateDeviceBuffer(&d_plist->sci, h_plist->sci.size(), &d_plist->nsci, &d_plist->sci_nalloc,
+ deviceContext);
+ copyToDeviceBuffer(&d_plist->sci, h_plist->sci.data(), 0, h_plist->sci.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
- reallocateDeviceBuffer(&d_plist->cj4, h_plist->cj4.size(), &d_plist->ncj4, &d_plist->cj4_nalloc, context);
- copyToDeviceBuffer(&d_plist->cj4, h_plist->cj4.data(), 0, h_plist->cj4.size(), stream,
+ reallocateDeviceBuffer(&d_plist->cj4, h_plist->cj4.size(), &d_plist->ncj4, &d_plist->cj4_nalloc,
+ deviceContext);
+ copyToDeviceBuffer(&d_plist->cj4, h_plist->cj4.data(), 0, h_plist->cj4.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
reallocateDeviceBuffer(&d_plist->imask, h_plist->cj4.size() * c_nbnxnGpuClusterpairSplit,
- &d_plist->nimask, &d_plist->imask_nalloc, context);
+ &d_plist->nimask, &d_plist->imask_nalloc, deviceContext);
reallocateDeviceBuffer(&d_plist->excl, h_plist->excl.size(), &d_plist->nexcl,
- &d_plist->excl_nalloc, context);
- copyToDeviceBuffer(&d_plist->excl, h_plist->excl.data(), 0, h_plist->excl.size(), stream,
+ &d_plist->excl_nalloc, deviceContext);
+ copyToDeviceBuffer(&d_plist->excl, h_plist->excl.data(), 0, h_plist->excl.size(), deviceStream,
GpuApiCallBehavior::Async, bDoTime ? iTimers.pl_h2d.fetchNextEvent() : nullptr);
if (bDoTime)
{
- iTimers.pl_h2d.closeTimingRegion(stream);
+ iTimers.pl_h2d.closeTimingRegion(deviceStream);
}
/* need to prune the pair list during the next step */
}
//! This function is documented in the header file
-void gpu_upload_shiftvec(gmx_nbnxn_ocl_t* nb, const nbnxn_atomdata_t* nbatom)
+void gpu_upload_shiftvec(NbnxmGpu* nb, const nbnxn_atomdata_t* nbatom)
{
cl_atomdata_t* adat = nb->atdat;
- cl_command_queue ls = nb->stream[InteractionLocality::Local];
+ cl_command_queue ls = nb->deviceStreams[InteractionLocality::Local]->stream();
/* only if we have a dynamic box */
if (nbatom->bDynamicBox || !adat->bShiftVecUploaded)
{
ocl_copy_H2D_async(adat->shift_vec, nbatom->shift_vec.data(), 0,
- SHIFTS * adat->shift_vec_elem_size, ls, nullptr);
+ SHIFTS * sizeof(nbatom->shift_vec[0]), ls, nullptr);
adat->bShiftVecUploaded = CL_TRUE;
}
}
//! This function is documented in the header file
-void gpu_init_atomdata(gmx_nbnxn_ocl_t* nb, const nbnxn_atomdata_t* nbat)
+void gpu_init_atomdata(NbnxmGpu* nb, const nbnxn_atomdata_t* nbat)
{
- cl_int cl_error;
- int nalloc, natoms;
- bool realloced;
- bool bDoTime = nb->bDoTime == CL_TRUE;
- cl_timers_t* timers = nb->timers;
- cl_atomdata_t* d_atdat = nb->atdat;
- cl_command_queue ls = nb->stream[InteractionLocality::Local];
+ cl_int cl_error;
+ int nalloc, natoms;
+ bool realloced;
+ bool bDoTime = nb->bDoTime;
+ cl_timers_t* timers = nb->timers;
+ cl_atomdata_t* d_atdat = nb->atdat;
+ const DeviceStream& deviceStream = *nb->deviceStreams[InteractionLocality::Local];
natoms = nbat->numAtoms();
realloced = false;
if (bDoTime)
{
/* time async copy */
- timers->atdat.openTimingRegion(ls);
+ timers->atdat.openTimingRegion(deviceStream);
}
/* need to reallocate if we have to copy more atoms than the amount of space
freeDeviceBuffer(&d_atdat->atom_types);
}
- d_atdat->f_elem_size = sizeof(rvec);
-
- d_atdat->f = clCreateBuffer(nb->dev_rundata->context, CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
- nalloc * d_atdat->f_elem_size, nullptr, &cl_error);
+ d_atdat->f = clCreateBuffer(nb->deviceContext_->context(), CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
+ nalloc * DIM * sizeof(nbat->out[0].f[0]), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
- d_atdat->xq = clCreateBuffer(nb->dev_rundata->context, CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
+ d_atdat->xq = clCreateBuffer(nb->deviceContext_->context(), CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
nalloc * sizeof(cl_float4), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clCreateBuffer failed: " + ocl_get_error_string(cl_error)).c_str());
if (useLjCombRule(nb->nbparam->vdwtype))
{
- d_atdat->lj_comb = clCreateBuffer(nb->dev_rundata->context,
+ d_atdat->lj_comb = clCreateBuffer(nb->deviceContext_->context(),
CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
nalloc * sizeof(cl_float2), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
}
else
{
- d_atdat->atom_types = clCreateBuffer(nb->dev_rundata->context,
+ d_atdat->atom_types = clCreateBuffer(nb->deviceContext_->context(),
CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
nalloc * sizeof(int), nullptr, &cl_error);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
if (useLjCombRule(nb->nbparam->vdwtype))
{
ocl_copy_H2D_async(d_atdat->lj_comb, nbat->params().lj_comb.data(), 0, natoms * sizeof(cl_float2),
- ls, bDoTime ? timers->atdat.fetchNextEvent() : nullptr);
+ deviceStream.stream(), bDoTime ? timers->atdat.fetchNextEvent() : nullptr);
}
else
{
ocl_copy_H2D_async(d_atdat->atom_types, nbat->params().type.data(), 0, natoms * sizeof(int),
- ls, bDoTime ? timers->atdat.fetchNextEvent() : nullptr);
+ deviceStream.stream(), bDoTime ? timers->atdat.fetchNextEvent() : nullptr);
}
if (bDoTime)
{
- timers->atdat.closeTimingRegion(ls);
+ timers->atdat.closeTimingRegion(deviceStream);
}
/* kick off the tasks enqueued above to ensure concurrency with the search */
- cl_error = clFlush(ls);
+ cl_error = clFlush(deviceStream.stream());
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clFlush failed: " + ocl_get_error_string(cl_error)).c_str());
}
{
cl_int gmx_unused cl_error;
- assert(nullptr != kernel_ptr);
+ GMX_ASSERT(kernel_ptr, "Need a valid kernel pointer");
if (*kernel_ptr)
{
}
}
-/*! \brief Free the OpenCL runtime data (context and program).
+/*! \brief Free the OpenCL program.
*
- * The function releases the OpenCL context and program assuciated with the
+ * The function releases the OpenCL program assuciated with the
* device that the calling PP rank is running on.
*
- * \param runData [in] porinter to the structure with runtime data.
+ * \param program [in] OpenCL program to release.
*/
-static void free_gpu_device_runtime_data(gmx_device_runtime_data_t* runData)
+static void freeGpuProgram(cl_program program)
{
- if (runData == nullptr)
+ if (program)
{
- return;
- }
-
- cl_int gmx_unused cl_error;
-
- if (runData->context)
- {
- cl_error = clReleaseContext(runData->context);
- GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
- ("clReleaseContext failed: " + ocl_get_error_string(cl_error)).c_str());
- runData->context = nullptr;
- }
-
- if (runData->program)
- {
- cl_error = clReleaseProgram(runData->program);
+ cl_int cl_error = clReleaseProgram(program);
GMX_RELEASE_ASSERT(cl_error == CL_SUCCESS,
("clReleaseProgram failed: " + ocl_get_error_string(cl_error)).c_str());
- runData->program = nullptr;
+ program = nullptr;
}
}
//! This function is documented in the header file
-void gpu_free(gmx_nbnxn_ocl_t* nb)
+void gpu_free(NbnxmGpu* nb)
{
if (nb == nullptr)
{
pfree(nb->nbst.fshift);
nb->nbst.fshift = nullptr;
- /* Free command queues */
- clReleaseCommandQueue(nb->stream[InteractionLocality::Local]);
- nb->stream[InteractionLocality::Local] = nullptr;
- if (nb->bUseTwoStreams)
- {
- clReleaseCommandQueue(nb->stream[InteractionLocality::NonLocal]);
- nb->stream[InteractionLocality::NonLocal] = nullptr;
- }
/* Free other events */
if (nb->nonlocal_done)
{
nb->misc_ops_and_local_H2D_done = nullptr;
}
- free_gpu_device_runtime_data(nb->dev_rundata);
- sfree(nb->dev_rundata);
+ freeGpuProgram(nb->dev_rundata->program);
+ delete nb->dev_rundata;
/* Free timers and timings */
delete nb->timers;
sfree(nb->timings);
- sfree(nb);
+ delete nb;
if (debug)
{
}
//! This function is documented in the header file
-gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(gmx_nbnxn_ocl_t* nb)
+gmx_wallclock_gpu_nbnxn_t* gpu_get_timings(NbnxmGpu* nb)
{
return (nb != nullptr && nb->bDoTime) ? nb->timings : nullptr;
}
}
//! This function is documented in the header file
-int gpu_min_ci_balanced(gmx_nbnxn_ocl_t* nb)
+int gpu_min_ci_balanced(NbnxmGpu* nb)
{
- return nb != nullptr ? gpu_min_ci_balanced_factor * nb->dev_info->compute_units : 0;
+ return nb != nullptr ? gpu_min_ci_balanced_factor * nb->deviceContext_->deviceInfo().compute_units : 0;
}
//! This function is documented in the header file
-gmx_bool gpu_is_kernel_ewald_analytical(const gmx_nbnxn_ocl_t* nb)
+gmx_bool gpu_is_kernel_ewald_analytical(const NbnxmGpu* nb)
{
return ((nb->nbparam->eeltype == eelOclEWALD_ANA) || (nb->nbparam->eeltype == eelOclEWALD_ANA_TWIN));
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* A fatal error results if compilation fails.
*
- * \param[inout] nb Manages OpenCL non-bonded calculations; compiled kernels returned in dev_info members
+ * \param[inout] nb Manages OpenCL non-bonded calculations; compiled kernels returned in deviceInfo members
*
* Does not throw
*/
-void nbnxn_gpu_compile_kernels(gmx_nbnxn_ocl_t* nb)
+void nbnxn_gpu_compile_kernels(NbnxmGpu* nb)
{
gmx_bool bFastGen = TRUE;
cl_program program = nullptr;
std::string extraDefines =
makeDefinesForKernelTypes(bFastGen, nb->nbparam->eeltype, nb->nbparam->vdwtype);
- /* Here we pass macros and static const int variables defined
+ /* Here we pass macros and static const/constexpr int variables defined
* in include files outside the opencl as macros, to avoid
- * including those files in the JIT compilation that happens
- * at runtime. This is particularly a problem for headers that
- * depend on config.h, such as pairlist.h. */
+ * including those files in the plain-C JIT compilation that happens
+ * at runtime. */
extraDefines += gmx::formatString(
- " -DNBNXN_GPU_CLUSTER_SIZE=%d "
+ " -Dc_nbnxnGpuClusterSize=%d"
+ " -Dc_nbnxnMinDistanceSquared=%g"
+ " -Dc_nbnxnGpuNumClusterPerSupercluster=%d"
+ " -Dc_nbnxnGpuJgroupSize=%d"
"%s",
- c_nbnxnGpuClusterSize, /* Defined in nbnxn_pairlist.h */
- (nb->bPrefetchLjParam) ? "-DIATYPE_SHMEM" : "");
+ c_nbnxnGpuClusterSize, c_nbnxnMinDistanceSquared, c_nbnxnGpuNumClusterPerSupercluster,
+ c_nbnxnGpuJgroupSize, (nb->bPrefetchLjParam) ? " -DIATYPE_SHMEM" : "");
try
{
/* TODO when we have a proper MPI-aware logging module,
the log output here should be written there */
program = gmx::ocl::compileProgram(
stderr, "gromacs/nbnxm/opencl", "nbnxm_ocl_kernels.cl", extraDefines,
- nb->dev_rundata->context, nb->dev_info->ocl_gpu_id.ocl_device_id,
- nb->dev_info->vendor_e);
+ nb->deviceContext_->context(), nb->deviceContext_->deviceInfo().oclDeviceId,
+ nb->deviceContext_->deviceInfo().deviceVendor);
}
catch (gmx::GromacsException& e)
{
e.prependContext(gmx::formatString("Failed to compile NBNXN kernels for GPU #%s\n",
- nb->dev_info->device_name));
+ nb->deviceContext_->deviceInfo().device_name));
throw;
}
}
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2012-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const int bidx = get_group_id(0);
const int widx = tidx / WARP_SIZE; /* warp index */
- /*! i-cluster interaction mask for a super-cluster with all NCL_PER_SUPERCL=8 bits set */
- const unsigned superClInteractionMask = ((1U << NCL_PER_SUPERCL) - 1U);
+ /*! i-cluster interaction mask for a super-cluster with all c_nbnxnGpuNumClusterPerSupercluster=8 bits set */
+ const unsigned superClInteractionMask = ((1U << c_nbnxnGpuNumClusterPerSupercluster) - 1U);
-#define LOCAL_OFFSET (xqib + NCL_PER_SUPERCL * CL_SIZE)
+#define LOCAL_OFFSET (xqib + c_nbnxnGpuNumClusterPerSupercluster * CL_SIZE)
CjType cjs = 0;
#if USE_CJ_PREFETCH
/* shmem buffer for cj, for both warps separately */
/* shmem buffer for i atom-type pre-loading */
__local int* atib = (__local int*)(LOCAL_OFFSET); //NOLINT(google-readability-casting)
# undef LOCAL_OFFSET
-# define LOCAL_OFFSET (atib + NCL_PER_SUPERCL * CL_SIZE)
+# define LOCAL_OFFSET (atib + c_nbnxnGpuNumClusterPerSupercluster * CL_SIZE)
# else
__local float2* ljcpib = (__local float2*)(LOCAL_OFFSET);
# undef LOCAL_OFFSET
-# define LOCAL_OFFSET (ljcpib + NCL_PER_SUPERCL * CL_SIZE)
+# define LOCAL_OFFSET (ljcpib + c_nbnxnGpuNumClusterPerSupercluster * CL_SIZE)
# endif
#endif
const int cij4_start = nb_sci.cj4_ind_start; /* first ...*/
const int cij4_end = nb_sci.cj4_ind_end; /* and last index of j clusters */
- for (int i = 0; i < NCL_PER_SUPERCL; i += CL_SIZE)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i += CL_SIZE)
{
/* Pre-load i-atom x and q into shared memory */
- const int ci = sci * NCL_PER_SUPERCL + tidxj + i;
+ const int ci = sci * c_nbnxnGpuNumClusterPerSupercluster + tidxj + i;
const int ai = ci * CL_SIZE + tidxi;
float4 xqbuf = xq[ai]
#endif
barrier(CLK_LOCAL_MEM_FENCE);
- float3 fci_buf[NCL_PER_SUPERCL]; /* i force buffer */
- for (int ci_offset = 0; ci_offset < NCL_PER_SUPERCL; ci_offset++)
+ float3 fci_buf[c_nbnxnGpuNumClusterPerSupercluster]; /* i force buffer */
+ for (int ci_offset = 0; ci_offset < c_nbnxnGpuNumClusterPerSupercluster; ci_offset++)
{
fci_buf[ci_offset] = (float3)(0.0F);
}
float E_el = 0.0F;
# if defined EXCLUSION_FORCES /* Ewald or RF */
- if (nb_sci.shift == CENTRAL && pl_cj4[cij4_start].cj[0] == sci * NCL_PER_SUPERCL)
+ if (nb_sci.shift == CENTRAL && pl_cj4[cij4_start].cj[0] == sci * c_nbnxnGpuNumClusterPerSupercluster)
{
/* we have the diagonal: add the charge and LJ self interaction energy term */
- for (int i = 0; i < NCL_PER_SUPERCL; i++)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
# if defined EL_EWALD_ANY || defined EL_RF || defined EL_CUTOFF
const float qi = xqib[i * CL_SIZE + tidxi].w;
E_el += qi * qi;
# endif
# if defined LJ_EWALD
- E_lj += nbfp_climg2d[atom_types[(sci * NCL_PER_SUPERCL + i) * CL_SIZE + tidxi] * (ntypes + 1) * 2];
+ E_lj += nbfp_climg2d[atom_types[(sci * c_nbnxnGpuNumClusterPerSupercluster + i) * CL_SIZE + tidxi]
+ * (ntypes + 1) * 2];
# endif /* LJ_EWALD */
}
#endif
for (int jm = 0; jm < c_nbnxnGpuJgroupSize; jm++)
{
- if (imask & (superClInteractionMask << (jm * NCL_PER_SUPERCL)))
+ if (imask & (superClInteractionMask << (jm * c_nbnxnGpuNumClusterPerSupercluster)))
{
- unsigned int mask_ji = (1U << (jm * NCL_PER_SUPERCL));
+ unsigned int mask_ji = (1U << (jm * c_nbnxnGpuNumClusterPerSupercluster));
const int cj = loadCj(cjs, pl_cj4[j4].cj, jm, tidxi, tidxj);
const int aj = cj * CL_SIZE + tidxj;
#if !defined PRUNE_NBL
# pragma unroll 8
#endif
- for (int i = 0; i < NCL_PER_SUPERCL; i++)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
if (imask & mask_ji)
{
- const int gmx_unused ci = sci * NCL_PER_SUPERCL + i; /* i cluster index */
+ const int gmx_unused ci = sci * c_nbnxnGpuNumClusterPerSupercluster + i; /* i cluster index */
/* all threads load an atom from i cluster ci into shmem! */
const float4 xiqbuf = xqib[i * CL_SIZE + tidxi];
# endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- // Ensure distance do not become so small that r^-12 overflows
- r2 = max(r2, NBNXN_MIN_RSQ);
+ // Ensure distance do not become so small that r^-12 overflows.
+ // Cast to float to ensure the correct built-in max() function
+ // is called.
+ r2 = max(r2, (float)c_nbnxnMinDistanceSquared);
const float inv_r = rsqrt(r2);
const float inv_r2 = inv_r * inv_r;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif
// TODO move these consts to utils and unify their use with the nonbonded kernels
- const int c_numClPerSupercl = NCL_PER_SUPERCL;
- const int c_clSize = CL_SIZE;
+ const int c_clSize = CL_SIZE;
// TODO pass this value at compile-time as a macro
const int c_nbnxnGpuClusterpairSplit = 2;
- /*! i-cluster interaction mask for a super-cluster with all c_numClPerSupercl=8 bits set */
- const unsigned superClInteractionMask = ((1U << c_numClPerSupercl) - 1U);
+ /*! i-cluster interaction mask for a super-cluster with all c_nbnxnGpuNumClusterPerSupercluster=8 bits set */
+ const unsigned superClInteractionMask = ((1U << c_nbnxnGpuNumClusterPerSupercluster) - 1U);
-#define LOCAL_OFFSET (xib + c_numClPerSupercl * c_clSize)
+#define LOCAL_OFFSET (xib + c_nbnxnGpuNumClusterPerSupercluster * c_clSize)
/* shmem buffer for i cj pre-loading */
CjType cjs = 0;
#if USE_CJ_PREFETCH
cjs = (((__local int*)(LOCAL_OFFSET)) + tidxz * c_nbnxnGpuClusterpairSplit * c_nbnxnGpuJgroupSize);
# undef LOCAL_OFFSET
/* Offset calculated using xib because cjs depends on on tidxz! */
-# define LOCAL_OFFSET \
- (((__local int*)(xib + c_numClPerSupercl * c_clSize)) \
+# define LOCAL_OFFSET \
+ (((__local int*)(xib + c_nbnxnGpuNumClusterPerSupercluster * c_clSize)) \
+ (NTHREAD_Z * c_nbnxnGpuClusterpairSplit * c_nbnxnGpuJgroupSize))
#endif
#if !USE_SUBGROUP_ANY
if (tidxz == 0)
{
- for (int i = 0; i < NCL_PER_SUPERCL; i += CL_SIZE)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i += CL_SIZE)
{
/* Pre-load i-atom x and q into shared memory */
- const int ci = sci * c_numClPerSupercl + tidxj + i;
+ const int ci = sci * c_nbnxnGpuNumClusterPerSupercluster + tidxj + i;
const int ai = ci * c_clSize + tidxi;
/* We don't need q, but using float4 in shmem avoids bank conflicts */
#pragma unroll 4
for (int jm = 0; jm < c_nbnxnGpuJgroupSize; jm++)
{
- if (imaskCheck & (superClInteractionMask << (jm * c_numClPerSupercl)))
+ if (imaskCheck & (superClInteractionMask << (jm * c_nbnxnGpuNumClusterPerSupercluster)))
{
- unsigned int mask_ji = (1U << (jm * c_numClPerSupercl));
+ unsigned int mask_ji = (1U << (jm * c_nbnxnGpuNumClusterPerSupercluster));
const int cj = loadCj(cjs, pl_cj4[j4].cj, jm, tidxi, tidxj);
const int aj = cj * c_clSize + tidxj;
const float3 xj = (float3)(tmp.xyz);
#pragma unroll 8
- for (int i = 0; i < c_numClPerSupercl; i++)
+ for (int i = 0; i < c_nbnxnGpuNumClusterPerSupercluster; i++)
{
if (imaskCheck & mask_ji)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ * \brief
+ * Utility constant and function declaration for the OpenCL non-bonded kernels.
+ * This header should be included once at the top level, just before the
+ * kernels are included (has to be preceded by nbnxn_ocl_types.h).
+ *
+ * \author Szilárd Páll <pall.szilard@gmail.com>
+ * \ingroup module_nbnxm
+ */
#define GMX_DOUBLE 0
#include "gromacs/gpu_utils/device_utils.clh"
#include "gromacs/gpu_utils/vectype_ops.clh"
-#include "gromacs/nbnxm/constants.h"
#include "gromacs/pbcutil/ishift.h"
#include "nbnxm_ocl_consts.h"
-#define CL_SIZE (NBNXN_GPU_CLUSTER_SIZE)
-#define NCL_PER_SUPERCL c_nbnxnGpuNumClusterPerSupercluster
+#define CL_SIZE (c_nbnxnGpuClusterSize)
#define WARP_SIZE (CL_SIZE * CL_SIZE / 2) // Currently only c_nbnxnGpuClusterpairSplit=2 supported
typedef struct cl_nbparam_params
{
- int eeltype; /**< type of electrostatics, takes values from #eelCu */
- int vdwtype; /**< type of VdW impl., takes values from #evdwCu */
-
- float epsfac; /**< charge multiplication factor */
- float c_rf; /**< Reaction-field/plain cutoff electrostatics const. */
- float two_k_rf; /**< Reaction-field electrostatics constant */
- float ewald_beta; /**< Ewald/PME parameter */
- float sh_ewald; /**< Ewald/PME correction term substracted from the direct-space potential */
- float sh_lj_ewald; /**< LJ-Ewald/PME correction term added to the correction potential */
- float ewaldcoeff_lj; /**< LJ-Ewald/PME coefficient */
-
- float rcoulomb_sq; /**< Coulomb cut-off squared */
-
- float rvdw_sq; /**< VdW cut-off squared */
- float rvdw_switch; /**< VdW switched cut-off */
- float rlistOuter_sq; /**< Full, outer pair-list cut-off squared */
- float rlistInner_sq; /**< Inner, dynamic pruned pair-list cut-off squared XXX: this is only needed in the pruning kernels, but for now we also pass it to the nonbondeds */
-
- shift_consts_t dispersion_shift; /**< VdW shift dispersion constants */
- shift_consts_t repulsion_shift; /**< VdW shift repulsion constants */
- switch_consts_t vdw_switch; /**< VdW switch constants */
+ //! type of electrostatics, takes values from #eelCu
+ int eeltype;
+ //! type of VdW impl., takes values from #evdwCu
+ int vdwtype;
+
+ //! charge multiplication factor
+ float epsfac;
+ //! Reaction-field/plain cutoff electrostatics const.
+ float c_rf;
+ //! Reaction-field electrostatics constant
+ float two_k_rf;
+ //! Ewald/PME parameter
+ float ewald_beta;
+ //! Ewald/PME correction term substracted from the direct-space potential
+ float sh_ewald;
+ //! LJ-Ewald/PME correction term added to the correction potential
+ float sh_lj_ewald;
+ //! LJ-Ewald/PME coefficient
+ float ewaldcoeff_lj;
+
+ //! Coulomb cut-off squared
+ float rcoulomb_sq;
+
+ //! VdW cut-off squared
+ float rvdw_sq;
+ //! VdW switched cut-off
+ float rvdw_switch;
+ //! Full, outer pair-list cut-off squared
+ float rlistOuter_sq;
+ //! Inner, dynamic pruned pair-list cut-off squared XXX: this is only needed in the pruning kernels, but for now we also pass it to the nonbondeds
+ float rlistInner_sq;
+
+ //! VdW shift dispersion constants
+ shift_consts_t dispersion_shift;
+ //! VdW shift repulsion constants
+ shift_consts_t repulsion_shift;
+ //! VdW switch constants
+ switch_consts_t vdw_switch;
/* Ewald Coulomb force table data - accessed through texture memory */
- float coulomb_tab_scale; /**< table scale/spacing */
+ //! table scale/spacing
+ float coulomb_tab_scale;
} cl_nbparam_params_t;
typedef struct
{
- int sci; /* i-super-cluster */
- int shift; /* Shift vector index plus possible flags */
- int cj4_ind_start; /* Start index into cj4 */
- int cj4_ind_end; /* End index into cj4 */
+ //! i-super-cluster
+ int sci;
+ //! Shift vector index plus possible flags
+ int shift;
+ //! Start index into cj4
+ int cj4_ind_start;
+ //! End index into cj4
+ int cj4_ind_end;
} nbnxn_sci_t;
typedef struct
{
- unsigned int imask; /* The i-cluster interactions mask for 1 warp */
- int excl_ind; /* Index into the exclusion array for 1 warp */
+ //! The i-cluster interactions mask for 1 warp
+ unsigned int imask;
+ //! Index into the exclusion array for 1 warp
+ int excl_ind;
} nbnxn_im_ei_t;
typedef struct
{
- int cj[4]; /* The 4 j-clusters */
- nbnxn_im_ei_t imei[2]; /* The i-cluster mask data for 2 warps */
+ //! The 4 j-clusters
+ int cj[4];
+ //! The i-cluster mask data for 2 warps
+ nbnxn_im_ei_t imei[2];
} nbnxn_cj4_t;
*/
} nbnxn_excl_t;
-/*! i-cluster interaction mask for a super-cluster with all NCL_PER_SUPERCL bits set */
-__constant unsigned supercl_interaction_mask = ((1U << NCL_PER_SUPERCL) - 1U);
+/*! i-cluster interaction mask for a super-cluster with all c_nbnxnGpuNumClusterPerSupercluster bits set */
+__constant unsigned supercl_interaction_mask = ((1U << c_nbnxnGpuNumClusterPerSupercluster) - 1U);
gmx_opencl_inline void preloadCj4Generic(__local int* sm_cjPreload,
const __global int* gm_cj,
/* Only does reduction over 4 elements in cluster (2 per warp). Needs to be changed
* for CL_SIZE>4.*/
float2 fshift_buf = 0;
- for (int ci_offset = 0; ci_offset < NCL_PER_SUPERCL; ci_offset++)
+ for (int ci_offset = 0; ci_offset < c_nbnxnGpuNumClusterPerSupercluster; ci_offset++)
{
- int aidx = (sci * NCL_PER_SUPERCL + ci_offset) * CL_SIZE + tidxi;
+ int aidx = (sci * c_nbnxnGpuNumClusterPerSupercluster + ci_offset) * CL_SIZE + tidxi;
float3 fin = fci_buf[ci_offset];
fin.x += intel_sub_group_shuffle_down(fin.x, fin.x, CL_SIZE);
fin.y += intel_sub_group_shuffle_up(fin.y, fin.y, CL_SIZE);
__global float* fshift)
{
float fshift_buf = 0;
- for (int ci_offset = 0; ci_offset < NCL_PER_SUPERCL; ci_offset++)
+ for (int ci_offset = 0; ci_offset < c_nbnxnGpuNumClusterPerSupercluster; ci_offset++)
{
- int aidx = (sci * NCL_PER_SUPERCL + ci_offset) * CL_SIZE + tidxi;
+ int aidx = (sci * c_nbnxnGpuNumClusterPerSupercluster + ci_offset) * CL_SIZE + tidxi;
int tidx = tidxi + tidxj * CL_SIZE;
/* store i forces in shmem */
f_buf[tidx] = fci_buf[ci_offset].x;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "nbnxm_ocl_consts.h"
+struct gmx_wallclock_gpu_nbnxn_t;
+
/* kernel does #include "gromacs/math/utilities.h" */
/* Move the actual useful stuff here: */
const int c_oclPruneKernelJ4ConcurrencyDEFAULT = GMX_NBNXN_PRUNE_KERNEL_J4_CONCURRENCY_DEFAULT;
/*! @} */
-/*! \brief Returns the j4 processing concurrency parameter for the vendor \p vendorId
- * \param vendorId takes values from #ocl_vendor_id_t.
- */
-static inline int getOclPruneKernelJ4Concurrency(int vendorId)
-{
- switch (vendorId)
- {
- default: return c_oclPruneKernelJ4ConcurrencyDEFAULT;
- }
-}
-
-
/*! \brief Electrostatic OpenCL kernel flavors.
*
* Types of electrostatics implementations available in the OpenCL non-bonded
* The energies/shift forces get downloaded here first, before getting added
* to the CPU-side aggregate values.
*/
-typedef struct cl_nb_staging
+struct nb_staging_t
{
- float* e_lj; /**< LJ energy */
- float* e_el; /**< electrostatic energy */
- float (*fshift)[3]; /**< float3 buffer with shift forces */
-} cl_nb_staging_t;
+ //! LJ energy
+ float* e_lj = nullptr;
+ //! electrostatic energy
+ float* e_el = nullptr;
+ //! float3 buffer with shift forces
+ float (*fshift)[3] = nullptr;
+};
/*! \internal
* \brief Nonbonded atom data - both inputs and outputs.
*/
typedef struct cl_atomdata
{
- int natoms; /**< number of atoms */
- int natoms_local; /**< number of local atoms */
- int nalloc; /**< allocation size for the atom data (xq, f) */
-
- cl_mem xq; /**< float4 buffer with atom coordinates + charges, size natoms */
-
- cl_mem f; /**< float3 buffer with force output array, size natoms */
- size_t f_elem_size; /**< Size in bytes for one element of f buffer */
-
- cl_mem e_lj; /**< LJ energy output, size 1 */
- cl_mem e_el; /**< Electrostatics energy input, size 1 */
-
- cl_mem fshift; /**< float3 buffer with shift forces */
- size_t fshift_elem_size; /**< Size in bytes for one element of fshift buffer */
-
- int ntypes; /**< number of atom types */
- cl_mem atom_types; /**< int buffer with atom type indices, size natoms */
- cl_mem lj_comb; /**< float2 buffer with sqrt(c6),sqrt(c12), size natoms */
-
- cl_mem shift_vec; /**< float3 buffer with shifts values */
- size_t shift_vec_elem_size; /**< Size in bytes for one element of shift_vec buffer */
-
- cl_bool bShiftVecUploaded; /**< true if the shift vector has been uploaded */
+ //! number of atoms
+ int natoms;
+ //! number of local atoms
+ int natoms_local;
+ //! allocation size for the atom data (xq, f)
+ int nalloc;
+
+ //! float4 buffer with atom coordinates + charges, size natoms
+ cl_mem xq;
+
+ //! float3 buffer with force output array, size natoms
+ cl_mem f;
+
+ //! LJ energy output, size 1
+ cl_mem e_lj;
+ //! Electrostatics energy input, size 1
+ cl_mem e_el;
+
+ //! float3 buffer with shift forces
+ cl_mem fshift;
+
+ //! number of atom types
+ int ntypes;
+ //! int buffer with atom type indices, size natoms
+ cl_mem atom_types;
+ //! float2 buffer with sqrt(c6),sqrt(c12), size natoms
+ cl_mem lj_comb;
+
+ //! float3 buffer with shifts values
+ cl_mem shift_vec;
+
+ //! true if the shift vector has been uploaded
+ bool bShiftVecUploaded;
} cl_atomdata_t;
/*! \internal
typedef struct cl_nbparam
{
- int eeltype; /**< type of electrostatics, takes values from #eelOcl */
- int vdwtype; /**< type of VdW impl., takes values from #evdwOcl */
-
- float epsfac; /**< charge multiplication factor */
- float c_rf; /**< Reaction-field/plain cutoff electrostatics const. */
- float two_k_rf; /**< Reaction-field electrostatics constant */
- float ewald_beta; /**< Ewald/PME parameter */
- float sh_ewald; /**< Ewald/PME correction term substracted from the direct-space potential */
- float sh_lj_ewald; /**< LJ-Ewald/PME correction term added to the correction potential */
- float ewaldcoeff_lj; /**< LJ-Ewald/PME coefficient */
-
- float rcoulomb_sq; /**< Coulomb cut-off squared */
-
- float rvdw_sq; /**< VdW cut-off squared */
- float rvdw_switch; /**< VdW switched cut-off */
- float rlistOuter_sq; /**< Full, outer pair-list cut-off squared */
- float rlistInner_sq; /**< Inner, dynamic pruned pair-list cut-off squared */
- bool useDynamicPruning; /**< True if we use dynamic pair-list pruning */
-
- shift_consts_t dispersion_shift; /**< VdW shift dispersion constants */
- shift_consts_t repulsion_shift; /**< VdW shift repulsion constants */
- switch_consts_t vdw_switch; /**< VdW switch constants */
+ //! type of electrostatics, takes values from #eelOcl
+ int eeltype;
+ //! type of VdW impl., takes values from #evdwOcl
+ int vdwtype;
+
+ //! charge multiplication factor
+ float epsfac;
+ //! Reaction-field/plain cutoff electrostatics const.
+ float c_rf;
+ //! Reaction-field electrostatics constant
+ float two_k_rf;
+ //! Ewald/PME parameter
+ float ewald_beta;
+ //! Ewald/PME correction term substracted from the direct-space potential
+ float sh_ewald;
+ //! LJ-Ewald/PME correction term added to the correction potential
+ float sh_lj_ewald;
+ //! LJ-Ewald/PME coefficient
+ float ewaldcoeff_lj;
+
+ //! Coulomb cut-off squared
+ float rcoulomb_sq;
+
+ //! VdW cut-off squared
+ float rvdw_sq;
+ //! VdW switched cut-off
+ float rvdw_switch;
+ //! Full, outer pair-list cut-off squared
+ float rlistOuter_sq;
+ //! Inner, dynamic pruned pair-list cut-off squared
+ float rlistInner_sq;
+ //! True if we use dynamic pair-list pruning
+ bool useDynamicPruning;
+
+ //! VdW shift dispersion constants
+ shift_consts_t dispersion_shift;
+ //! VdW shift repulsion constants
+ shift_consts_t repulsion_shift;
+ //! VdW switch constants
+ switch_consts_t vdw_switch;
/* LJ non-bonded parameters - accessed through texture memory */
- cl_mem nbfp_climg2d; /**< nonbonded parameter table with C6/C12 pairs per atom type-pair, 2*ntype^2 elements */
- cl_mem nbfp_comb_climg2d; /**< nonbonded parameter table per atom type, 2*ntype elements */
+ //! nonbonded parameter table with C6/C12 pairs per atom type-pair, 2*ntype^2 elements
+ cl_mem nbfp_climg2d;
+ //! nonbonded parameter table per atom type, 2*ntype elements
+ cl_mem nbfp_comb_climg2d;
/* Ewald Coulomb force table data - accessed through texture memory */
- float coulomb_tab_scale; /**< table scale/spacing */
- cl_mem coulomb_tab_climg2d; /**< pointer to the table in the device memory */
+ //! table scale/spacing
+ float coulomb_tab_scale;
+ //! pointer to the table in the device memory
+ cl_mem coulomb_tab_climg2d;
} cl_nbparam_t;
/*! \internal
typedef struct cl_nbparam_params
{
- int eeltype; /**< type of electrostatics, takes values from #eelCu */
- int vdwtype; /**< type of VdW impl., takes values from #evdwCu */
-
- float epsfac; /**< charge multiplication factor */
- float c_rf; /**< Reaction-field/plain cutoff electrostatics const. */
- float two_k_rf; /**< Reaction-field electrostatics constant */
- float ewald_beta; /**< Ewald/PME parameter */
- float sh_ewald; /**< Ewald/PME correction term substracted from the direct-space potential */
- float sh_lj_ewald; /**< LJ-Ewald/PME correction term added to the correction potential */
- float ewaldcoeff_lj; /**< LJ-Ewald/PME coefficient */
-
- float rcoulomb_sq; /**< Coulomb cut-off squared */
-
- float rvdw_sq; /**< VdW cut-off squared */
- float rvdw_switch; /**< VdW switched cut-off */
- float rlistOuter_sq; /**< Full, outer pair-list cut-off squared */
- float rlistInner_sq; /**< Inner, dynamic pruned pair-list cut-off squared */
-
- shift_consts_t dispersion_shift; /**< VdW shift dispersion constants */
- shift_consts_t repulsion_shift; /**< VdW shift repulsion constants */
- switch_consts_t vdw_switch; /**< VdW switch constants */
+ //! type of electrostatics, takes values from #eelCu
+ int eeltype;
+ //! type of VdW impl., takes values from #evdwCu
+ int vdwtype;
+
+ //! charge multiplication factor
+ float epsfac;
+ //! Reaction-field/plain cutoff electrostatics const.
+ float c_rf;
+ //! Reaction-field electrostatics constant
+ float two_k_rf;
+ //! Ewald/PME parameter
+ float ewald_beta;
+ //! Ewald/PME correction term substracted from the direct-space potential
+ float sh_ewald;
+ //! LJ-Ewald/PME correction term added to the correction potential
+ float sh_lj_ewald;
+ //! LJ-Ewald/PME coefficient
+ float ewaldcoeff_lj;
+
+ //! Coulomb cut-off squared
+ float rcoulomb_sq;
+
+ //! VdW cut-off squared
+ float rvdw_sq;
+ //! VdW switched cut-off
+ float rvdw_switch;
+ //! Full, outer pair-list cut-off squared
+ float rlistOuter_sq;
+ //! Inner, dynamic pruned pair-list cut-off squared
+ float rlistInner_sq;
+
+ //! VdW shift dispersion constants
+ shift_consts_t dispersion_shift;
+ //! VdW shift repulsion constants
+ shift_consts_t repulsion_shift;
+ //! VdW switch constants
+ switch_consts_t vdw_switch;
/* Ewald Coulomb force table data - accessed through texture memory */
- float coulomb_tab_scale; /**< table scale/spacing */
+ //! table scale/spacing
+ float coulomb_tab_scale;
} cl_nbparam_params_t;
/*! \internal
* \brief Main data structure for OpenCL nonbonded force calculations.
*/
-struct gmx_nbnxn_ocl_t
+struct NbnxmGpu
{
- const gmx_device_info_t* dev_info; /**< OpenCL device information */
- struct gmx_device_runtime_data_t* dev_rundata; /**< OpenCL runtime data (context, kernels) */
+ /* \brief OpenCL device context
+ *
+ * \todo Make it constant reference, once NbnxmGpu is a proper class.
+ */
+ const DeviceContext* deviceContext_;
+ //! OpenCL runtime data (context, kernels)
+ struct gmx_device_runtime_data_t* dev_rundata = nullptr;
/**< Pointers to non-bonded kernel functions
* organized similar with nb_kfunc_xxx arrays in nbnxn_ocl.cpp */
///@{
- cl_kernel kernel_noener_noprune_ptr[eelOclNR][evdwOclNR];
- cl_kernel kernel_ener_noprune_ptr[eelOclNR][evdwOclNR];
- cl_kernel kernel_noener_prune_ptr[eelOclNR][evdwOclNR];
- cl_kernel kernel_ener_prune_ptr[eelOclNR][evdwOclNR];
+ cl_kernel kernel_noener_noprune_ptr[eelOclNR][evdwOclNR] = { { nullptr } };
+ cl_kernel kernel_ener_noprune_ptr[eelOclNR][evdwOclNR] = { { nullptr } };
+ cl_kernel kernel_noener_prune_ptr[eelOclNR][evdwOclNR] = { { nullptr } };
+ cl_kernel kernel_ener_prune_ptr[eelOclNR][evdwOclNR] = { { nullptr } };
///@}
- cl_kernel kernel_pruneonly[ePruneNR]; /**< prune kernels, ePruneKind defined the kernel kinds */
+ //! prune kernels, ePruneKind defined the kernel kinds
+ cl_kernel kernel_pruneonly[ePruneNR] = { nullptr };
- bool bPrefetchLjParam; /**< true if prefetching fg i-atom LJ parameters should be used in the kernels */
+ //! true if prefetching fg i-atom LJ parameters should be used in the kernels
+ bool bPrefetchLjParam = false;
/**< auxiliary kernels implementing memset-like functions */
///@{
- cl_kernel kernel_memset_f;
- cl_kernel kernel_memset_f2;
- cl_kernel kernel_memset_f3;
- cl_kernel kernel_zero_e_fshift;
+ cl_kernel kernel_memset_f = nullptr;
+ cl_kernel kernel_memset_f2 = nullptr;
+ cl_kernel kernel_memset_f3 = nullptr;
+ cl_kernel kernel_zero_e_fshift = nullptr;
///@}
- cl_bool bUseTwoStreams; /**< true if doing both local/non-local NB work on GPU */
- cl_bool bNonLocalStreamActive; /**< true indicates that the nonlocal_done event was enqueued */
-
- cl_atomdata_t* atdat; /**< atom data */
- cl_nbparam_t* nbparam; /**< parameters required for the non-bonded calc. */
- gmx::EnumerationArray<Nbnxm::InteractionLocality, cl_plist_t*> plist; /**< pair-list data structures (local and non-local) */
- cl_nb_staging_t nbst; /**< staging area where fshift/energies get downloaded */
-
- gmx::EnumerationArray<Nbnxm::InteractionLocality, cl_command_queue> stream; /**< local and non-local GPU queues */
-
- /** events used for synchronization */
- cl_event nonlocal_done; /**< event triggered when the non-local non-bonded kernel
- is done (and the local transfer can proceed) */
- cl_event misc_ops_and_local_H2D_done; /**< event triggered when the tasks issued in
- the local stream that need to precede the
- non-local force calculations are done
- (e.g. f buffer 0-ing, local x/q H2D) */
+ //! true if doing both local/non-local NB work on GPU
+ bool bUseTwoStreams = false;
+ //! true indicates that the nonlocal_done event was enqueued
+ bool bNonLocalStreamActive = false;
+
+ //! atom data
+ cl_atomdata_t* atdat = nullptr;
+ //! parameters required for the non-bonded calc.
+ cl_nbparam_t* nbparam = nullptr;
+ //! pair-list data structures (local and non-local)
+ gmx::EnumerationArray<Nbnxm::InteractionLocality, cl_plist_t*> plist = { nullptr };
+ //! staging area where fshift/energies get downloaded
+ nb_staging_t nbst;
+
+ //! local and non-local GPU queues
+ gmx::EnumerationArray<Nbnxm::InteractionLocality, const DeviceStream*> deviceStreams;
+
+ /*! \brief Events used for synchronization */
+ /*! \{ */
+ /*! \brief Event triggered when the non-local non-bonded
+ * kernel is done (and the local transfer can proceed) */
+ cl_event nonlocal_done = nullptr;
+ /*! \brief Event triggered when the tasks issued in the local
+ * stream that need to precede the non-local force or buffer
+ * operation calculations are done (e.g. f buffer 0-ing, local
+ * x/q H2D, buffer op initialization in local stream that is
+ * required also by nonlocal stream ) */
+ cl_event misc_ops_and_local_H2D_done = nullptr;
+ /*! \} */
//! True if there has been local/nonlocal GPU work, either bonded or nonbonded, scheduled
// to be executed in the current domain. As long as bonded work is not split up into
gmx::EnumerationArray<Nbnxm::InteractionLocality, bool> haveWork;
- cl_bool bDoTime; /**< True if event-based timing is enabled. */
- cl_timers_t* timers; /**< OpenCL event-based timers. */
- struct gmx_wallclock_gpu_nbnxn_t* timings; /**< Timing data. TODO: deprecate this and query timers for accumulated data instead */
+ //! True if event-based timing is enabled.
+ bool bDoTime = false;
+ //! OpenCL event-based timers.
+ cl_timers_t* timers = nullptr;
+ //! Timing data. TODO: deprecate this and query timers for accumulated data instead
+ gmx_wallclock_gpu_nbnxn_t* timings = nullptr;
};
#endif /* NBNXN_OPENCL_TYPES_H */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/mdlib/gmx_omp_nthreads.h"
#include "gromacs/mdtypes/group.h"
#include "gromacs/mdtypes/md_enums.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/nbnxm/gpu_data_mgmt.h"
#include "gromacs/pbcutil/ishift.h"
#include "gromacs/pbcutil/pbc.h"
#include "gromacs/simd/simd.h"
#include "gromacs/simd/vector_operations.h"
-#include "gromacs/topology/block.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxomp.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
-#include "atomdata.h"
#include "boundingboxes.h"
#include "clusterdistancekerneltype.h"
#include "gridset.h"
Gpu8x8x8 // i-cluster size 8, j-cluster size 8 + super-clustering
};
-#if GMX_SIMD
+#if defined(GMX_NBNXN_SIMD_4XN) || defined(GMX_NBNXN_SIMD_2XNN)
/* Returns the j-cluster size */
template<NbnxnLayout layout>
static constexpr int jClusterSize()
return cj * STRIDE_P8;
}
}
-#endif // GMX_SIMD
+#endif // defined(GMX_NBNXN_SIMD_4XN) || defined(GMX_NBNXN_SIMD_2XNN)
void nbnxn_init_pairlist_fep(t_nblist* nl)
* Set all atom-pair exclusions from the topology stored in exclusions
* as masks in the pair-list for simple list entry iEntry.
*/
-static void setExclusionsForIEntry(const Nbnxm::GridSet& gridSet,
- NbnxnPairlistCpu* nbl,
- gmx_bool diagRemoved,
- int na_cj_2log,
- const nbnxn_ci_t& iEntry,
- const t_blocka& exclusions)
+static void setExclusionsForIEntry(const Nbnxm::GridSet& gridSet,
+ NbnxnPairlistCpu* nbl,
+ gmx_bool diagRemoved,
+ int na_cj_2log,
+ const nbnxn_ci_t& iEntry,
+ const ListOfLists<int>& exclusions)
{
if (iEntry.cj_ind_end == iEntry.cj_ind_start)
{
if (iAtom >= 0)
{
/* Loop over the topology-based exclusions for this i-atom */
- for (int exclIndex = exclusions.index[iAtom]; exclIndex < exclusions.index[iAtom + 1];
- exclIndex++)
+ for (const int jAtom : exclusions[iAtom])
{
- const int jAtom = exclusions.a[exclIndex];
-
if (jAtom == iAtom)
{
/* The self exclusion are already set, save some time */
static void setExclusionsForIEntry(const Nbnxm::GridSet& gridSet,
NbnxnPairlistGpu* nbl,
gmx_bool diagRemoved,
- int gmx_unused na_cj_2log,
- const nbnxn_sci_t& iEntry,
- const t_blocka& exclusions)
+ int gmx_unused na_cj_2log,
+ const nbnxn_sci_t& iEntry,
+ const ListOfLists<int>& exclusions)
{
if (iEntry.numJClusterGroups() == 0)
{
const int iCluster = i / c_clusterSize;
/* Loop over the topology-based exclusions for this i-atom */
- for (int exclIndex = exclusions.index[iAtom]; exclIndex < exclusions.index[iAtom + 1];
- exclIndex++)
+ for (const int jAtom : exclusions[iAtom])
{
- const int jAtom = exclusions.a[exclIndex];
-
if (jAtom == iAtom)
{
/* The self exclusions are already set, save some time */
const Grid& jGrid,
PairsearchWork* work,
const nbnxn_atomdata_t* nbat,
- const t_blocka& exclusions,
+ const ListOfLists<int>& exclusions,
real rlist,
const PairlistType pairlistType,
int ci_block,
/* Check if we need periodicity shifts.
* Without PBC or with domain decomposition we don't need them.
*/
- if (d >= ePBC2npbcdim(gridSet.domainSetup().ePBC)
+ if (d >= numPbcDimensions(gridSet.domainSetup().pbcType)
|| gridSet.domainSetup().haveMultipleDomainsPerDim[d])
{
shp[d] = 0;
}
}
- /* Set the exclusions for this ci list */
- setExclusionsForIEntry(gridSet, nbl, excludeSubDiagonal, na_cj_2log,
- *getOpenIEntry(nbl), exclusions);
+ if (!exclusions.empty())
+ {
+ /* Set the exclusions for this ci list */
+ setExclusionsForIEntry(gridSet, nbl, excludeSubDiagonal, na_cj_2log,
+ *getOpenIEntry(nbl), exclusions);
+ }
if (haveFep)
{
void PairlistSet::constructPairlists(const Nbnxm::GridSet& gridSet,
gmx::ArrayRef<PairsearchWork> searchWork,
nbnxn_atomdata_t* nbat,
- const t_blocka* excl,
+ const ListOfLists<int>& exclusions,
const int minimumIlistCountForGpuBalancing,
t_nrnb* nrnb,
SearchCycleCounting* searchCycleCounting)
/* Divide the i cells equally over the pairlists */
if (isCpuType_)
{
- nbnxn_make_pairlist_part(gridSet, iGrid, jGrid, &work, nbat, *excl, rlist,
+ nbnxn_make_pairlist_part(gridSet, iGrid, jGrid, &work, nbat, exclusions, rlist,
params_.pairlistType, ci_block, nbat->bUseBufferFlags,
nsubpair_target, progBal, nsubpair_tot_est, th,
numLists, &cpuLists_[th], fepListPtr);
}
else
{
- nbnxn_make_pairlist_part(gridSet, iGrid, jGrid, &work, nbat, *excl, rlist,
+ nbnxn_make_pairlist_part(gridSet, iGrid, jGrid, &work, nbat, exclusions, rlist,
params_.pairlistType, ci_block, nbat->bUseBufferFlags,
nsubpair_target, progBal, nsubpair_tot_est, th,
numLists, &gpuLists_[th], fepListPtr);
void PairlistSets::construct(const InteractionLocality iLocality,
PairSearch* pairSearch,
nbnxn_atomdata_t* nbat,
- const t_blocka* excl,
+ const ListOfLists<int>& exclusions,
const int64_t step,
t_nrnb* nrnb)
{
- pairlistSet(iLocality).constructPairlists(pairSearch->gridSet(), pairSearch->work(), nbat, excl,
+ const auto& gridSet = pairSearch->gridSet();
+ const auto* ddZones = gridSet.domainSetup().zones;
+
+ /* The Nbnxm code can also work with more exclusions than those in i-zones only
+ * when using DD, but the equality check can catch more issues.
+ */
+ GMX_RELEASE_ASSERT(
+ exclusions.empty() || (!ddZones && exclusions.ssize() == gridSet.numRealAtomsTotal())
+ || (ddZones && exclusions.ssize() == ddZones->cg_range[ddZones->iZones.size()]),
+ "exclusions should either be empty or the number of lists should match the number of "
+ "local i-atoms");
+
+ pairlistSet(iLocality).constructPairlists(gridSet, pairSearch->work(), nbat, exclusions,
minimumIlistCountForGpuBalancing_, nrnb,
&pairSearch->cycleCounting_);
}
void nonbonded_verlet_t::constructPairlist(const InteractionLocality iLocality,
- const t_blocka* excl,
+ const ListOfLists<int>& exclusions,
int64_t step,
t_nrnb* nrnb)
{
- pairlistSets_->construct(iLocality, pairSearch_.get(), nbat.get(), excl, step, nrnb);
+ pairlistSets_->construct(iLocality, pairSearch_.get(), nbat.get(), exclusions, step, nrnb);
if (useGpu())
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, The GROMACS development team.
- * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/real.h"
-// This file with constants is separate from this file to be able
-// to include it during OpenCL jitting without including config.h
-#include "constants.h"
#include "pairlistparams.h"
struct NbnxnPairlistCpuWork;
struct NbnxnPairlistGpuWork;
-/* Convenience type for vector with aligned memory */
+//! Convenience type for vector with aligned memory
template<typename T>
using AlignedVector = std::vector<T, gmx::AlignedAllocator<T>>;
-/* Convenience type for vector that avoids initialization at resize() */
+//! Convenience type for vector that avoids initialization at resize()
template<typename T>
using FastVector = std::vector<T, gmx::DefaultInitializationAllocator<T>>;
-/* A buffer data structure of 64 bytes
+/*! \brief Cache-line protection buffer
+ *
+ * A buffer data structure of 64 bytes
* to be placed at the beginning and end of structs
* to avoid cache invalidation of the real contents
* of the struct by writes to neighboring memory.
*/
typedef struct
{
+ //! Unused field used to create space to protect cache lines that are in use
int dummy[16];
} gmx_cache_protect_t;
-/* This is the actual cluster-pair list j-entry.
+/*! \brief This is the actual cluster-pair list j-entry.
+ *
* cj is the j-cluster.
* The interaction bits in excl are indexed i-major, j-minor.
* The cj entries are sorted such that ones with exclusions come first.
*/
struct nbnxn_cj_t
{
- int cj; /* The j-cluster */
- unsigned int excl; /* The exclusion (interaction) bits */
+ //! The j-cluster
+ int cj;
+ //! The exclusion (interaction) bits
+ unsigned int excl;
};
-/* In nbnxn_ci_t the integer shift contains the shift in the lower 7 bits.
+/*! \brief Constants for interpreting interaction flags
+ *
+ * In nbnxn_ci_t the integer shift contains the shift in the lower 7 bits.
* The upper bits contain information for non-bonded kernel optimization.
* Simply calculating LJ and Coulomb for all pairs in a cluster pair is fine.
* But three flags can be used to skip interactions, currently only for subc=0
* shift & NBNXN_CI_HALF_LJ(subc) => we can skip LJ for the second half of i
* !(shift & NBNXN_CI_DO_COUL(subc)) => we can skip Coulomb for all pairs
*/
+//! \{
#define NBNXN_CI_SHIFT 127
#define NBNXN_CI_DO_LJ(subc) (1 << (7 + 3 * (subc)))
#define NBNXN_CI_HALF_LJ(subc) (1 << (8 + 3 * (subc)))
#define NBNXN_CI_DO_COUL(subc) (1 << (9 + 3 * (subc)))
+//! \}
-/* Cluster-pair Interaction masks
+/*! \brief Cluster-pair Interaction masks
+ *
* Bit i*j-cluster-size + j tells if atom i and j interact.
*/
+//! \{
// TODO: Rename according to convention when moving into Nbnxn namespace
-/* All interaction mask is the same for all kernels */
+//! All interaction mask is the same for all kernels
constexpr unsigned int NBNXN_INTERACTION_MASK_ALL = 0xffffffffU;
-/* 4x4 kernel diagonal mask */
+//! 4x4 kernel diagonal mask
constexpr unsigned int NBNXN_INTERACTION_MASK_DIAG = 0x08ceU;
-/* 4x2 kernel diagonal masks */
+//! 4x2 kernel diagonal masks
+//! \{
constexpr unsigned int NBNXN_INTERACTION_MASK_DIAG_J2_0 = 0x0002U;
constexpr unsigned int NBNXN_INTERACTION_MASK_DIAG_J2_1 = 0x002fU;
-/* 4x8 kernel diagonal masks */
+//! \}
+//! 4x8 kernel diagonal masks
+//! \{
constexpr unsigned int NBNXN_INTERACTION_MASK_DIAG_J8_0 = 0xf0f8fcfeU;
constexpr unsigned int NBNXN_INTERACTION_MASK_DIAG_J8_1 = 0x0080c0e0U;
+//! \}
+//! \}
+
+/*! \brief Lower limit for square interaction distances in nonbonded kernels.
+ *
+ * For smaller values we will overflow when calculating r^-1 or r^-12, but
+ * to keep it simple we always apply the limit from the tougher r^-12 condition.
+ */
+#if GMX_DOUBLE
+// Some double precision SIMD architectures use single precision in the first
+// step, so although the double precision criterion would allow smaller rsq,
+// we need to stay in single precision with some margin for the N-R iterations.
+constexpr double c_nbnxnMinDistanceSquared = 1.0e-36;
+#else
+// The worst intermediate value we might evaluate is r^-12, which
+// means we should ensure r^2 stays above pow(GMX_FLOAT_MAX,-1.0/6.0)*1.01 (some margin)
+constexpr float c_nbnxnMinDistanceSquared = 3.82e-07F; // r > 6.2e-4
+#endif
-/* Simple pair-list i-unit */
+
+//! The number of clusters in a super-cluster, used for GPU
+constexpr int c_nbnxnGpuNumClusterPerSupercluster = 8;
+
+/*! \brief With GPU kernels we group cluster pairs in 4 to optimize memory usage
+ * of integers containing 32 bits.
+ */
+constexpr int c_nbnxnGpuJgroupSize = (32 / c_nbnxnGpuNumClusterPerSupercluster);
+
+/*! \internal
+ * \brief Simple pair-list i-unit
+ */
struct nbnxn_ci_t
{
- int ci; /* i-cluster */
- int shift; /* Shift vector index plus possible flags, see above */
- int cj_ind_start; /* Start index into cj */
- int cj_ind_end; /* End index into cj */
+ //! i-cluster
+ int ci;
+ //! Shift vector index plus possible flags, see above
+ int shift;
+ //! Start index into cj
+ int cj_ind_start;
+ //! End index into cj
+ int cj_ind_end;
};
-/* Grouped pair-list i-unit */
+//! Grouped pair-list i-unit
typedef struct
{
- /* Returns the number of j-cluster groups in this entry */
+ //! Returns the number of j-cluster groups in this entry
int numJClusterGroups() const { return cj4_ind_end - cj4_ind_start; }
- int sci; /* i-super-cluster */
- int shift; /* Shift vector index plus possible flags */
- int cj4_ind_start; /* Start index into cj4 */
- int cj4_ind_end; /* End index into cj4 */
+ //! i-super-cluster
+ int sci;
+ //! Shift vector index plus possible flags
+ int shift;
+ //! Start index into cj4
+ int cj4_ind_start;
+ //! End index into cj4
+ int cj4_ind_end;
} nbnxn_sci_t;
-/* Interaction data for a j-group for one warp */
+//! Interaction data for a j-group for one warp
struct nbnxn_im_ei_t
{
- // The i-cluster interactions mask for 1 warp
+ //! The i-cluster interactions mask for 1 warp
unsigned int imask = 0U;
- // Index into the exclusion array for 1 warp, default index 0 which means no exclusions
+ //! Index into the exclusion array for 1 warp, default index 0 which means no exclusions
int excl_ind = 0;
};
+//! Four-way j-cluster lists
typedef struct
{
- int cj[c_nbnxnGpuJgroupSize]; /* The 4 j-clusters */
- nbnxn_im_ei_t imei[c_nbnxnGpuClusterpairSplit]; /* The i-cluster mask data for 2 warps */
+ //! The 4 j-clusters
+ int cj[c_nbnxnGpuJgroupSize];
+ //! The i-cluster mask data for 2 warps
+ nbnxn_im_ei_t imei[c_nbnxnGpuClusterpairSplit];
} nbnxn_cj4_t;
-/* Struct for storing the atom-pair interaction bits for a cluster pair in a GPU pairlist */
+//! Struct for storing the atom-pair interaction bits for a cluster pair in a GPU pairlist
struct nbnxn_excl_t
{
- /* Constructor, sets no exclusions, so all atom pairs interacting */
+ //! Constructor, sets no exclusions, so all atom pairs interacting
MSVC_DIAGNOSTIC_IGNORE(26495) // pair is not being initialized!
nbnxn_excl_t()
{
}
MSVC_DIAGNOSTIC_RESET
- /* Topology exclusion interaction bits per warp */
+ //! Topology exclusion interaction bits per warp
unsigned int pair[c_nbnxnGpuExclSize];
};
-/* Cluster pairlist type for use on CPUs */
+//! Cluster pairlist type for use on CPUs
struct NbnxnPairlistCpu
{
NbnxnPairlistCpu();
+ //! Cache protection
gmx_cache_protect_t cp0;
- int na_ci; /* The number of atoms per i-cluster */
- int na_cj; /* The number of atoms per j-cluster */
- real rlist; /* The radius for constructing the list */
- FastVector<nbnxn_ci_t> ci; /* The i-cluster list */
- FastVector<nbnxn_ci_t> ciOuter; /* The outer, unpruned i-cluster list */
-
- FastVector<nbnxn_cj_t> cj; /* The j-cluster list, size ncj */
- FastVector<nbnxn_cj_t> cjOuter; /* The outer, unpruned j-cluster list */
- int ncjInUse; /* The number of j-clusters that are used by ci entries in this list, will be <= cj.size() */
-
- int nci_tot; /* The total number of i clusters */
+ //! The number of atoms per i-cluster
+ int na_ci;
+ //! The number of atoms per j-cluster
+ int na_cj;
+ //! The radius for constructing the list
+ real rlist;
+ //! The i-cluster list
+ FastVector<nbnxn_ci_t> ci;
+ //! The outer, unpruned i-cluster list
+ FastVector<nbnxn_ci_t> ciOuter;
+
+ //! The j-cluster list, size ncj
+ FastVector<nbnxn_cj_t> cj;
+ //! The outer, unpruned j-cluster list
+ FastVector<nbnxn_cj_t> cjOuter;
+ //! The number of j-clusters that are used by ci entries in this list, will be <= cj.size()
+ int ncjInUse;
+
+ //! The total number of i clusters
+ int nci_tot;
- /* Working data storage for list construction */
+ //! Working data storage for list construction
std::unique_ptr<NbnxnPairlistCpuWork> work;
+ //! Cache protection
gmx_cache_protect_t cp1;
};
*/
struct NbnxnPairlistGpu
{
- /* Constructor
+ /*! \brief Constructor
*
* \param[in] pinningPolicy Sets the pinning policy for all buffers used on the GPU
*/
NbnxnPairlistGpu(gmx::PinningPolicy pinningPolicy);
+ //! Cache protection
gmx_cache_protect_t cp0;
- int na_ci; /* The number of atoms per i-cluster */
- int na_cj; /* The number of atoms per j-cluster */
- int na_sc; /* The number of atoms per super cluster */
- real rlist; /* The radius for constructing the list */
+ //! The number of atoms per i-cluster
+ int na_ci;
+ //! The number of atoms per j-cluster
+ int na_cj;
+ //! The number of atoms per super cluster
+ int na_sc;
+ //! The radius for constructing the list
+ real rlist;
// The i-super-cluster list, indexes into cj4;
gmx::HostVector<nbnxn_sci_t> sci;
// The list of 4*j-cluster groups
// The total number of i-clusters
int nci_tot;
- /* Working data storage for list construction */
+ //! Working data storage for list construction
std::unique_ptr<NbnxnPairlistGpuWork> work;
+ //! Cache protection
gmx_cache_protect_t cp1;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ *
+ * \brief
+ * Declares inline-friendly code for making 2xNN pairlists
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
+
-/* Stride of the packed x coordinate array */
+//! Stride of the packed x coordinate array
static constexpr int c_xStride2xNN = (GMX_SIMD_REAL_WIDTH >= 2 * c_nbnxnCpuIClusterSize)
? GMX_SIMD_REAL_WIDTH / 2
: c_nbnxnCpuIClusterSize;
-/* Copies PBC shifted i-cell packed atom coordinates to working array */
+//! Copies PBC shifted i-cell packed atom coordinates to working array
static inline void icell_set_x_simd_2xnn(int ci,
real shx,
real shy,
loadU1DualHsimd(x + ia + 2 * c_xStride2xNN + 2) + SimdReal(shz));
}
-/* SIMD code for checking and adding cluster-pairs to the list using coordinates in packed format.
+/*! \brief SIMD code for checking and adding cluster-pairs to the list using coordinates in packed format.
*
* Checks bouding box distances and possibly atom pair distances.
* This is an accelerated version of make_cluster_list_simple.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* the research papers on the package. Check out http://www.gromacs.org.
*/
-/* Stride of the packed x coordinate array */
+/*! \internal \file
+ *
+ * \brief
+ * Declares inline-friendly code for making 4xN pairlists
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_nbnxm
+ */
+
+//! Stride of the packed x coordinate array
static constexpr int c_xStride4xN =
(GMX_SIMD_REAL_WIDTH > c_nbnxnCpuIClusterSize ? GMX_SIMD_REAL_WIDTH : c_nbnxnCpuIClusterSize);
-/* Copies PBC shifted i-cell packed atom coordinates to working array */
+//! Copies PBC shifted i-cell packed atom coordinates to working array
static inline void icell_set_x_simd_4xn(int ci,
real shx,
real shy,
store(x_ci_simd + 11 * GMX_SIMD_REAL_WIDTH, SimdReal(x[ia + 2 * c_xStride4xN + 3] + shz));
}
-/* SIMD code for checking and adding cluster-pairs to the list using coordinates in packed format.
+/*! \brief SIMD code for checking and adding cluster-pairs to the list using coordinates in packed format.
*
* Checks bouding box distances and possibly atom pair distances.
* This is an accelerated version of make_cluster_list_simple.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
rlist_new = calcVerletBufferSize(*mtop, det(box), *ir, ir->nstlist, ir->nstlist - 1, -1, listSetup);
/* Does rlist fit in the box? */
- bBox = (gmx::square(rlist_new) < max_cutoff2(ir->ePBC, box));
+ bBox = (gmx::square(rlist_new) < max_cutoff2(ir->pbcType, box));
bDD = TRUE;
if (bBox && DOMAINDECOMP(cr))
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
PairlistParams(Nbnxm::KernelType kernelType, bool haveFep, real rlist, bool haveMultipleDomains);
- PairlistType pairlistType; //!< The type of cluster-pair list
- bool haveFep; //!< Tells whether we have perturbed interactions
- real rlistOuter; //!< Cut-off of the larger, outer pair-list
- real rlistInner; //!< Cut-off of the smaller, inner pair-list
- bool haveMultipleDomains; //!< True when using DD with multiple domains
- bool useDynamicPruning; //!< Are we using dynamic pair-list pruning
- int nstlistPrune; //!< Pair-list dynamic pruning interval
- int numRollingPruningParts; //!< The number parts to divide the pair-list into for rolling pruning, a value of 1 gives no rolling pruning
- int lifetime; //!< Lifetime in steps of the pair-list
+ //! The type of cluster-pair list
+ PairlistType pairlistType;
+ //! Tells whether we have perturbed interactions
+ bool haveFep;
+ //! Cut-off of the larger, outer pair-list
+ real rlistOuter;
+ //! Cut-off of the smaller, inner pair-list
+ real rlistInner;
+ //! True when using DD with multiple domains
+ bool haveMultipleDomains;
+ //! Are we using dynamic pair-list pruning
+ bool useDynamicPruning;
+ //! Pair-list dynamic pruning interval
+ int nstlistPrune;
+ //! The number parts to divide the pair-list into for rolling pruning, a value of 1 gives no rolling pruning
+ int numRollingPruningParts;
+ //! Lifetime in steps of the pair-list
+ int lifetime;
};
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct PairlistParams;
struct PairsearchWork;
struct SearchCycleCounting;
-struct t_blocka;
struct t_nrnb;
+namespace gmx
+{
+template<typename>
+class ListOfLists;
+}
+
namespace Nbnxm
{
class GridSet;
void constructPairlists(const Nbnxm::GridSet& gridSet,
gmx::ArrayRef<PairsearchWork> searchWork,
nbnxn_atomdata_t* nbat,
- const t_blocka* excl,
+ const gmx::ListOfLists<int>& exclusions,
int minimumIlistCountForGpuBalancing,
t_nrnb* nrnb,
SearchCycleCounting* searchCycleCounting);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class PairlistSet;
enum class PairlistType;
class PairSearch;
-struct t_blocka;
struct t_nrnb;
+namespace gmx
+{
+template<typename>
+class ListOfLists;
+}
+//! Contains sets of pairlists \internal
class PairlistSets
{
public:
+ //! Constructor
PairlistSets(const PairlistParams& pairlistParams,
bool haveMultipleDomains,
int minimumIlistCountForGpuBalancing);
//! Construct the pairlist set for the given locality
- void construct(gmx::InteractionLocality iLocality,
- PairSearch* pairSearch,
- nbnxn_atomdata_t* nbat,
- const t_blocka* excl,
- int64_t step,
- t_nrnb* nrnb);
+ void construct(gmx::InteractionLocality iLocality,
+ PairSearch* pairSearch,
+ nbnxn_atomdata_t* nbat,
+ const gmx::ListOfLists<int>& exclusions,
+ int64_t step,
+ t_nrnb* nrnb);
//! Dispatches the dynamic pruning kernel for the given locality
void dispatchPruneKernel(gmx::InteractionLocality iLocality,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "grid.h"
#include "pairlist.h"
-/* Working data for the actual i-supercell during pair search */
+//! Working data for the actual i-supercell during pair search \internal
struct NbnxnPairlistCpuWork
{
- // Struct for storing coordinats and bounding box for an i-entry during search
+ //! Struct for storing coordinats and bounding box for an i-entry during search \internal
struct IClusterData
{
IClusterData() :
{
}
- // The bounding boxes, pbc shifted, for each cluster
+ //! The bounding boxes, pbc shifted, for each cluster
AlignedVector<Nbnxm::BoundingBox> bb;
- // The coordinates, pbc shifted, for each atom
+ //! The coordinates, pbc shifted, for each atom
std::vector<real> x;
- // Aligned list for storing 4*DIM*GMX_SIMD_REAL_WIDTH reals
+ //! Aligned list for storing 4*DIM*GMX_SIMD_REAL_WIDTH reals
AlignedVector<real> xSimd;
};
- // Protect data from cache pollution between threads
+ //! Protect data from cache pollution between threads
gmx_cache_protect_t cp0;
- // Work data for generating an IEntry in the pairlist
+ //! Work data for generating an IEntry in the pairlist
IClusterData iClusterData;
- // The current cj_ind index for the current list
+ //! The current cj_ind index for the current list
int cj_ind;
- // Temporary j-cluster list, used for sorting on exclusions
+ //! Temporary j-cluster list, used for sorting on exclusions
std::vector<nbnxn_cj_t> cj;
- // Nr. of cluster pairs without Coulomb for flop counting
+ //! Nr. of cluster pairs without Coulomb for flop counting
int ncj_noq;
- // Nr. of cluster pairs with 1/2 LJ for flop count
+ //! Nr. of cluster pairs with 1/2 LJ for flop count
int ncj_hlj;
- // Protect data from cache pollution between threads
+ //! Protect data from cache pollution between threads
gmx_cache_protect_t cp1;
};
{
}
- // The bounding boxes, pbc shifted, for each cluster
+ //! The bounding boxes, pbc shifted, for each cluster
AlignedVector<Nbnxm::BoundingBox> bb;
- // As bb, but in packed xxxx format
+ //! As bb, but in packed xxxx format
AlignedVector<float> bbPacked;
- // The coordinates, pbc shifted, for each atom
+ //! The coordinates, pbc shifted, for each atom
AlignedVector<real> x;
- // Aligned coordinate list used for 4*DIM*GMX_SIMD_REAL_WIDTH floats
+ //! Aligned coordinate list used for 4*DIM*GMX_SIMD_REAL_WIDTH floats
AlignedVector<real> xSimd;
};
{
}
- // Protect data from cache pollution between threads
+ //! Protect data from cache pollution between threads
gmx_cache_protect_t cp0;
- // Work data for generating an i-entry in the pairlist
+ //! Work data for generating an i-entry in the pairlist
ISuperClusterData iSuperClusterData;
- // The current j-cluster index for the current list
+ //! The current j-cluster index for the current list
int cj_ind;
- // Bounding box distance work array
+ //! Bounding box distance work array
AlignedVector<float> distanceBuffer;
- // Buffer for sorting list entries
+ //! Buffer for sorting list entries
std::vector<int> sortBuffer;
- // Second sci array, for sorting
+ //! Second sci array, for sorting
gmx::HostVector<nbnxn_sci_t> sci_sort;
- // Protect data from cache pollution between threads
+ //! Protect data from cache pollution between threads
gmx_cache_protect_t cp1;
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
free_nblist(nbl_fep.get());
}
-PairSearch::PairSearch(const int ePBC,
+PairSearch::PairSearch(const PbcType pbcType,
const bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* ddZones,
const bool haveFep,
const int maxNumThreads,
gmx::PinningPolicy pinningPolicy) :
- gridSet_(ePBC, doTestParticleInsertion, numDDCells, ddZones, pairlistType, haveFep, maxNumThreads, pinningPolicy),
+ gridSet_(pbcType, doTestParticleInsertion, numDDCells, ddZones, pairlistType, haveFep, maxNumThreads, pinningPolicy),
work_(maxNumThreads)
{
cycleCounting_.recordCycles_ = (getenv("GMX_NBNXN_CYCLE") != nullptr);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/domdec/domdec.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/nbnxm/atomdata.h"
#include "gromacs/timing/cyclecounter.h"
#include "gromacs/utility/alignedallocator.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/real.h"
-#include "atomdata.h"
#include "gridset.h"
#include "pairlist.h"
using AlignedVector = std::vector<T, gmx::AlignedAllocator<T>>;
-/* Local cycle count struct for profiling */
+//! Local cycle count struct for profiling \internal
class nbnxn_cycle_t
{
public:
+ //! Start counting cycles
void start() { start_ = gmx_cycles_read(); }
-
+ //! Stop counting cycles
void stop()
{
cycles_ += gmx_cycles_read() - start_;
count_++;
}
-
+ //! Return the number of periods of cycle counting
int count() const { return count_; }
+ //! Return the average number of million cycles per counting period
double averageMCycles() const
{
if (count_ > 0)
}
private:
- int count_ = 0;
+ //! Number of counting periods
+ int count_ = 0;
+ //! Total cycles in all counting periods
gmx_cycles_t cycles_ = 0;
- gmx_cycles_t start_ = 0;
+ //! Cycle count at the most recent start
+ gmx_cycles_t start_ = 0;
};
//! Local cycle count enum for profiling different parts of search
// TODO: Move nbnxn_search_work_t definition to its own file
-/* Thread-local work struct, contains working data for Grid */
+//! Thread-local work struct, contains working data for Grid \internal
struct PairsearchWork
{
PairsearchWork();
~PairsearchWork();
- gmx_cache_protect_t cp0; /* Buffer to avoid cache polution */
+ //! Buffer to avoid cache polution
+ gmx_cache_protect_t cp0;
- std::vector<int> sortBuffer; /* Temporary buffer for sorting atoms within a grid column */
+ //! Temporary buffer for sorting atoms within a grid column
+ std::vector<int> sortBuffer;
- nbnxn_buffer_flags_t buffer_flags; /* Flags for force buffer access */
+ //! Flags for force buffer access
+ nbnxn_buffer_flags_t buffer_flags;
- int ndistc; /* Number of distance checks for flop counting */
+ //! Number of distance checks for flop counting
+ int ndistc;
- std::unique_ptr<t_nblist> nbl_fep; /* Temporary FEP list for load balancing */
+ //! Temporary FEP list for load balancing
+ std::unique_ptr<t_nblist> nbl_fep;
- nbnxn_cycle_t cycleCounter; /* Counter for thread-local cycles */
+ //! Counter for thread-local cycles
+ nbnxn_cycle_t cycleCounter;
- gmx_cache_protect_t cp1; /* Buffer to avoid cache polution */
+ //! Buffer to avoid cache polution
+ gmx_cache_protect_t cp1;
};
-/* Main pair-search struct, contains the grid(s), not the pair-list(s) */
+//! Main pair-search struct, contains the grid(s), not the pair-list(s) \internal
class PairSearch
{
public:
cycleCounting_.stop(enbsCCgrid);
}
- /* \brief Constructor
+ /*! \brief Constructor
*
- * \param[in] ePBC The periodic boundary conditions
- * \param[in] numDDCells The number of domain decomposition cells per dimension, without DD nullptr should be passed
- * \param[in] zones The domain decomposition zone setup, without DD nullptr should be passed
- * \param[in] haveFep Tells whether non-bonded interactions are perturbed
- * \param[in] maxNumThreads The maximum number of threads used in the search
+ * \param[in] pbcType The periodic boundary conditions
+ * \param[in] doTestParticleInsertion Whether test-particle insertion is active
+ * \param[in] numDDCells The number of domain decomposition cells per dimension, without DD nullptr should be passed
+ * \param[in] zones The domain decomposition zone setup, without DD nullptr should be passed
+ * \param[in] pairlistType The type of tte pair list
+ * \param[in] haveFep Tells whether non-bonded interactions are perturbed
+ * \param[in] maxNumThreads The maximum number of threads used in the search
+ * \param[in] pinningPolicy Sets the pinning policy for all buffers used on the GPU
*/
- PairSearch(int ePBC,
+ PairSearch(PbcType pbcType,
bool doTestParticleInsertion,
const ivec* numDDCells,
const gmx_domdec_zones_t* zones,
PairlistType pairlistType,
bool haveFep,
- int maxNumthreads,
+ int maxNumThreads,
gmx::PinningPolicy pinningPolicy);
//! Sets the order of the local atoms to the order grid atom ordering
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/gmxassert.h"
#include "clusterdistancekerneltype.h"
+#include "nbnxm_gpu.h"
+#include "nbnxm_simd.h"
#include "pairlistset.h"
#include "pairlistsets.h"
#include "kernels_reference/kernel_ref_prune.h"
switch (getClusterDistanceKernelType(params_.pairlistType, *nbat))
{
+#ifdef GMX_NBNXN_SIMD_4XN
case ClusterDistanceKernelType::CpuSimd_4xM:
nbnxn_kernel_prune_4xn(nbl, nbat, shift_vec, rlistInner);
break;
+#endif
+#ifdef GMX_NBNXN_SIMD_2XNN
case ClusterDistanceKernelType::CpuSimd_2xMM:
nbnxn_kernel_prune_2xnn(nbl, nbat, shift_vec, rlistInner);
break;
+#endif
case ClusterDistanceKernelType::CpuPlainC:
nbnxn_kernel_prune_ref(nbl, nbat, shift_vec, rlistInner);
break;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2014,2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2014,2015,2016,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
mock_helptopic.cpp)
gmx_add_unit_test(OnlineHelpUnitTests onlinehelp-test
- helpformat.cpp
- helpmanager.cpp
- helpwritercontext.cpp)
+ CPP_SOURCE_FILES
+ helpformat.cpp
+ helpmanager.cpp
+ helpwritercontext.cpp
+ )
target_link_libraries(onlinehelp-test PRIVATE onlinehelp-test-shared)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/abstractoption.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/gmxassert.h"
#include "ivaluestore.h"
//! \{
/*! \brief
- * Specifies an option that accepts enumerated string values and writes the
- * selected index into an `enum` variable.
- *
- * \tparam EnumType Type of the variable that receives the values
- * (can also be `int`).
- *
- * Examples:
- * \code
- enum MyEnum { eAtom, eRes, eMol };
- using gmx::EnumOption;
- const char * const allowed[] = { "atom", "residue", "molecule" };
- MyEnum value = eAtom; // default value
- options.addOption(EnumOption<MyEnum>("type").enumValue(allowed).store(&value));
- * \endcode
- *
- * storeCount() is not currently implemented for this option type, and
- * providing multiple default values through an array passed to store() does
- * not work consistently in all cases.
- * In the current implementation, the values of the enum type should correspond
- * to indices in the array passed to enumValue(), i.e., be consencutive
- * starting from zero. Only values corresponding to valid indices are accepted
- * as parameters to, e.g., defaultValue(). However, other values can be used
- * as the initial value of the variable (`value` in the above example), and
- * those will be preserved if the option is not set.
- *
- * Public methods in this class do not throw.
- *
- * \inpublicapi
- */
+* Specifies an option that accepts an EnumerationArray of string values and writes the
+* selected index into an `enum` variable.
+*
+* \tparam EnumType DataType of the variable that receives the values
+*
+* Examples:
+* \code
+ enum class MyEnum { Atom, Res, Mol, Count } : int;
+ EnumerationArray<MyEnum, const char *> myEnumNames = { "atom", "residue", "molecule" };
+ MyEnum value = MyEnum::Atom; // default value
+ options.addOption(EnumOption<MyEnum>("type").enumValue(myEnumNames).store(&value));
+* \endcode
+*
+* storeCount() is not currently implemented for this option type, and
+* providing multiple default values through an array passed to store() does
+* not work consistently in all cases.
+* In the current implementation, the values of the enum type should correspond
+* to indices in the array passed to enumValue(), i.e., be consecutive
+* starting from zero. Only values corresponding to valid indices are accepted
+* as parameters to, e.g., defaultValue(). However, other values can be used
+* as the initial value of the variable (`value` in the above example), and
+* those will be preserved if the option is not set.
+*
+* Public methods in this class do not throw.
+*
+* \inpublicapi
+*/
template<typename EnumType>
class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>>
{
{
}
+ /*! \brief
+ * Sets the option to only accept one of a fixed set of strings.
+ *
+
+ * \param[in] values Array of strings to accept.
+ *
+ * Also accepts prefixes of the strings; if a prefix matches more than
+ * one of the possible strings, the shortest one is used (in a tie, the
+ * first one is).
+ *
+ * The strings are copied once the option is created.
+ */
+ EnumOption& enumValue(const EnumerationArray<EnumType, const char*>& values)
+ {
+ GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
+ enumValues_ = values.data();
+ enumValuesCount_ = values.size();
+ return MyBase::me();
+ }
+
+private:
+ //! Helper function to convert default values for storage initialization.
+ static int convertToInt(const EnumType* defaultValue)
+ {
+ return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
+ }
+
+ //! Creates a EnumOptionStorage object.
+ AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
+ {
+ // TODO: Implement storeCount() if necessary.
+ return internal::createEnumOptionStorage(*this, enumValues_, enumValuesCount_,
+ convertToInt(MyBase::defaultValue()),
+ convertToInt(MyBase::defaultValueIfSet()),
+ std::make_unique<internal::EnumIndexStore<EnumType>>(
+ MyBase::store(), MyBase::storeVector()));
+ }
+
+ const char* const* enumValues_;
+ int enumValuesCount_;
+
+ /*! \brief
+ * Needed to initialize EnumOptionStorage from this class without
+ * otherwise unnecessary accessors.
+ */
+ friend class EnumOptionStorage;
+};
+
+/*! \brief
+* Specifies an option that accepts enumerated string values and writes the
+* selected index into an `enum` variable.
+*
+* \tparam EnumType Type of the variable that receives the values
+* (can also be `int`).
+*
+* Examples:
+* \code
+ enum MyEnum { eAtom, eRes, eMol };
+ using gmx::LegacyEnumOption;
+ const char * const allowed[] = { "atom", "residue", "molecule" };
+ MyEnum value = eAtom; // default value
+ options.addOption(LegacyEnumOption<MyEnum>("type").enumValue(allowed).store(&value));
+* \endcode
+*
+* Works exactly as EnumOption.
+*
+* This is legacy support for pargsToOptions and can be removed when it
+* is removed. No new uses of it should be made.
+*
+* Public methods in this class do not throw.
+*
+* \inpublicapi
+*/
+template<typename EnumType>
+class LegacyEnumOption : public OptionTemplate<EnumType, LegacyEnumOption<EnumType>>
+{
+public:
+ //! OptionInfo subclass corresponding to this option type.
+ typedef EnumOptionInfo InfoType;
+
+ // This needs to be duplicated from OptionTemplate because this class
+ // is a template.
+ //! Short-hand for the base class.
+ typedef OptionTemplate<EnumType, LegacyEnumOption<EnumType>> MyBase;
+
+ //! Initializes an option with the given name.
+ explicit LegacyEnumOption(const char* name) :
+ MyBase(name),
+ enumValues_(nullptr),
+ enumValuesCount_(0)
+ {
+ }
+
/*! \brief
* Sets the option to only accept one of a fixed set of strings.
*
* The strings are copied once the option is created.
*/
template<size_t count>
- EnumOption& enumValue(const char* const (&values)[count])
+ LegacyEnumOption& enumValue(const char* const (&values)[count])
{
GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
enumValues_ = values;
*
* \see enumValue()
*/
- EnumOption& enumValueFromNullTerminatedArray(const char* const* values)
+ LegacyEnumOption& enumValueFromNullTerminatedArray(const char* const* values)
{
GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
enumValues_ = values;
}
private:
- //! Helper function to convert default values for storate initialization.
+ //! Helper function to convert default values for storage initialization.
static int convertToInt(const EnumType* defaultValue)
{
return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
friend class EnumOptionStorage;
};
-//! Shorthand for an enumerated option that stores into an `int` variable.
-typedef EnumOption<int> EnumIntOption;
-
/*! \brief
* Wrapper class for accessing boolean option information.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return processedValue;
}
if (bAllowMissing)
- {
+ { // NOLINT bugprone-branch-clone
return value + option.defaultExtension();
}
else if (option.isLibraryFile())
{
- // TODO: Treat also library files here.
+ // TODO: Treat also library files here and remove the NOLINT.
return value + option.defaultExtension();
}
else
return completedName;
}
if (option.allowMissing())
- {
+ { // NOLINT bugprone-branch-clone
return realPrefix + option.defaultExtension();
}
- else if (option.isLibraryFile())
+ else if (option.isLibraryFile()) // NOLINT bugprone-branch-clone
{
- // TODO: Treat also library files here.
+ // TODO: Treat also library files here and remove the NOLINT
return realPrefix + option.defaultExtension();
}
else if (option.isSet())
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
store_->reserve(setValues_.size());
// For bool the loop variable isn't a reference (it's its special reference type)
// clang-format off
- CLANG_DIAGNOSTIC_IGNORE(-Wrange-loop-analysis)
+ CLANG_DIAGNOSTIC_IGNORE(-Wrange-loop-analysis);
// clang-format on
for (const auto& value : setValues_)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2014,2016, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2014,2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(OptionsUnitTests options-test
- abstractoptionstorage.cpp
- filenameoption.cpp
- filenameoptionmanager.cpp
- option.cpp
- optionsassigner.cpp
- repeatingsection.cpp
- timeunitmanager.cpp
- treesupport.cpp
- )
+ CPP_SOURCE_FILES
+ abstractoptionstorage.cpp
+ filenameoption.cpp
+ filenameoptionmanager.cpp
+ option.cpp
+ optionsassigner.cpp
+ repeatingsection.cpp
+ timeunitmanager.cpp
+ treesupport.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2017, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
//! Enum type for EnumOption tests.
-enum TestEnum
+enum class TestEnum : int
{
- etestNone,
- etestTest,
- etestValue,
- etestNR
+ None,
+ Test,
+ Value,
+ Count
};
+//! Set of allowed values for enum option tests.
+const gmx::EnumerationArray<TestEnum, const char*> c_testEnumNames = { { "none", "test", "value" } };
TEST(OptionsAssignerEnumTest, StoresSingleValue)
{
gmx::Options options;
- TestEnum value = etestNone;
+ TestEnum value = TestEnum::None;
using gmx::EnumOption;
- ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
- EXPECT_EQ(etestNone, value);
+ ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+ EXPECT_EQ(TestEnum::None, value);
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(etestTest, value);
+ EXPECT_EQ(TestEnum::Test, value);
}
TEST(OptionsAssignerEnumTest, StoresVectorValues)
std::vector<TestEnum> values;
using gmx::EnumOption;
ASSERT_NO_THROW(options.addOption(
- EnumOption<TestEnum>("p").storeVector(&values).multiValue().enumValue(c_allowed)));
+ EnumOption<TestEnum>("p").storeVector(&values).multiValue().enumValue(c_testEnumNames)));
EXPECT_TRUE(values.empty());
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(options.finish());
ASSERT_EQ(2U, values.size());
- EXPECT_EQ(etestTest, values[0]);
- EXPECT_EQ(etestValue, values[1]);
+ EXPECT_EQ(TestEnum::Test, values[0]);
+ EXPECT_EQ(TestEnum::Value, values[1]);
}
TEST(OptionsAssignerEnumTest, HandlesInitialValueOutOfRange)
{
gmx::Options options;
- TestEnum value = etestNR;
+ TestEnum value = TestEnum::Count;
using gmx::EnumOption;
- ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
- EXPECT_EQ(etestNR, value);
+ ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+ EXPECT_EQ(TestEnum::Count, value);
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(etestNR, value);
+ EXPECT_EQ(TestEnum::Count, value);
}
TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValue)
{
gmx::Options options;
- TestEnum value = etestNone;
+ TestEnum value = TestEnum::None;
using gmx::EnumOption;
ASSERT_NO_THROW(options.addOption(
- EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed).defaultValue(etestTest)));
- EXPECT_EQ(etestTest, value);
+ EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames).defaultValue(TestEnum::Test)));
+ EXPECT_EQ(TestEnum::Test, value);
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(etestTest, value);
+ EXPECT_EQ(TestEnum::Test, value);
}
TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVariable)
{
gmx::Options options;
- TestEnum value = etestTest;
+ TestEnum value = TestEnum::Test;
using gmx::EnumOption;
- ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_allowed)));
- EXPECT_EQ(etestTest, value);
+ ASSERT_NO_THROW(options.addOption(EnumOption<TestEnum>("p").store(&value).enumValue(c_testEnumNames)));
+ EXPECT_EQ(TestEnum::Test, value);
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(etestTest, value);
+ EXPECT_EQ(TestEnum::Test, value);
}
TEST(OptionsAssignerEnumTest, HandlesEnumDefaultValueFromVector)
{
gmx::Options options;
std::vector<TestEnum> value;
- value.push_back(etestNone);
- value.push_back(etestTest);
+ value.push_back(TestEnum::None);
+ value.push_back(TestEnum::Test);
using gmx::EnumOption;
ASSERT_NO_THROW(options.addOption(
- EnumOption<TestEnum>("p").storeVector(&value).valueCount(2).enumValue(c_allowed)));
+ EnumOption<TestEnum>("p").storeVector(&value).valueCount(2).enumValue(c_testEnumNames)));
ASSERT_EQ(2U, value.size());
- EXPECT_EQ(etestNone, value[0]);
- EXPECT_EQ(etestTest, value[1]);
+ EXPECT_EQ(TestEnum::None, value[0]);
+ EXPECT_EQ(TestEnum::Test, value[1]);
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
EXPECT_NO_THROW(options.finish());
ASSERT_EQ(2U, value.size());
- EXPECT_EQ(etestNone, value[0]);
- EXPECT_EQ(etestTest, value[1]);
+ EXPECT_EQ(TestEnum::None, value[0]);
+ EXPECT_EQ(TestEnum::Test, value[1]);
}
} // namespace
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
TEST(TimeUnitManagerTest, BasicOperations)
{
gmx::TimeUnitManager manager;
- EXPECT_EQ(gmx::TimeUnit_ps, manager.timeUnit());
+ EXPECT_EQ(gmx::TimeUnit::Picoseconds, manager.timeUnit());
EXPECT_DOUBLE_EQ(1.0, manager.timeScaleFactor());
- manager.setTimeUnit(gmx::TimeUnit_ns);
- EXPECT_EQ(gmx::TimeUnit_ns, manager.timeUnit());
+ manager.setTimeUnit(gmx::TimeUnit::Nanoseconds);
+ EXPECT_EQ(gmx::TimeUnit::Nanoseconds, manager.timeUnit());
EXPECT_DOUBLE_EQ(1e3, manager.timeScaleFactor());
EXPECT_DOUBLE_EQ(1e-3, manager.inverseTimeScaleFactor());
}
EXPECT_NO_THROW_GMX(assigner.finish());
EXPECT_DOUBLE_EQ(1.5, value);
- behavior.setTimeUnit(gmx::TimeUnit_ns);
+ behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1500, value);
EXPECT_NO_THROW_GMX(options.finish());
- behavior.setTimeUnit(gmx::TimeUnit_us);
+ behavior.setTimeUnit(gmx::TimeUnit::Microseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1500000, value);
- behavior.setTimeUnit(gmx::TimeUnit_fs);
+ behavior.setTimeUnit(gmx::TimeUnit::Femtoseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(0.0015, value);
- behavior.setTimeUnit(gmx::TimeUnit_ps);
+ behavior.setTimeUnit(gmx::TimeUnit::Picoseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1.5, value);
}
EXPECT_NO_THROW_GMX(options.finish());
EXPECT_DOUBLE_EQ(2.5, value2);
- behavior.setTimeUnit(gmx::TimeUnit_ns);
+ behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1.5, value);
EXPECT_DOUBLE_EQ(2.5, value2);
EXPECT_NO_THROW_GMX(options.finish());
EXPECT_DOUBLE_EQ(1.5, value);
- behavior.setTimeUnit(gmx::TimeUnit_ns);
+ behavior.setTimeUnit(gmx::TimeUnit::Nanoseconds);
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1500, value);
}
EXPECT_NO_THROW_GMX(assigner.finish());
EXPECT_DOUBLE_EQ(1.5, value);
- EXPECT_EQ(gmx::TimeUnit_ns, behavior.timeUnit());
+ EXPECT_EQ(gmx::TimeUnit::Nanoseconds, behavior.timeUnit());
behavior.optionsFinishing(&options);
EXPECT_DOUBLE_EQ(1500, value);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::KeyValueTreeBuilder builder_;
private:
- std::vector<char> serializeTree(const gmx::KeyValueTreeObject& tree)
+ static std::vector<char> serializeTree(const gmx::KeyValueTreeObject& tree)
{
gmx::InMemorySerializer serializer;
gmx::serializeKeyValueTree(tree, &serializer);
return serializer.finishAndGetBuffer();
}
- std::string formatBuffer(const std::vector<char>& buffer)
+ static std::string formatBuffer(const std::vector<char>& buffer)
{
return gmx::formatAndJoin(buffer, " ", [](char c) {
return gmx::formatString("%02x", static_cast<unsigned char>(c));
runTest();
}
-TEST_F(TreeValueSupportTest, SupportsEnumIntOption)
-{
- const char* const values[] = { "foo", "bar" };
- options_.addOption(gmx::EnumIntOption("a").enumValue(values).defaultValue(0));
- runTest();
-}
-
//! Enum for testing EnumOption.
-enum class TestEnum
+enum class TestEnum : int
{
Foo,
Bar
TEST_F(TreeValueSupportTest, SupportsEnumOption)
{
- const char* const values[] = { "foo", "bar" };
- options_.addOption(gmx::EnumOption<TestEnum>("a").enumValue(values).defaultValue(TestEnum::Foo));
+ enum class TestEnum : int
+ {
+ Foo,
+ Bar,
+ Count
+ };
+ const gmx::EnumerationArray<TestEnum, const char*> testEnumNames = { { "foo", "bar" } };
+ options_.addOption(gmx::EnumOption<TestEnum>("a").enumValue(testEnumNames).defaultValue(TestEnum::Foo));
runTest();
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/options/options.h"
#include "gromacs/options/optionsvisitor.h"
#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
+namespace gmx
+{
+
namespace
{
*
* These must correspond to the TimeUnit enum in the header!
*/
-const char* const g_timeUnits[] = { "fs", "ps", "ns", "us", "ms", "s" };
+const EnumerationArray<TimeUnit, const char*> c_timeUnitNames = { { "fs", "ps", "ns", "us", "ms",
+ "s" } };
/*! \brief
* Scaling factors from each time unit to internal units (=picoseconds).
*
* These must correspond to the TimeUnit enum in the header!
*/
-const double g_timeScaleFactors[] = { 1e-3, 1, 1e3, 1e6, 1e9, 1e12 };
+const EnumerationArray<TimeUnit, double> c_timeUnitScaleFactors = { { 1e-3, 1, 1e3, 1e6, 1e9, 1e12 } };
} // namespace
-namespace gmx
-{
-
-TimeUnitManager::TimeUnitManager() : timeUnit_(TimeUnit_Default) {}
+TimeUnitManager::TimeUnitManager() : timeUnit_(TimeUnit::Default) {}
-TimeUnitManager::TimeUnitManager(TimeUnit unit) : timeUnit_(unit)
-{
- GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
-}
+TimeUnitManager::TimeUnitManager(TimeUnit unit) : timeUnit_(unit) {}
void TimeUnitManager::setTimeUnit(TimeUnit unit)
{
- GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
timeUnit_ = unit;
}
const char* TimeUnitManager::timeUnitAsString() const
{
- GMX_RELEASE_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s, "Invalid time unit");
- return g_timeUnits[timeUnit_];
+ return c_timeUnitNames[timeUnit_];
}
double TimeUnitManager::timeScaleFactor() const
{
- GMX_RELEASE_ASSERT(timeUnit_ >= 0
- && static_cast<size_t>(timeUnit_)
- < sizeof(g_timeScaleFactors) / sizeof(g_timeScaleFactors[0]),
- "Time unit index has become out-of-range");
- return g_timeScaleFactors[timeUnit_];
+ return c_timeUnitScaleFactors[timeUnit_];
}
double TimeUnitManager::inverseTimeScaleFactor() const
* TimeUnitBehavior
*/
-TimeUnitBehavior::TimeUnitBehavior() : timeUnit_(TimeUnit_Default), timeUnitStore_(nullptr) {}
+TimeUnitBehavior::TimeUnitBehavior() : timeUnit_(TimeUnit::Default), timeUnitStore_(nullptr) {}
void TimeUnitBehavior::setTimeUnit(TimeUnit unit)
{
- GMX_RELEASE_ASSERT(unit >= 0 && unit <= TimeUnit_s, "Invalid time unit");
timeUnit_ = unit;
if (timeUnitStore_ != nullptr)
{
const char* const value = std::getenv("GMXTIMEUNIT");
if (value != nullptr)
{
- ArrayRef<const char* const> timeUnits(g_timeUnits);
- ArrayRef<const char* const>::const_iterator i =
- std::find(timeUnits.begin(), timeUnits.end(), std::string(value));
- if (i == timeUnits.end())
+ TimeUnit result = TimeUnit::Count;
+ for (TimeUnit t : keysOf(c_timeUnitNames))
+ {
+ if (std::strcmp(value, c_timeUnitNames[t]) == 0)
+ {
+ result = t;
+ break;
+ }
+ }
+ if (result == TimeUnit::Count)
{
std::string message = formatString(
"Time unit provided with environment variable GMXTIMEUNIT=%s "
"is not recognized as a valid time unit.\n"
"Possible values are: %s",
- value, joinStrings(timeUnits, ", ").c_str());
+ value, joinStrings(c_timeUnitNames, ", ").c_str());
GMX_THROW(InvalidInputError(message));
}
- setTimeUnit(static_cast<TimeUnit>(i - timeUnits.begin()));
+ setTimeUnit(result);
}
}
void TimeUnitBehavior::addTimeUnitOption(IOptionsContainer* options, const char* name)
{
options->addOption(
- EnumOption<TimeUnit>(name).enumValue(g_timeUnits).store(&timeUnit_).description("Unit for time values"));
+ EnumOption<TimeUnit>(name).enumValue(c_timeUnitNames).store(&timeUnit_).description("Unit for time values"));
}
namespace
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_OPTIONS_TIMEUNITMANAGER_H
#define GMX_OPTIONS_TIMEUNITMANAGER_H
+#include "gromacs/fileio/oenv.h"
#include "gromacs/options/ioptionsbehavior.h"
#include "gromacs/utility/classhelpers.h"
-#include "gromacs/utility/gmxassert.h"
namespace gmx
{
class IOptionsContainer;
class Options;
-/*! \brief
- * Time values for TimeUnitManager.
- *
- * \if internal
- * Currently, this should match with the time_unit_t enum defined in oenv.h
- * except that there is no NULL first item in this enum.
- * \endif
- *
- * \inpublicapi
- */
-enum TimeUnit
-{
- TimeUnit_fs, //!< Femtoseconds.
- TimeUnit_ps, //!< Picoseconds.
- TimeUnit_ns, //!< Nanoseconds.
- TimeUnit_us, //!< Microseconds.
- TimeUnit_ms, //!< Milliseconds.
- TimeUnit_s, //!< Seconds.
- TimeUnit_Default = TimeUnit_ps //!< Default time unit.
-};
-
/*! \brief
* Provides common functionality for time unit conversions.
*
explicit TimeUnitManager(TimeUnit unit);
//! Returns the currently selected time unit.
- TimeUnit timeUnit() const
- {
- GMX_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s,
- "Time unit index has become out-of-range");
- return timeUnit_;
- }
+ TimeUnit timeUnit() const { return timeUnit_; }
//! Set a new time unit for the manager.
void setTimeUnit(TimeUnit unit);
TimeUnitBehavior();
//! Returns the current time unit.
- TimeUnit timeUnit() const
- {
- GMX_ASSERT(timeUnit_ >= 0 && timeUnit_ <= TimeUnit_s,
- "Time unit index has become out-of-range");
- return static_cast<TimeUnit>(timeUnit_);
- }
+ TimeUnit timeUnit() const { return timeUnit_; }
//! Sets the time unit.
void setTimeUnit(TimeUnit unit);
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
file(GLOB PBCUTIL_SOURCES *.cpp)
set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${PBCUTIL_SOURCES} PARENT_SCOPE)
+if(GMX_INSTALL_LEGACY_API)
+ install(FILES
+ pbc.h
+ DESTINATION include/gromacs/pbcutil)
+endif()
+
if (BUILD_TESTING)
add_subdirectory(tests)
endif()
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/ifunc.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/strconvert.h"
#include "gromacs/utility/stringutil.h"
*
************************************************************/
-static void add_gbond(t_graph* g, int a0, int a1)
+using gmx::ArrayRef;
+using gmx::IVec;
+
+// Class for generating the edges of the graph
+class EdgesGenerator
{
- int i;
- int inda0, inda1;
- gmx_bool bFound;
-
- inda0 = a0 - g->at_start;
- inda1 = a1 - g->at_start;
- bFound = FALSE;
- /* Search for a direct edge between a0 and a1.
- * All egdes are bidirectional, so we only need to search one way.
- */
- for (i = 0; (i < g->nedge[inda0] && !bFound); i++)
- {
- bFound = (g->edge[inda0][i] == a1);
- }
+public:
+ EdgesGenerator(const int endAtom) : edges_(endAtom) {}
+
+ // Adds an edge, bi-directional
+ void addEdge(int a0, int a1);
+
+ // Returns the edges
+ const std::vector<std::vector<int>>& edges() const { return edges_; }
+
+private:
+ // The edges stored as list (for each atom starting at \p startAtom_) of lists of atoms
+ std::vector<std::vector<int>> edges_;
+};
- if (!bFound)
+void EdgesGenerator::addEdge(const int a0, const int a1)
+{
+ const auto& edges = edges_[a0];
+ if (std::find(edges.begin(), edges.end(), a1) == edges.end())
{
- g->edge[inda0][g->nedge[inda0]++] = a1;
- g->edge[inda1][g->nedge[inda1]++] = a0;
+ edges_[a0].push_back(a1);
+ edges_[a1].push_back(a0);
}
}
* edges are only added when atoms have a different part index.
*/
template<typename T>
-static bool mk_igraph(t_graph* g, int ftype, const T& il, int at_start, int at_end, const int* part)
+static bool mk_igraph(EdgesGenerator* edgesG, int ftype, const T& il, int at_end, ArrayRef<const int> part)
{
int i, j, np;
int end;
{
np = interaction_function[ftype].nratoms;
- if (np > 1 && il.iatoms[i + 1] >= at_start && il.iatoms[i + 1] < at_end)
+ if (np > 1 && il.iatoms[i + 1] < at_end)
{
if (il.iatoms[i + np] >= at_end)
{
if (ftype == F_SETTLE)
{
/* Bond all the atoms in the settle */
- add_gbond(g, il.iatoms[i + 1], il.iatoms[i + 2]);
- add_gbond(g, il.iatoms[i + 1], il.iatoms[i + 3]);
+ edgesG->addEdge(il.iatoms[i + 1], il.iatoms[i + 2]);
+ edgesG->addEdge(il.iatoms[i + 1], il.iatoms[i + 3]);
addedEdge = true;
}
- else if (part == nullptr)
+ else if (part.empty())
{
/* Simply add this bond */
for (j = 1; j < np; j++)
{
- add_gbond(g, il.iatoms[i + j], il.iatoms[i + j + 1]);
+ edgesG->addEdge(il.iatoms[i + j], il.iatoms[i + j + 1]);
}
addedEdge = true;
}
{
if (part[il.iatoms[i + j]] != part[il.iatoms[i + j + 1]])
{
- add_gbond(g, il.iatoms[i + j], il.iatoms[i + j + 1]);
+ edgesG->addEdge(il.iatoms[i + j], il.iatoms[i + j + 1]);
addedEdge = true;
}
}
if ((g) == NULL) \
g_error(__LINE__, __FILE__)
-void p_graph(FILE* log, const char* title, t_graph* g)
+void p_graph(FILE* log, const char* title, const t_graph* g)
{
- int i, j;
+ int i;
const char* cc[egcolNR] = { "W", "G", "B" };
GCHECK(g);
fprintf(log, "graph: %s\n", title);
- fprintf(log, "nnodes: %d\n", g->nnodes);
- fprintf(log, "nbound: %d\n", g->nbound);
- fprintf(log, "start: %d\n", g->at_start);
- fprintf(log, "end: %d\n", g->at_end);
+ fprintf(log, "nnodes: %d\n", g->numNodes());
+ fprintf(log, "nbound: %d\n", g->numConnectedAtoms);
+ fprintf(log, "start: %d\n", g->edgeAtomBegin);
+ fprintf(log, "end: %d\n", g->edgeAtomEnd);
fprintf(log, " atom shiftx shifty shiftz C nedg e1 e2 etc.\n");
- for (i = 0; (i < g->nnodes); i++)
+ for (i = 0; i < int(g->edges.size()); i++)
{
- if (g->nedge[i] > 0)
+ if (!g->edges[i].empty())
{
- fprintf(log, "%5d%7d%7d%7d %1s%5d", g->at_start + i + 1, g->ishift[g->at_start + i][XX],
- g->ishift[g->at_start + i][YY], g->ishift[g->at_start + i][ZZ],
- (g->negc > 0) ? cc[g->egc[i]] : " ", g->nedge[i]);
- for (j = 0; (j < g->nedge[i]); j++)
+ fprintf(log, "%5d%7d%7d%7d %1s%5zu", g->edgeAtomBegin + i + 1,
+ g->ishift[g->edgeAtomBegin + i][XX], g->ishift[g->edgeAtomBegin + i][YY],
+ g->ishift[g->edgeAtomBegin + i][ZZ],
+ (!g->edgeColor.empty()) ? cc[g->edgeColor[i]] : " ", g->edges[i].size());
+ for (const int edge : g->edges[i])
{
- fprintf(log, " %5d", g->edge[i][j] + 1);
+ fprintf(log, " %5d", edge + 1);
}
fprintf(log, "\n");
}
fflush(log);
}
-template<typename T>
-static void calc_1se(t_graph* g, int ftype, const T& il, int nbond[], int at_start, int at_end)
+/* Converts the vector of vector of edges to ListOfLists
+ * and removes leading and trailing uncoupled atoms
+ */
+static gmx::ListOfLists<int> convertGraph(FILE* fplog,
+ const EdgesGenerator& edgesG,
+ int* firstConnectedAtom,
+ int* numConnectedAtoms)
{
- int k, nratoms, end, j;
+ gmx::ListOfLists<int> edgesLists;
- end = il.size();
-
- for (j = 0; (j < end); j += nratoms + 1)
+ *firstConnectedAtom = edgesG.edges().size();
+ *numConnectedAtoms = 0;
+ int numEmptyEntriesSkipped = 0;
+ int max_nedge = 0;
+ for (const auto& edges : edgesG.edges())
{
- nratoms = interaction_function[ftype].nratoms;
-
- if (ftype == F_SETTLE)
+ if (edges.empty())
{
- const int iaa = il.iatoms[j + 1];
- if (iaa >= at_start && iaa < at_end)
- {
- nbond[iaa] += 2;
- nbond[il.iatoms[j + 2]] += 1;
- nbond[il.iatoms[j + 3]] += 1;
- g->at_start = std::min(g->at_start, iaa);
- g->at_end = std::max(g->at_end, iaa + 2 + 1);
- }
+ numEmptyEntriesSkipped++;
}
else
{
- for (k = 1; (k <= nratoms); k++)
+ if (edgesLists.empty())
+ {
+ /* We ignore empty entries before the first connected entry */
+ *firstConnectedAtom = numEmptyEntriesSkipped;
+ }
+ else
{
- const int iaa = il.iatoms[j + k];
- if (iaa >= at_start && iaa < at_end)
+ /* Push any empty entries we skipped */
+ for (int i = 0; i < numEmptyEntriesSkipped; i++)
{
- g->at_start = std::min(g->at_start, iaa);
- g->at_end = std::max(g->at_end, iaa + 1);
- /* When making the graph we (might) link all atoms in an interaction
- * sequentially. Therefore the end atoms add 1 to the count,
- * the middle atoms 2.
- */
- if (k == 1 || k == nratoms)
- {
- nbond[iaa] += 1;
- }
- else
- {
- nbond[iaa] += 2;
- }
+ edgesLists.pushBack({});
}
}
- }
- }
-}
+ numEmptyEntriesSkipped = 0;
-template<typename T>
-static int calc_start_end(FILE* fplog, t_graph* g, const T il[], int at_start, int at_end, int nbond[])
-{
- int i, nnb, nbtot;
+ edgesLists.pushBack(edges);
- g->at_start = at_end;
- g->at_end = 0;
+ (*numConnectedAtoms)++;
- /* First add all the real bonds: they should determine the molecular
- * graph.
- */
- for (i = 0; (i < F_NRE); i++)
- {
- if (interaction_function[i].flags & IF_CHEMBOND)
- {
- calc_1se(g, i, il[i], nbond, at_start, at_end);
- }
- }
- /* Then add all the other interactions in fixed lists, but first
- * check to see what's there already.
- */
- for (i = 0; (i < F_NRE); i++)
- {
- if (!(interaction_function[i].flags & IF_CHEMBOND))
- {
- calc_1se(g, i, il[i], nbond, at_start, at_end);
+ max_nedge = std::max(max_nedge, int(gmx::ssize(edges)));
}
}
- nnb = 0;
- nbtot = 0;
- for (i = g->at_start; (i < g->at_end); i++)
- {
- nbtot += nbond[i];
- nnb = std::max(nnb, nbond[i]);
- }
- if (fplog)
- {
- fprintf(fplog, "Max number of connections per atom is %d\n", nnb);
- fprintf(fplog, "Total number of connections is %d\n", nbtot);
- }
- return nbtot;
-}
-
-
-static void compact_graph(FILE* fplog, t_graph* g)
-{
- int i, j, n, max_nedge;
-
- max_nedge = 0;
- n = 0;
- for (i = 0; i < g->nnodes; i++)
- {
- for (j = 0; j < g->nedge[i]; j++)
- {
- g->edge[0][n++] = g->edge[i][j];
- }
- max_nedge = std::max(max_nedge, g->nedge[i]);
- }
- srenew(g->edge[0], n);
- /* set pointers after srenew because edge[0] might move */
- for (i = 1; i < g->nnodes; i++)
- {
- g->edge[i] = g->edge[i - 1] + g->nedge[i - 1];
- }
-
if (fplog)
{
fprintf(fplog, "Max number of graph edges per atom is %d\n", max_nedge);
- fprintf(fplog, "Total number of graph edges is %d\n", n);
+ fprintf(fplog, "Total number of graph edges is %d\n", edgesLists.numElements());
}
+
+ return edgesLists;
}
-static gmx_bool determine_graph_parts(t_graph* g, int* part)
+static gmx_bool determine_graph_parts(const EdgesGenerator& edgesG, ArrayRef<int> partNr)
{
- int i, e;
- int nchanged;
- int at_i, *at_i2;
- gmx_bool bMultiPart;
-
/* Initialize the part array with all entries different */
- for (at_i = g->at_start; at_i < g->at_end; at_i++)
+ const int endAtom = edgesG.edges().size();
+ for (int at_i = 0; at_i < endAtom; at_i++)
{
- part[at_i] = at_i;
+ partNr[at_i] = at_i;
}
/* Loop over the graph until the part array is fixed */
+ bool haveMultipleParts = false;
+ int numAtomsChanged = 0;
do
{
- bMultiPart = FALSE;
- nchanged = 0;
- for (i = 0; (i < g->nnodes); i++)
+ haveMultipleParts = false;
+ numAtomsChanged = 0;
+ for (gmx::index at_i = 0; at_i < gmx::ssize(edgesG.edges()); at_i++)
{
- at_i = g->at_start + i;
- at_i2 = g->edge[i];
- for (e = 0; e < g->nedge[i]; e++)
+ for (const int at_i2 : edgesG.edges()[at_i])
{
/* Set part for both nodes to the minimum */
- if (part[at_i2[e]] > part[at_i])
+ if (partNr[at_i2] > partNr[at_i])
{
- part[at_i2[e]] = part[at_i];
- nchanged++;
+ partNr[at_i2] = partNr[at_i];
+ numAtomsChanged++;
}
- else if (part[at_i2[e]] < part[at_i])
+ else if (partNr[at_i2] < partNr[at_i])
{
- part[at_i] = part[at_i2[e]];
- nchanged++;
+ partNr[at_i] = partNr[at_i2];
+ numAtomsChanged++;
}
}
- if (part[at_i] != part[g->at_start])
+ if (partNr[at_i] != partNr[0])
{
- bMultiPart = TRUE;
+ haveMultipleParts = true;
}
}
if (debug)
{
- fprintf(debug, "graph part[] nchanged=%d, bMultiPart=%s\n", nchanged,
- gmx::boolToString(bMultiPart));
+ fprintf(debug, "graph partNr[] numAtomsChanged=%d, bMultiPart=%s\n", numAtomsChanged,
+ gmx::boolToString(haveMultipleParts));
}
- } while (nchanged > 0);
+ } while (numAtomsChanged > 0);
- return bMultiPart;
+ return haveMultipleParts;
}
template<typename T>
-static void mk_graph_ilist(FILE* fplog,
- const T* ilist,
- int at_start,
- int at_end,
- gmx_bool bShakeOnly,
- gmx_bool bSettle,
- t_graph* g)
+static t_graph mk_graph_ilist(FILE* fplog, const T* ilist, int at_end, gmx_bool bShakeOnly, gmx_bool bSettle)
{
- int* nbond;
- int i, nbtot;
- gmx_bool bMultiPart;
+ EdgesGenerator edgesG(at_end);
- /* The naming is somewhat confusing, but we need g->at0 and g->at1
- * for shifthing coordinates to a new array (not in place) when
- * some atoms are not connected by the graph, which runs from
- * g->at_start (>= g->at0) to g->at_end (<= g->at1).
- */
- g->at0 = at_start;
- g->at1 = at_end;
- g->parts = t_graph::BondedParts::Single;
+ t_graph::BondedParts parts = t_graph::BondedParts::Single;
- snew(nbond, at_end);
- nbtot = calc_start_end(fplog, g, ilist, at_start, at_end, nbond);
-
- if (g->at_start >= g->at_end)
- {
- g->at_start = at_start;
- g->at_end = at_end;
- g->nnodes = 0;
- g->nbound = 0;
- }
- else
+ if (at_end > 0)
{
- g->nnodes = g->at_end - g->at_start;
- snew(g->nedge, g->nnodes);
- snew(g->edge, g->nnodes);
- /* Allocate a single array and set pointers into it */
- snew(g->edge[0], nbtot);
- for (i = 1; (i < g->nnodes); i++)
- {
- g->edge[i] = g->edge[i - 1] + nbond[g->at_start + i - 1];
- }
-
if (!bShakeOnly)
{
/* First add all the real bonds: they should determine the molecular
* graph.
*/
- for (i = 0; (i < F_NRE); i++)
+ for (int i = 0; (i < F_NRE); i++)
{
if (interaction_function[i].flags & IF_CHEMBOND)
{
- mk_igraph(g, i, ilist[i], at_start, at_end, nullptr);
+ mk_igraph(&edgesG, i, ilist[i], at_end, {});
}
}
/* Determine of which separated parts the IF_CHEMBOND graph consists.
- * Store the parts in the nbond array.
+ * Store the part numbers in the partNr array.
*/
- bMultiPart = determine_graph_parts(g, nbond);
+ std::vector<int> partNr(at_end);
+ const bool bMultiPart = determine_graph_parts(edgesG, partNr);
if (bMultiPart)
{
* that are not connected through IF_CHEMBOND interactions.
*/
bool addedEdge = false;
- for (i = 0; (i < F_NRE); i++)
+ for (int i = 0; (i < F_NRE); i++)
{
if (!(interaction_function[i].flags & IF_CHEMBOND))
{
- bool addedEdgeForType = mk_igraph(g, i, ilist[i], at_start, at_end, nbond);
+ bool addedEdgeForType = mk_igraph(&edgesG, i, ilist[i], at_end, partNr);
addedEdge = (addedEdge || addedEdgeForType);
}
}
if (addedEdge)
{
- g->parts = t_graph::BondedParts::MultipleConnected;
+ parts = t_graph::BondedParts::MultipleConnected;
}
else
{
- g->parts = t_graph::BondedParts::MultipleDisconnected;
+ parts = t_graph::BondedParts::MultipleDisconnected;
}
}
-
- /* Removed all the unused space from the edge array */
- compact_graph(fplog, g);
}
else
{
/* This is a special thing used in splitter.c to generate shake-blocks */
- mk_igraph(g, F_CONSTR, ilist[F_CONSTR], at_start, at_end, nullptr);
+ mk_igraph(&edgesG, F_CONSTR, ilist[F_CONSTR], at_end, {});
if (bSettle)
{
- mk_igraph(g, F_SETTLE, ilist[F_SETTLE], at_start, at_end, nullptr);
- }
- }
- g->nbound = 0;
- for (i = 0; (i < g->nnodes); i++)
- {
- if (g->nedge[i] > 0)
- {
- g->nbound++;
+ mk_igraph(&edgesG, F_SETTLE, ilist[F_SETTLE], at_end, {});
}
}
}
- g->negc = 0;
- g->egc = nullptr;
+ t_graph graph;
+ /* The naming is somewhat confusing, but we need g->shiftAtomEnd
+ * for shifthing coordinates to a new array (not in place) when
+ * some atoms are not connected by the graph, which runs from
+ * g->edgeAtomBegin (>= 0) to g->edgeAtomEnd (<= g->shiftAtomEnd).
+ */
+ graph.shiftAtomEnd = at_end;
+ graph.edgeAtomBegin = 0;
+ graph.edgeAtomEnd = at_end;
+ graph.parts = parts;
+ if (at_end > 0)
+ {
+ /* Convert the vector of vector of edges to ListOfLists */
+ graph.edges = convertGraph(fplog, edgesG, &graph.edgeAtomBegin, &graph.numConnectedAtoms);
- sfree(nbond);
+ graph.edgeAtomEnd = graph.edgeAtomBegin + graph.edges.ssize();
+ }
- snew(g->ishift, g->at1);
+ graph.edgeColor.resize(graph.edges.size());
+ graph.ishift.resize(graph.shiftAtomEnd);
if (gmx_debug_at)
{
- p_graph(debug, "graph", g);
+ p_graph(debug, "graph", &graph);
}
+
+ return graph;
+}
+
+t_graph mk_graph_moltype(const gmx_moltype_t& moltype)
+{
+ return mk_graph_ilist(nullptr, moltype.ilist.data(), moltype.atoms.nr, FALSE, FALSE);
}
-void mk_graph_moltype(const gmx_moltype_t& moltype, t_graph* g)
+t_graph mk_graph(const InteractionDefinitions& idef, const int numAtoms)
{
- mk_graph_ilist(nullptr, moltype.ilist.data(), 0, moltype.atoms.nr, FALSE, FALSE, g);
+ return mk_graph_ilist(nullptr, idef.il.data(), numAtoms, false, false);
}
-t_graph* mk_graph(FILE* fplog, const t_idef* idef, int at_start, int at_end, gmx_bool bShakeOnly, gmx_bool bSettle)
+t_graph* mk_graph(FILE* fplog, const InteractionDefinitions& idef, int at_end, gmx_bool bShakeOnly, gmx_bool bSettle)
{
- t_graph* g;
+ t_graph* g = new (t_graph);
- snew(g, 1);
+ *g = mk_graph_ilist(fplog, idef.il.data(), at_end, bShakeOnly, bSettle);
- mk_graph_ilist(fplog, idef->il, at_start, at_end, bShakeOnly, bSettle, g);
+ return g;
+}
+
+t_graph* mk_graph(FILE* fplog, const t_idef* idef, int at_end, gmx_bool bShakeOnly, gmx_bool bSettle)
+{
+ t_graph* g = new (t_graph);
+
+ *g = mk_graph_ilist(fplog, idef->il, at_end, bShakeOnly, bSettle);
return g;
}
void done_graph(t_graph* g)
{
- GCHECK(g);
- if (g->nnodes > 0)
- {
- sfree(g->nedge);
- sfree(g->edge[0]);
- sfree(g->edge);
- sfree(g->egc);
- }
- sfree(g->ishift);
+ delete g;
}
/************************************************************
}
}
-static int mk_grey(egCol egc[], t_graph* g, int* AtomI, int npbcdim, const matrix box, const rvec x[], int* nerror)
+static int mk_grey(ArrayRef<egCol> edgeColor,
+ t_graph* g,
+ int* AtomI,
+ int npbcdim,
+ const matrix box,
+ const rvec x[],
+ int* nerror)
{
- int m, j, ng, ai, aj, g0;
+ int m, ng, ai, g0;
rvec dx, hbox;
gmx_bool bTriclinic;
ivec is_aj;
}
bTriclinic = TRICLINIC(box);
- g0 = g->at_start;
+ g0 = g->edgeAtomBegin;
ng = 0;
ai = g0 + *AtomI;
/* Loop over all the bonds */
- for (j = 0; (j < g->nedge[ai - g0]); j++)
+ for (const int aj : g->edges[ai - g0])
{
- aj = g->edge[ai - g0][j];
/* If there is a white one, make it grey and set pbc */
- if (g->bScrewPBC)
+ if (g->useScrewPbc)
{
mk_1shift_screw(box, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
}
mk_1shift(npbcdim, hbox, x[ai], x[aj], g->ishift[ai], is_aj);
}
- if (egc[aj - g0] == egcolWhite)
+ if (edgeColor[aj - g0] == egcolWhite)
{
if (aj - g0 < *AtomI)
{
*AtomI = aj - g0;
}
- egc[aj - g0] = egcolGrey;
+ edgeColor[aj - g0] = egcolGrey;
copy_ivec(is_aj, g->ishift[aj]);
{
if (gmx_debug_at)
{
- set_pbc(&pbc, -1, box);
+ set_pbc(&pbc, PbcType::Unset, box);
pbc_dx(&pbc, x[ai], x[aj], dx);
fprintf(debug,
"mk_grey: shifts for atom %d due to atom %d\n"
return ng;
}
-static int first_colour(int fC, egCol Col, t_graph* g, const egCol egc[])
-/* Return the first node with colour Col starting at fC.
+/* Return the first node/atom with colour Col starting at fC.
* return -1 if none found.
*/
+static gmx::index first_colour(const int fC, const egCol Col, const t_graph* g, ArrayRef<const egCol> edgeColor)
{
- int i;
-
- for (i = fC; (i < g->nnodes); i++)
+ for (gmx::index i = fC; i < gmx::ssize(g->edges); i++)
{
- if ((g->nedge[i] > 0) && (egc[i] == Col))
+ if (!g->edges[i].empty() && edgeColor[i] == Col)
{
return i;
}
}
/* Returns the maximum length of the graph edges for coordinates x */
-static real maxEdgeLength(const t_graph g, int ePBC, const matrix box, const rvec x[])
+static real maxEdgeLength(const t_graph& g, PbcType pbcType, const matrix box, const rvec x[])
{
t_pbc pbc;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
real maxEdgeLength2 = 0;
- for (int node = 0; node < g.nnodes; node++)
+ for (int node = 0; node < int(g.edges.size()); node++)
{
- for (int edge = 0; edge < g.nedge[node]; edge++)
+ for (const int nodeJ : g.edges[node])
{
- int nodeJ = g.edge[node][edge];
rvec dx;
- pbc_dx(&pbc, x[g.at0 + node], x[g.at0 + nodeJ], dx);
+ pbc_dx(&pbc, x[node], x[nodeJ], dx);
maxEdgeLength2 = std::max(maxEdgeLength2, norm2(dx));
}
}
return std::sqrt(maxEdgeLength2);
}
-void mk_mshift(FILE* log, t_graph* g, int ePBC, const matrix box, const rvec x[])
+void mk_mshift(FILE* log, t_graph* g, PbcType pbcType, const matrix box, const rvec x[])
{
static int nerror_tot = 0;
int npbcdim;
- int ng, nnodes, i;
+ int ng, i;
int nW, nG, nB; /* Number of Grey, Black, White */
int fW, fG; /* First of each category */
int nerror = 0;
- g->bScrewPBC = (ePBC == epbcSCREW);
+ g->useScrewPbc = (pbcType == PbcType::Screw);
- if (ePBC == epbcXY)
+ if (pbcType == PbcType::XY)
{
npbcdim = 2;
}
* at all. If we return without doing this for a system without bonds
* (i.e. only settles) all water molecules are moved to the opposite octant
*/
- for (i = g->at0; (i < g->at1); i++)
+ for (i = 0; i < g->shiftAtomEnd; i++)
{
g->ishift[i][XX] = g->ishift[i][YY] = g->ishift[i][ZZ] = 0;
}
- if (!g->nbound)
+ if (!g->numConnectedAtoms)
{
return;
}
- nnodes = g->nnodes;
- if (nnodes > g->negc)
- {
- g->negc = nnodes;
- srenew(g->egc, g->negc);
- }
- memset(g->egc, 0, static_cast<size_t>(nnodes * sizeof(g->egc[0])));
+ std::fill(g->edgeColor.begin(), g->edgeColor.end(), egcolWhite);
- nW = g->nbound;
+ nW = g->numConnectedAtoms;
nG = 0;
nB = 0;
* number than before, because no nodes are made white
* in the loop
*/
- if ((fW = first_colour(fW, egcolWhite, g, g->egc)) == -1)
+ if ((fW = first_colour(fW, egcolWhite, g, g->edgeColor)) == -1)
{
gmx_fatal(FARGS, "No WHITE nodes found while nW=%d\n", nW);
}
/* Make the first white node grey */
- g->egc[fW] = egcolGrey;
+ g->edgeColor[fW] = egcolGrey;
nG++;
nW--;
#endif
while (nG > 0)
{
- if ((fG = first_colour(fG, egcolGrey, g, g->egc)) == -1)
+ if ((fG = first_colour(fG, egcolGrey, g, g->edgeColor)) == -1)
{
gmx_fatal(FARGS, "No GREY nodes found while nG=%d\n", nG);
}
/* Make the first grey node black */
- g->egc[fG] = egcolBlack;
+ g->edgeColor[fG] = egcolBlack;
nB++;
nG--;
/* Make all the neighbours of this black node grey
* and set their periodicity
*/
- ng = mk_grey(g->egc, g, &fG, npbcdim, box, x, &nerror);
+ ng = mk_grey(g->edgeColor, g, &fG, npbcdim, box, x, &nerror);
/* ng is the number of white nodes made grey */
nG += ng;
nW -= ng;
*/
constexpr real c_relativeDistanceThreshold = 0.25;
- int numPbcDimensions = ePBC2npbcdim(ePBC);
- GMX_RELEASE_ASSERT(numPbcDimensions > 0, "Expect PBC with graph");
+ int npbcdim = numPbcDimensions(pbcType);
+ GMX_RELEASE_ASSERT(npbcdim > 0, "Expect PBC with graph");
real minBoxSize = norm(box[XX]);
- for (int d = 1; d < numPbcDimensions; d++)
+ for (int d = 1; d < npbcdim; d++)
{
minBoxSize = std::min(minBoxSize, norm(box[d]));
}
- real maxDistance = maxEdgeLength(*g, ePBC, box, x);
+ real maxDistance = maxEdgeLength(*g, pbcType, box, x);
if (maxDistance >= c_relativeDistanceThreshold * minBoxSize)
{
std::string mesg = gmx::formatString(
"There are inconsistent shifts over periodic boundaries in a molecule type "
"consisting of %d atoms. The longest distance involved in such interactions is "
"%.3f nm which is %s half the box length.",
- g->at1 - g->at0, maxDistance, maxDistance >= 0.5 * minBoxSize ? "above" : "close to");
+ g->shiftAtomEnd, maxDistance, maxDistance >= 0.5 * minBoxSize ? "above" : "close to");
switch (g->parts)
{
void shift_x(const t_graph* g, const matrix box, const rvec x[], rvec x_s[])
{
- ivec* is;
- int g0, g1;
- int j, tx, ty, tz;
+ int j, tx, ty, tz;
GCHECK(g);
- g0 = g->at_start;
- g1 = g->at_end;
- is = g->ishift;
+ const int g0 = g->edgeAtomBegin;
+ const int g1 = g->edgeAtomEnd;
+ ArrayRef<const IVec> is = g->ishift;
- for (j = g->at0; j < g0; j++)
+ for (j = 0; j < g0; j++)
{
copy_rvec(x[j], x_s[j]);
}
- if (g->bScrewPBC)
+ if (g->useScrewPbc)
{
for (j = g0; (j < g1); j++)
{
}
}
- for (j = g1; j < g->at1; j++)
+ for (j = g1; j < g->shiftAtomEnd; j++)
{
copy_rvec(x[j], x_s[j]);
}
}
-void shift_self(const t_graph* g, const matrix box, rvec x[])
+void shift_self(const t_graph& g, const matrix box, rvec x[])
{
- ivec* is;
- int g0, g1;
- int j, tx, ty, tz;
+ int j, tx, ty, tz;
- if (g->bScrewPBC)
- {
- gmx_incons("screw pbc not implemented for shift_self");
- }
+ GMX_RELEASE_ASSERT(!g.useScrewPbc, "screw pbc not implemented for shift_self");
- g0 = g->at_start;
- g1 = g->at_end;
- is = g->ishift;
+ const int g0 = g.edgeAtomBegin;
+ const int g1 = g.edgeAtomEnd;
+ ArrayRef<const IVec> is = g.ishift;
#ifdef DEBUG
fprintf(stderr, "Shifting atoms %d to %d\n", g0, g0 + gn);
}
}
+void shift_self(const t_graph* g, const matrix box, rvec x[])
+{
+ shift_self(*g, box, x);
+}
+
void unshift_x(const t_graph* g, const matrix box, rvec x[], const rvec x_s[])
{
- ivec* is;
- int g0, g1;
- int j, tx, ty, tz;
+ int j, tx, ty, tz;
- if (g->bScrewPBC)
+ if (g->useScrewPbc)
{
gmx_incons("screw pbc not implemented (yet) for unshift_x");
}
- g0 = g->at_start;
- g1 = g->at_end;
- is = g->ishift;
+ const int g0 = g->edgeAtomBegin;
+ const int g1 = g->edgeAtomEnd;
+ ArrayRef<const IVec> is = g->ishift;
- for (j = g->at0; j < g0; j++)
+ for (j = 0; j < g0; j++)
{
copy_rvec(x_s[j], x[j]);
}
}
}
- for (j = g1; j < g->at1; j++)
+ for (j = g1; j < g->shiftAtomEnd; j++)
{
copy_rvec(x_s[j], x[j]);
}
void unshift_self(const t_graph* g, const matrix box, rvec x[])
{
- ivec* is;
- int g0, g1;
- int j, tx, ty, tz;
+ int j, tx, ty, tz;
- if (g->bScrewPBC)
+ if (g->useScrewPbc)
{
gmx_incons("screw pbc not implemented for unshift_self");
}
- g0 = g->at_start;
- g1 = g->at_end;
- is = g->ishift;
+ const int g0 = g->edgeAtomBegin;
+ const int g1 = g->edgeAtomEnd;
+ ArrayRef<const IVec> is = g->ishift;
if (TRICLINIC(box))
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_PBCUTIL_MSHIFT_H
#define GMX_PBCUTIL_MSHIFT_H
-#include <stdio.h>
+#include <cstdio>
+
+#include <vector>
#include "gromacs/math/vectypes.h"
#include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/listoflists.h"
struct InteractionList;
struct gmx_moltype_t;
+class InteractionDefinitions;
struct t_idef;
+enum class PbcType : int;
typedef enum
{
egcolNR
} egCol;
+/* Struct used to make molecules broken over PBC whole
+ *
+ * TODO: Should be turned into a proper class
+ */
struct t_graph
{
- /* Described the connectivity between, potentially, multiple parts of
+ /* Describes the connectivity between, potentially, multiple parts of
* the ilist that are internally chemically bonded together.
*/
enum class BondedParts
MultipleConnected /* There are multiple parts, e.g. monomers, that are partially or fully connected between each other by interactions other than chemical bonds */
};
- int at0; /* The first atom the graph was constructed for */
- int at1; /* The last atom the graph was constructed for */
- int nnodes; /* The number of nodes, nnodes=at_end-at_start */
- int nbound; /* The number of nodes with edges */
- int at_start; /* The first connected atom in this graph */
- int at_end; /* The last+1 connected atom in this graph */
- int* nedge; /* For each node the number of edges */
- int** edge; /* For each node, the actual edges (bidirect.) */
- gmx_bool bScrewPBC; /* Screw boundary conditions */
- ivec* ishift; /* Shift for each particle */
- int negc;
- egCol* egc; /* color of each node */
- BondedParts parts; /* How chemically bonded parts are connected */
+ // Returns the number of nodes stored in the graph (can be less than shiftAtomEnd)
+ int numNodes() const { return edges.size(); }
+
+ // Shift atoms up to shiftAtomEnd
+ int shiftAtomEnd = 0;
+ // The number of atoms that are connected to other atoms in the graph
+ int numConnectedAtoms = 0;
+ // The first connected atom in the graph
+ int edgeAtomBegin = 0;
+ // The last connected atom in the graph
+ int edgeAtomEnd = 0;
+ // The graph: list of atoms connected to each atom, indexing is offset by -edgeAtomBegin
+ gmx::ListOfLists<int> edges;
+ // Whether we are using screw PBC
+ bool useScrewPbc = false;
+ // Shift for each particle, updated after putting atoms in the box
+ std::vector<gmx::IVec> ishift;
+ // Work buffer for coloring nodes
+ std::vector<egCol> edgeColor;
+ // Tells how connected this graph is
+ BondedParts parts = BondedParts::Single;
};
#define SHIFT_IVEC(g, i) ((g)->ishift[i])
-t_graph* mk_graph(FILE* fplog, const struct t_idef* idef, int at_start, int at_end, gmx_bool bShakeOnly, gmx_bool bSettle);
+t_graph mk_graph(const InteractionDefinitions& idef, int numAtoms);
+/* Build a graph from an idef description. The graph can be used
+ * to generate mol-shift indices.
+ * numAtoms should coincide will molecule boundaries,
+ */
+
+t_graph* mk_graph(FILE* fplog,
+ const InteractionDefinitions& idef,
+ int shiftAtomEnd,
+ gmx_bool bShakeOnly,
+ gmx_bool bSettle);
/* Build a graph from an idef description. The graph can be used
* to generate mol-shift indices.
- * at_start and at_end should coincide will molecule boundaries,
- * for the whole system this is simply 0 and natoms.
+ * Shifts atoms up to shiftAtomEnd, which should coincide with a molecule boundary,
+ * for the whole system this is simply natoms.
* If bShakeOnly, only the connections in the shake list are used.
* If bSettle && bShakeOnly the settles are used too.
*/
-void mk_graph_moltype(const gmx_moltype_t& moltype, t_graph* g);
-/* As mk_graph, but takes gmx_moltype_t iso t_idef and does not allocate g */
+t_graph* mk_graph(FILE* fplog, const struct t_idef* idef, int shiftAtomEnd, gmx_bool bShakeOnly, gmx_bool bSettle);
+/* Build a graph from an idef description. The graph can be used
+ * to generate mol-shift indices.
+ * Shifts atoms up to shiftAtomEnd, which should coincide with a molecule boundary,
+ * for the whole system this is simply natoms.
+ * If bShakeOnly, only the connections in the shake list are used.
+ * If bSettle && bShakeOnly the settles are used too.
+ */
+
+t_graph mk_graph_moltype(const gmx_moltype_t& moltype);
+/* As mk_graph, but takes gmx_moltype_t iso t_idef */
void done_graph(t_graph* g);
-/* Free the memory in g */
+/* Free the memory in *g and the pointer g */
-void p_graph(FILE* log, const char* title, t_graph* g);
+void p_graph(FILE* log, const char* title, const t_graph* g);
/* Print a graph to log */
-void mk_mshift(FILE* log, t_graph* g, int ePBC, const matrix box, const rvec x[]);
+void mk_mshift(FILE* log, t_graph* g, PbcType pbcType, const matrix box, const rvec x[]);
/* Calculate the mshift codes, based on the connection graph in g. */
void shift_x(const t_graph* g, const matrix box, const rvec x[], rvec x_s[]);
/* Add the shift vector to x, and store in x_s (may be same array as x) */
+void shift_self(const t_graph& g, const matrix box, rvec x[]);
+/* Id. but in place */
+
void shift_self(const t_graph* g, const matrix box, rvec x[]);
/* Id. but in place */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
-const char* epbc_names[epbcNR + 1] = { "xyz", "no", "xy", "screw", nullptr };
+const gmx::EnumerationArray<PbcType, std::string> c_pbcTypeNames = { { "xyz", "no", "xy", "screw",
+ "unset" } };
/* Skip 0 so we have more chance of detecting if we forgot to call set_pbc. */
enum
//! Margin correction if the box is too skewed
#define BOX_MARGIN_CORRECT 1.0005
-int ePBC2npbcdim(int ePBC)
+int numPbcDimensions(PbcType pbcType)
{
int npbcdim = 0;
- switch (ePBC)
+ switch (pbcType)
{
- case epbcXYZ: npbcdim = 3; break;
- case epbcXY: npbcdim = 2; break;
- case epbcSCREW: npbcdim = 3; break;
- case epbcNONE: npbcdim = 0; break;
- default: gmx_fatal(FARGS, "Unknown ePBC=%d in ePBC2npbcdim", ePBC);
+ case PbcType::Unset:
+ gmx_fatal(FARGS, "Number of PBC dimensions was requested before the PBC type set.");
+ case PbcType::Xyz: npbcdim = 3; break;
+ case PbcType::XY: npbcdim = 2; break;
+ case PbcType::Screw: npbcdim = 3; break;
+ case PbcType::No: npbcdim = 0; break;
+ default:
+ gmx_fatal(FARGS, "Unknown pbcType=%s in numPbcDimensions", c_pbcTypeNames[pbcType].c_str());
}
return npbcdim;
{
rvec sum_box;
- fprintf(fp, "ePBCDX = %d\n", pbc->ePBCDX);
+ fprintf(fp, "pbcTypeDX = %d\n", pbc->pbcTypeDX);
pr_rvecs(fp, 0, "box", pbc->box, DIM);
pr_rvecs(fp, 0, "fbox_diag", &pbc->fbox_diag, 1);
pr_rvecs(fp, 0, "hbox_diag", &pbc->hbox_diag, 1);
}
}
-const char* check_box(int ePBC, const matrix box)
+const char* check_box(PbcType pbcType, const matrix box)
{
const char* ptr;
- if (ePBC == -1)
+ if (pbcType == PbcType::Unset)
{
- ePBC = guess_ePBC(box);
+ pbcType = guessPbcType(box);
}
- if (ePBC == epbcNONE)
+ if (pbcType == PbcType::No)
{
return nullptr;
}
ptr = "Only triclinic boxes with the first vector parallel to the x-axis and the second "
"vector in the xy-plane are supported.";
}
- else if (ePBC == epbcSCREW && (box[YY][XX] != 0 || box[ZZ][XX] != 0))
+ else if (pbcType == PbcType::Screw && (box[YY][XX] != 0 || box[ZZ][XX] != 0))
{
ptr = "The unit cell can not have off-diagonal x-components with screw pbc";
}
else if (std::fabs(box[YY][XX]) > BOX_MARGIN * 0.5 * box[XX][XX]
- || (ePBC != epbcXY
+ || (pbcType != PbcType::XY
&& (std::fabs(box[ZZ][XX]) > BOX_MARGIN * 0.5 * box[XX][XX]
|| std::fabs(box[ZZ][YY]) > BOX_MARGIN * 0.5 * box[YY][YY])))
{
std::sqrt(gmx::square(vec[ZZ]) - box[ZZ][XX] * box[ZZ][XX] - box[ZZ][YY] * box[ZZ][YY]);
}
-real max_cutoff2(int ePBC, const matrix box)
+real max_cutoff2(PbcType pbcType, const matrix box)
{
real min_hv2, min_ss;
const real oneFourth = 0.25;
* by half the length of the shortest box vector.
*/
min_hv2 = oneFourth * std::min(norm2(box[XX]), norm2(box[YY]));
- if (ePBC != epbcXY)
+ if (pbcType != PbcType::XY)
{
min_hv2 = std::min(min_hv2, oneFourth * norm2(box[ZZ]));
}
* in the grid search and pbc_dx is a lot faster
* than checking all possible combinations.
*/
- if (ePBC == epbcXY)
+ if (pbcType == PbcType::XY)
{
min_ss = std::min(box[XX][XX], box[YY][YY]);
}
//! Set to true if warning has been printed
static gmx_bool bWarnedGuess = FALSE;
-int guess_ePBC(const matrix box)
+PbcType guessPbcType(const matrix box)
{
- int ePBC;
+ PbcType pbcType;
if (box[XX][XX] > 0 && box[YY][YY] > 0 && box[ZZ][ZZ] > 0)
{
- ePBC = epbcXYZ;
+ pbcType = PbcType::Xyz;
}
else if (box[XX][XX] > 0 && box[YY][YY] > 0 && box[ZZ][ZZ] == 0)
{
- ePBC = epbcXY;
+ pbcType = PbcType::XY;
}
else if (box[XX][XX] == 0 && box[YY][YY] == 0 && box[ZZ][ZZ] == 0)
{
- ePBC = epbcNONE;
+ pbcType = PbcType::No;
}
else
{
box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
bWarnedGuess = TRUE;
}
- ePBC = epbcNONE;
+ pbcType = PbcType::No;
}
if (debug)
{
- fprintf(debug, "Guessed pbc = %s from the box matrix\n", epbc_names[ePBC]);
+ fprintf(debug, "Guessed pbc = %s from the box matrix\n", c_pbcTypeNames[pbcType].c_str());
}
- return ePBC;
+ return pbcType;
}
//! Check if the box still obeys the restrictions, if not, correct it
return shift;
}
-gmx_bool correct_box(FILE* fplog, int step, tensor box, t_graph* graph)
+gmx_bool correct_box(FILE* fplog, int step, tensor box)
{
- int zy, zx, yx, i;
+ int zy, zx, yx;
gmx_bool bCorrected;
zy = correct_box_elem(fplog, step, box, ZZ, YY);
bCorrected = ((zy != 0) || (zx != 0) || (yx != 0));
- if (bCorrected && graph)
- {
- /* correct the graph */
- for (i = graph->at_start; i < graph->at_end; i++)
- {
- graph->ishift[i][YY] -= graph->ishift[i][ZZ] * zy;
- graph->ishift[i][XX] -= graph->ishift[i][ZZ] * zx;
- graph->ishift[i][XX] -= graph->ishift[i][YY] * yx;
- }
- }
-
return bCorrected;
}
//! Do the real arithmetic for filling the pbc struct
-static void low_set_pbc(t_pbc* pbc, int ePBC, const ivec dd_pbc, const matrix box)
+static void low_set_pbc(t_pbc* pbc, PbcType pbcType, const ivec dd_pbc, const matrix box)
{
int order[3] = { 0, -1, 1 };
ivec bPBC;
const char* ptr;
- pbc->ePBC = ePBC;
- pbc->ndim_ePBC = ePBC2npbcdim(ePBC);
+ pbc->pbcType = pbcType;
+ pbc->ndim_ePBC = numPbcDimensions(pbcType);
- if (pbc->ePBC == epbcNONE)
+ if (pbc->pbcType == PbcType::No)
{
- pbc->ePBCDX = epbcdxNOPBC;
+ pbc->pbcTypeDX = epbcdxNOPBC;
return;
}
pbc->mhbox_diag[i] = -pbc->hbox_diag[i];
}
- ptr = check_box(ePBC, box);
+ ptr = check_box(pbcType, box);
if (ptr)
{
fprintf(stderr, "Warning: %s\n", ptr);
pr_rvecs(stderr, 0, " Box", box, DIM);
fprintf(stderr, " Can not fix pbc.\n\n");
- pbc->ePBCDX = epbcdxUNSUPPORTED;
+ pbc->pbcTypeDX = epbcdxUNSUPPORTED;
}
else
{
- if (ePBC == epbcSCREW && nullptr != dd_pbc)
+ if (pbcType == PbcType::Screw && nullptr != dd_pbc)
{
/* This combinated should never appear here */
gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL");
int npbcdim = 0;
for (int i = 0; i < DIM; i++)
{
- if ((dd_pbc && dd_pbc[i] == 0) || (ePBC == epbcXY && i == ZZ))
+ if ((dd_pbc && dd_pbc[i] == 0) || (pbcType == PbcType::XY && i == ZZ))
{
bPBC[i] = 0;
}
/* 1D pbc is not an mdp option and it is therefore only used
* with single shifts.
*/
- pbc->ePBCDX = epbcdx1D_RECT;
+ pbc->pbcTypeDX = epbcdx1D_RECT;
for (int i = 0; i < DIM; i++)
{
if (bPBC[i])
{
if (pbc->box[pbc->dim][i] != 0)
{
- pbc->ePBCDX = epbcdx1D_TRIC;
+ pbc->pbcTypeDX = epbcdx1D_TRIC;
}
}
break;
case 2:
- pbc->ePBCDX = epbcdx2D_RECT;
+ pbc->pbcTypeDX = epbcdx2D_RECT;
for (int i = 0; i < DIM; i++)
{
if (!bPBC[i])
{
if (pbc->box[i][j] != 0)
{
- pbc->ePBCDX = epbcdx2D_TRIC;
+ pbc->pbcTypeDX = epbcdx2D_TRIC;
}
}
}
}
break;
case 3:
- if (ePBC != epbcSCREW)
+ if (pbcType != PbcType::Screw)
{
if (TRICLINIC(box))
{
- pbc->ePBCDX = epbcdxTRICLINIC;
+ pbc->pbcTypeDX = epbcdxTRICLINIC;
}
else
{
- pbc->ePBCDX = epbcdxRECTANGULAR;
+ pbc->pbcTypeDX = epbcdxRECTANGULAR;
}
}
else
{
- pbc->ePBCDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC);
- if (pbc->ePBCDX == epbcdxSCREW_TRIC)
+ pbc->pbcTypeDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC);
+ if (pbc->pbcTypeDX == epbcdxSCREW_TRIC)
{
fprintf(stderr,
"Screw pbc is not yet implemented for triclinic boxes.\n"
"Can not fix pbc.\n");
- pbc->ePBCDX = epbcdxUNSUPPORTED;
+ pbc->pbcTypeDX = epbcdxUNSUPPORTED;
}
}
break;
default: gmx_fatal(FARGS, "Incorrect number of pbc dimensions with DD: %d", npbcdim);
}
- pbc->max_cutoff2 = max_cutoff2(ePBC, box);
+ pbc->max_cutoff2 = max_cutoff2(pbcType, box);
- if (pbc->ePBCDX == epbcdxTRICLINIC || pbc->ePBCDX == epbcdx2D_TRIC || pbc->ePBCDX == epbcdxSCREW_TRIC)
+ if (pbc->pbcTypeDX == epbcdxTRICLINIC || pbc->pbcTypeDX == epbcdx2D_TRIC
+ || pbc->pbcTypeDX == epbcdxSCREW_TRIC)
{
if (debug)
{
}
}
-void set_pbc(t_pbc* pbc, int ePBC, const matrix box)
+void set_pbc(t_pbc* pbc, PbcType pbcType, const matrix box)
{
- if (ePBC == -1)
+ if (pbcType == PbcType::Unset)
{
- ePBC = guess_ePBC(box);
+ pbcType = guessPbcType(box);
}
- low_set_pbc(pbc, ePBC, nullptr, box);
+ low_set_pbc(pbc, pbcType, nullptr, box);
}
-t_pbc* set_pbc_dd(t_pbc* pbc, int ePBC, const ivec domdecCells, gmx_bool bSingleDir, const matrix box)
+t_pbc* set_pbc_dd(t_pbc* pbc, PbcType pbcType, const ivec domdecCells, gmx_bool bSingleDir, const matrix box)
{
- if (ePBC == epbcNONE)
+ if (pbcType == PbcType::No)
{
- pbc->ePBC = ePBC;
+ pbc->pbcType = pbcType;
return nullptr;
}
if (nullptr == domdecCells)
{
- low_set_pbc(pbc, ePBC, nullptr, box);
+ low_set_pbc(pbc, pbcType, nullptr, box);
}
else
{
- if (ePBC == epbcSCREW && domdecCells[XX] > 1)
+ if (pbcType == PbcType::Screw && domdecCells[XX] > 1)
{
/* The rotation has been taken care of during coordinate communication */
- ePBC = epbcXYZ;
+ pbcType = PbcType::Xyz;
}
ivec usePBC;
for (int i = 0; i < DIM; i++)
{
usePBC[i] = 0;
- if (domdecCells[i] <= (bSingleDir ? 1 : 2) && !(ePBC == epbcXY && i == ZZ))
+ if (domdecCells[i] <= (bSingleDir ? 1 : 2) && !(pbcType == PbcType::XY && i == ZZ))
{
usePBC[i] = 1;
npbcdim++;
if (npbcdim > 0)
{
- low_set_pbc(pbc, ePBC, usePBC, box);
+ low_set_pbc(pbc, pbcType, usePBC, box);
}
else
{
- pbc->ePBC = epbcNONE;
+ pbc->pbcType = PbcType::No;
}
}
- return (pbc->ePBC != epbcNONE ? pbc : nullptr);
+ return (pbc->pbcType != PbcType::No ? pbc : nullptr);
}
void pbc_dx(const t_pbc* pbc, const rvec x1, const rvec x2, rvec dx)
rvec_sub(x1, x2, dx);
- switch (pbc->ePBCDX)
+ switch (pbc->pbcTypeDX)
{
case epbcdxRECTANGULAR:
for (i = 0; i < DIM; i++)
rvec_sub(x1, x2, dx);
clear_ivec(ishift);
- switch (pbc->ePBCDX)
+ switch (pbc->pbcTypeDX)
{
case epbcdxRECTANGULAR:
for (i = 0; i < DIM; i++)
dvec_sub(x1, x2, dx);
- switch (pbc->ePBCDX)
+ switch (pbc->pbcTypeDX)
{
case epbcdxRECTANGULAR:
case epbcdx2D_RECT:
return edge;
}
-void put_atoms_in_box(int ePBC, const matrix box, gmx::ArrayRef<gmx::RVec> x)
+void put_atoms_in_box(PbcType pbcType, const matrix box, gmx::ArrayRef<gmx::RVec> x)
{
int npbcdim, m, d;
- if (ePBC == epbcSCREW)
+ if (pbcType == PbcType::Screw)
{
- gmx_fatal(FARGS, "Sorry, %s pbc is not yet supported", epbc_names[ePBC]);
+ gmx_fatal(FARGS, "Sorry, %s pbc is not yet supported", c_pbcTypeNames[pbcType].c_str());
}
- if (ePBC == epbcXY)
+ if (pbcType == PbcType::XY)
{
npbcdim = 2;
}
}
}
-void put_atoms_in_box_omp(int ePBC, const matrix box, gmx::ArrayRef<gmx::RVec> x, gmx_unused int nth)
+void put_atoms_in_box_omp(PbcType pbcType, const matrix box, gmx::ArrayRef<gmx::RVec> x, gmx_unused int nth)
{
#pragma omp parallel for num_threads(nth) schedule(static)
for (int t = 0; t < nth; t++)
size_t natoms = x.size();
size_t offset = (natoms * t) / nth;
size_t len = (natoms * (t + 1)) / nth - offset;
- put_atoms_in_box(ePBC, box, x.subArray(offset, len));
+ put_atoms_in_box(pbcType, box, x.subArray(offset, len));
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
}
}
}
-void put_atoms_in_compact_unitcell(int ePBC, int ecenter, const matrix box, gmx::ArrayRef<gmx::RVec> x)
+void put_atoms_in_compact_unitcell(PbcType pbcType, int ecenter, const matrix box, gmx::ArrayRef<gmx::RVec> x)
{
t_pbc pbc;
rvec box_center, dx;
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
- if (pbc.ePBCDX == epbcdxUNSUPPORTED)
+ if (pbc.pbcTypeDX == epbcdxUNSUPPORTED)
{
gmx_fatal(FARGS, "Can not put atoms in compact unitcell with unsupported PBC");
}
/*! \brief Make molecules whole by shifting positions
*
* \param[in] fplog Log file
- * \param[in] ePBC The PBC type
+ * \param[in] pbcType The PBC type
* \param[in] box The simulation box
* \param[in] mtop System topology definition
* \param[in,out] x The coordinates of the atoms
* \param[in] bFirst Specifier for first-time PBC removal
*/
-static void low_do_pbc_mtop(FILE* fplog, int ePBC, const matrix box, const gmx_mtop_t* mtop, rvec x[], gmx_bool bFirst)
+static void
+low_do_pbc_mtop(FILE* fplog, PbcType pbcType, const matrix box, const gmx_mtop_t* mtop, rvec x[], gmx_bool bFirst)
{
- t_graph* graph;
- int as, mol;
+ int as, mol;
if (bFirst && fplog)
{
fprintf(fplog, "Removing pbc first time\n");
}
- snew(graph, 1);
as = 0;
for (const gmx_molblock_t& molb : mtop->molblock)
{
}
else
{
- mk_graph_moltype(moltype, graph);
+ t_graph graph = mk_graph_moltype(moltype);
for (mol = 0; mol < molb.nmol; mol++)
{
- mk_mshift(fplog, graph, ePBC, box, x + as);
+ mk_mshift(fplog, &graph, pbcType, box, x + as);
shift_self(graph, box, x + as);
/* The molecule is whole now.
as += moltype.atoms.nr;
}
- done_graph(graph);
}
}
- sfree(graph);
}
-void do_pbc_first_mtop(FILE* fplog, int ePBC, const matrix box, const gmx_mtop_t* mtop, rvec x[])
+void do_pbc_first_mtop(FILE* fplog, PbcType pbcType, const matrix box, const gmx_mtop_t* mtop, rvec x[])
{
- low_do_pbc_mtop(fplog, ePBC, box, mtop, x, TRUE);
+ low_do_pbc_mtop(fplog, pbcType, box, mtop, x, TRUE);
}
-void do_pbc_mtop(int ePBC, const matrix box, const gmx_mtop_t* mtop, rvec x[])
+void do_pbc_mtop(PbcType pbcType, const matrix box, const gmx_mtop_t* mtop, rvec x[])
{
- low_do_pbc_mtop(nullptr, ePBC, box, mtop, x, FALSE);
+ low_do_pbc_mtop(nullptr, pbcType, box, mtop, x, FALSE);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <stdio.h>
+#include <string>
+
#include "gromacs/math/vectypes.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/real.h"
struct gmx_domdec_t;
struct gmx_mtop_t;
-enum
+//! Enumeration that contains all supported periodic boundary setups.
+enum class PbcType : int
{
- epbcXYZ,
- epbcNONE,
- epbcXY,
- epbcSCREW,
- epbcNR
+ Xyz = 0, //!< Periodic boundaries in all dimensions.
+ No = 1, //!< No periodic boundaries.
+ XY = 2, //!< Only two dimensions are periodic.
+ Screw = 3, //!< Screw.
+ Unset = 4, //!< The type of PBC is not set or invalid.
+ Count = 5
};
-//! Strings corresponding to epbc enum values.
-extern const char* epbc_names[epbcNR + 1];
+//! Names for all values in PBC types enumeration
+extern const gmx::EnumerationArray<PbcType, std::string> c_pbcTypeNames;
/* Maximum number of combinations of single triclinic box vectors
* required to shift atoms that are within a brick of the size of
typedef struct t_pbc
{
//! The PBC type
- int ePBC;
+ PbcType pbcType;
//! Number of dimensions in which PBC is exerted
int ndim_ePBC;
/*! \brief Determines how to compute distance vectors.
*
* Indicator of how to compute distance vectors, depending
- * on PBC type (depends on ePBC and dimensions with(out) DD)
+ * on PBC type (depends on pbcType and dimensions with(out) DD)
* and the box angles.
*/
- int ePBCDX;
+ int pbcTypeDX;
/*! \brief Used for selecting which dimensions to use in PBC.
*
* In case of 1-D PBC this indicates which dimension is used,
ecenterDEF = ecenterTRIC
};
-struct t_graph;
-
/*! \brief Returns the number of dimensions that use pbc
*
- * \param[in] ePBC The periodic boundary condition type
+ * \param[in] pbcType The periodic boundary condition type
* \return the number of dimensions that use pbc, starting at X
*/
-int ePBC2npbcdim(int ePBC);
+int numPbcDimensions(PbcType pbcType);
/*! \brief Dump the contents of the pbc structure to the file
*
/*! \brief Check the box for consistency
*
- * \param[in] ePBC The pbc identifier
- * \param[in] box The box matrix
+ * When \p pbcType=PbcTypes::Unset, the type of pbc is guessed from the box matrix.
+ *
+ * \param[in] pbcType The pbc identifier
+ * \param[in] box The box matrix
* \return NULL if the box is supported by Gromacs.
- * Otherwise returns a string with the problem.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
+ * Otherwise returns a string with the problem.
*/
-const char* check_box(int ePBC, const matrix box);
+const char* check_box(PbcType pbcType, const matrix box);
/*! \brief Creates box matrix from edge lengths and angles.
*
- * \param[in,out] box The box matrix
+ * \param[in,out] box The box matrix
* \param[in] vec The edge lengths
* \param[in] angleInDegrees The angles
*/
* Returns the square of the maximum cut-off allowed for the box,
* taking into account that the grid neighborsearch code and pbc_dx
* only check combinations of single box-vector shifts.
- * \param[in] ePBC The pbc identifier
+ *
+ * \param[in] pbcType The pbc identifier
* \param[in] box The box matrix
* \return the maximum cut-off.
*/
-real max_cutoff2(int ePBC, const matrix box);
+real max_cutoff2(PbcType pbcType, const matrix box);
-/*! \brief Guess PBC typr
+/*! \brief Guess PBC type
*
* Guesses the type of periodic boundary conditions using the box
+ *
* \param[in] box The box matrix
- * \return The pbc identifier
+ * \return The pbc type identifier
*/
-int guess_ePBC(const matrix box);
+PbcType guessPbcType(const matrix box);
/*! \brief Corrects the box if necessary
*
- * Checks for un-allowed box angles and corrects the box
- * and the integer shift vectors in the graph (if graph!=NULL) if necessary.
+ * Checks for un-allowed box angles and corrects the box.
+ *
* \param[in] fplog File for debug output
* \param[in] step The MD step number
* \param[in] box The simulation cell
- * \param[in] graph Information about molecular connectivity
* \return TRUE when the box was corrected.
*/
-gmx_bool correct_box(FILE* fplog, int step, tensor box, struct t_graph* graph);
+gmx_bool correct_box(FILE* fplog, int step, tensor box);
/*! \brief Initiate the periodic boundary condition algorithms.
*
* pbc_dx will not use pbc and return the normal difference vector
* when one or more of the diagonal elements of box are zero.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
+ * When \p pbcType=PbcType::Unset, the type of pbc is guessed from the box matrix.
+ *
* \param[in,out] pbc The pbc information structure
- * \param[in] ePBC The PBC identifier
- * \param[in] box The box tensor
+ * \param[in] pbcType The PBC identifier
+ * \param[in] box The box tensor
*/
-void set_pbc(t_pbc* pbc, int ePBC, const matrix box);
+void set_pbc(t_pbc* pbc, PbcType pbcType, const matrix box);
/*! \brief Initiate the periodic boundary condition algorithms.
*
* If domdecCells!=NULL pbc is not used for directions
* with dd->nc[i]==1 with bSingleDir==TRUE or
* with dd->nc[i]<=2 with bSingleDir==FALSE.
- * Note that when no PBC is required only pbc->ePBC is set,
+ * Note that when no PBC is required only pbc->pbcType is set,
* the rest of the struct will be invalid.
- * \param[in,out] pbc The pbc information structure
- * \param[in] ePBC The PBC identifier
+ *
+ * \param[in,out] pbc The pbc information structure
+ * \param[in] pbcType The PBC identifier
* \param[in] domdecCells 3D integer vector describing the number of DD cells
* or nullptr if not using DD.
* \param[in] bSingleDir TRUE if DD communicates only in one direction along dimensions
* \param[in] box The box tensor
* \return the pbc structure when pbc operations are required, NULL otherwise.
*/
-t_pbc* set_pbc_dd(t_pbc* pbc, int ePBC, const ivec domdecCells, gmx_bool bSingleDir, const matrix box);
+t_pbc* set_pbc_dd(t_pbc* pbc, PbcType pbcType, const ivec domdecCells, gmx_bool bSingleDir, const matrix box);
/*! \brief Compute distance with PBC
*
* These routines puts ONE or ALL atoms in the box, not caring
* about charge groups!
* Also works for triclinic cells.
- * \param[in] ePBC The pbc type
- * \param[in] box The simulation box
- * \param[in,out] x The coordinates of the atoms
+ *
+ * \param[in] pbcType The pbc type
+ * \param[in] box The simulation box
+ * \param[in,out] x The coordinates of the atoms
*/
-void put_atoms_in_box(int ePBC, const matrix box, gmx::ArrayRef<gmx::RVec> x);
+void put_atoms_in_box(PbcType pbcType, const matrix box, gmx::ArrayRef<gmx::RVec> x);
/*! \brief Parallellizes put_atoms_in_box()
*
* This wrapper function around put_atoms_in_box() with the ugly manual
* workload splitting is needed to avoid silently introducing multithreading
* in tools.
- * \param[in] ePBC The pbc type
+ *
+ * \param[in] pbcType The pbc type
* \param[in] box The simulation box
* \param[in,out] x The coordinates of the atoms
* \param[in] nth number of threads to be used in the given module
*/
-void put_atoms_in_box_omp(int ePBC, const matrix box, gmx::ArrayRef<gmx::RVec> x, gmx_unused int nth);
+void put_atoms_in_box_omp(PbcType pbcType, const matrix box, gmx::ArrayRef<gmx::RVec> x, gmx_unused int nth);
/*! \brief Put atoms inside triclinic box
*
*
* This puts ALL atoms at the closest distance for the center of the box
* as calculated by calc_box_center.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
- * \param[in] ePBC The pbc type
+ * When \p pbcType=PbcType::Unset, the type of pbc is guessed from the box matrix.
+ *
+ * \param[in] pbcType The pbc type
* \param[in] ecenter The pbc center type
* \param[in] box The simulation box
- * \param[in,out] x The coordinates of the atoms
+ * \param[in,out] x The coordinates of the atoms
*/
-void put_atoms_in_compact_unitcell(int ePBC, int ecenter, const matrix box, gmx::ArrayRef<gmx::RVec> x);
+void put_atoms_in_compact_unitcell(PbcType pbcType, int ecenter, const matrix box, gmx::ArrayRef<gmx::RVec> x);
/*! \brief Make all molecules whole by shifting positions
*
* \param[in] fplog Log file
- * \param[in] ePBC The PBC type
+ * \param[in] pbcType The PBC type
* \param[in] box The simulation box
* \param[in] mtop System topology definition
* \param[in,out] x The coordinates of the atoms
*/
-void do_pbc_first_mtop(FILE* fplog, int ePBC, const matrix box, const gmx_mtop_t* mtop, rvec x[]);
+void do_pbc_first_mtop(FILE* fplog, PbcType pbcType, const matrix box, const gmx_mtop_t* mtop, rvec x[]);
/*! \brief Make molecules consisting of multiple charge groups whole by shifting positions
*
- * \param[in] ePBC The PBC type
+ * \param[in] pbcType The PBC type
* \param[in] box The simulation box
* \param[in] mtop System topology definition
* \param[in,out] x The coordinates of the atoms
*/
-void do_pbc_mtop(int ePBC, const matrix box, const gmx_mtop_t* mtop, rvec x[]);
+void do_pbc_mtop(PbcType pbcType, const matrix box, const gmx_mtop_t* mtop, rvec x[]);
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \todo CPU, GPU and SIMD routines essentially do the same operations on
* different data-types. Currently this leads to code duplication,
- * which has to be resolved. For details, see Redmine task #2863
- * https://redmine.gromacs.org/issues/2863
+ * which has to be resolved. For details, see Issue #2863
+ * https://gitlab.com/gromacs/gromacs/-/issues/2863
*
* \author Mark Abraham <mark.j.abraham@gmail.com>
* \author Berk Hess <hess@kth.se>
* \todo This routine operates on rvec types and uses PbcAiuc to define
* periodic box, but essentially does the same thing as SIMD and GPU
* version. These will have to be unified in future to avoid code
- * duplication. See Redmine task #2863:
- * https://redmine.gromacs.org/issues/2863
+ * duplication. See Issue #2863:
+ * https://gitlab.com/gromacs/gromacs/-/issues/2863
*
* \param[in] pbcAiuc PBC object.
* \param[in] r1 Coordinates of the first point.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \todo CPU, GPU and SIMD routines essentially do the same operations on
* different data-types. Currently this leads to code duplication,
- * which has to be resolved. For details, see Redmine task #2863
- * https://redmine.gromacs.org/issues/2863
+ * which has to be resolved. For details, see Issue #2863
+ * https://gitlab.com/gromacs/gromacs/-/issues/2863
*
* \author Mark Abraham <mark.j.abraham@gmail.com>
* \author Berk Hess <hess@kth.se>
#ifndef GMX_PBCUTIL_PBC_AIUC_CUDA_CUH
#define GMX_PBCUTIL_PBC_AIUC_CUDA_CUH
-#include "gromacs/gpu_utils/gpu_vec.cuh"
#include "gromacs/gpu_utils/vectype_ops.cuh"
#include "gromacs/pbcutil/pbc_aiuc.h"
* the same thing as the version below, as well as SIMD and CPU
* versions. This routine is used in gpubonded module.
* To avoid code duplication, these implementations should be
- * unified. See Redmine task #2863:
- * https://redmine.gromacs.org/issues/2863
+ * unified. See Issue #2863:
+ * https://gitlab.com/gromacs/gromacs/-/issues/2863
*
* \param[in] pbcAiuc PBC object.
* \param[in] r1 Coordinates of the first point.
*/
template<bool returnShift>
static __forceinline__ __device__ int
- pbcDxAiuc(const PbcAiuc& pbcAiuc, const float4& r1, const float4& r2, fvec dr)
+ pbcDxAiuc(const PbcAiuc& pbcAiuc, const float4 r1, const float4 r2, float3& dr)
{
- dr[XX] = r1.x - r2.x;
- dr[YY] = r1.y - r2.y;
- dr[ZZ] = r1.z - r2.z;
+ dr.x = r1.x - r2.x;
+ dr.y = r1.y - r2.y;
+ dr.z = r1.z - r2.z;
- float shz = rintf(dr[ZZ] * pbcAiuc.invBoxDiagZ);
- dr[XX] -= shz * pbcAiuc.boxZX;
- dr[YY] -= shz * pbcAiuc.boxZY;
- dr[ZZ] -= shz * pbcAiuc.boxZZ;
+ float shz = rintf(dr.z * pbcAiuc.invBoxDiagZ);
+ dr.x -= shz * pbcAiuc.boxZX;
+ dr.y -= shz * pbcAiuc.boxZY;
+ dr.z -= shz * pbcAiuc.boxZZ;
- float shy = rintf(dr[YY] * pbcAiuc.invBoxDiagY);
- dr[XX] -= shy * pbcAiuc.boxYX;
- dr[YY] -= shy * pbcAiuc.boxYY;
+ float shy = rintf(dr.y * pbcAiuc.invBoxDiagY);
+ dr.x -= shy * pbcAiuc.boxYX;
+ dr.y -= shy * pbcAiuc.boxYY;
- float shx = rintf(dr[XX] * pbcAiuc.invBoxDiagX);
- dr[XX] -= shx * pbcAiuc.boxXX;
+ float shx = rintf(dr.x * pbcAiuc.invBoxDiagX);
+ dr.x -= shx * pbcAiuc.boxXX;
if (returnShift)
{
* version above, as well as SIMD and CPU versions. This routine is
* used in GPU-based constraints.
* To avoid code duplication, these implementations should be
- * unified. See Redmine task #2863:
- * https://redmine.gromacs.org/issues/2863
+ * unified. See Issue #2863:
+ * https://gitlab.com/gromacs/gromacs/-/issues/2863
*
* \param[in] pbcAiuc PBC object.
* \param[in] r1 Coordinates of the first point.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void set_pbc_simd(const t_pbc gmx_unused* pbc, real gmx_unused* pbc_simd)
{
#if GMX_SIMD_HAVE_REAL
- if (pbc != nullptr && pbc->ePBC != epbcNONE)
+ if (pbc != nullptr && pbc->pbcType != PbcType::No)
{
rvec inv_box_diag = { 0, 0, 0 };
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
-void calc_pbc_cluster(int ecenter, int nrefat, t_topology* top, int ePBC, rvec x[], const int index[], matrix box)
+void calc_pbc_cluster(int ecenter, int nrefat, t_topology* top, PbcType pbcType, rvec x[], const int index[], matrix box)
{
int m, i, j, j0, j1, jj, ai, aj;
int imin, jmin;
/* Initiate the pbc structure */
std::memset(&pbc, 0, sizeof(pbc));
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
/* Convert atom index to molecular */
nmol = top->mols.nr;
t_block* mols,
int natoms,
t_atom atom[],
- int ePBC,
+ PbcType pbcType,
matrix box,
rvec x[])
{
t_pbc pbc;
calc_box_center(ecenter, box, box_center);
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
if (mols->nr <= 0)
{
gmx_fatal(FARGS,
auto newComArrayRef = gmx::arrayRefFromArray(&newCom, 1);
switch (unitcell_enum)
{
- case euRect: put_atoms_in_box(ePBC, box, newComArrayRef); break;
+ case euRect: put_atoms_in_box(pbcType, box, newComArrayRef); break;
case euTric: put_atoms_in_triclinic_unitcell(ecenter, box, newComArrayRef); break;
case euCompact:
- put_atoms_in_compact_unitcell(ePBC, ecenter, box, newComArrayRef);
+ put_atoms_in_compact_unitcell(pbcType, ecenter, box, newComArrayRef);
break;
}
rvec_sub(newCom, com, shift);
}
}
-void put_residue_com_in_box(int unitcell_enum, int ecenter, int natoms, t_atom atom[], int ePBC, matrix box, rvec x[])
+void put_residue_com_in_box(int unitcell_enum,
+ int ecenter,
+ int natoms,
+ t_atom atom[],
+ PbcType pbcType,
+ matrix box,
+ rvec x[])
{
int i, j, res_start, res_end;
int d, presnr;
auto newComArrayRef = gmx::arrayRefFromArray(&newCom, 1);
switch (unitcell_enum)
{
- case euRect: put_atoms_in_box(ePBC, box, newComArrayRef); break;
+ case euRect: put_atoms_in_box(pbcType, box, newComArrayRef); break;
case euTric: put_atoms_in_triclinic_unitcell(ecenter, box, newComArrayRef); break;
case euCompact:
- put_atoms_in_compact_unitcell(ePBC, ecenter, box, newComArrayRef);
+ put_atoms_in_compact_unitcell(pbcType, ecenter, box, newComArrayRef);
break;
}
rvec_sub(newCom, com, shift);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_topology;
struct t_block;
struct t_atom;
+enum class PbcType : int;
#include "gmxpre.h"
euNR
};
-void calc_pbc_cluster(int ecenter, int nrefat, t_topology* top, int ePBC, rvec x[], const int index[], matrix box);
+void calc_pbc_cluster(int ecenter, int nrefat, t_topology* top, PbcType pbcType, rvec x[], const int index[], matrix box);
void put_molecule_com_in_box(int unitcell_enum,
t_block* mols,
int natoms,
t_atom atom[],
- int ePBC,
+ PbcType pbcType,
matrix box,
rvec x[]);
-void put_residue_com_in_box(int unitcell_enum, int ecenter, int natoms, t_atom atom[], int ePBC, matrix box, rvec x[]);
+void put_residue_com_in_box(int unitcell_enum,
+ int ecenter,
+ int natoms,
+ t_atom atom[],
+ PbcType pbcType,
+ matrix box,
+ rvec x[]);
void center_x(int ecenter, rvec x[], matrix box, int n, int nc, const int ci[]);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_rmpbc
{
- const t_idef* idef;
- int natoms_init;
- int ePBC;
- int ngraph;
- rmpbc_graph_t* graph;
+ const InteractionDefinitions* interactionDefinitions;
+ const t_idef* idef;
+ int natoms_init;
+ PbcType pbcType;
+ int ePBC;
+ int ngraph;
+ rmpbc_graph_t* graph;
};
-static t_graph* gmx_rmpbc_get_graph(gmx_rmpbc_t gpbc, int ePBC, int natoms)
+static t_graph* gmx_rmpbc_get_graph(gmx_rmpbc_t gpbc, PbcType pbcType, int natoms)
{
int i;
rmpbc_graph_t* gr;
- if (ePBC == epbcNONE || nullptr == gpbc || nullptr == gpbc->idef || gpbc->idef->ntypes <= 0)
+ if (pbcType == PbcType::No || nullptr == gpbc || nullptr == gpbc->idef || gpbc->idef->ntypes <= 0)
{
return nullptr;
}
srenew(gpbc->graph, gpbc->ngraph);
gr = &gpbc->graph[gpbc->ngraph - 1];
gr->natoms = natoms;
- gr->gr = mk_graph(nullptr, gpbc->idef, 0, natoms, FALSE, FALSE);
+ if (gpbc->interactionDefinitions)
+ {
+ gr->gr = mk_graph(nullptr, *gpbc->interactionDefinitions, natoms, FALSE, FALSE);
+ }
+ else
+ {
+ gr->gr = mk_graph(nullptr, gpbc->idef, natoms, FALSE, FALSE);
+ }
}
return gr->gr;
}
-gmx_rmpbc_t gmx_rmpbc_init(const t_idef* idef, int ePBC, int natoms)
+gmx_rmpbc_t gmx_rmpbc_init(const InteractionDefinitions& idef, PbcType pbcType, int natoms)
+{
+ gmx_rmpbc_t gpbc;
+
+ snew(gpbc, 1);
+
+ gpbc->natoms_init = natoms;
+
+ /* This sets pbc when we now it,
+ * otherwise we guess it from the instantaneous box in the trajectory.
+ */
+ gpbc->pbcType = pbcType;
+
+ gpbc->interactionDefinitions = &idef;
+
+ return gpbc;
+}
+
+gmx_rmpbc_t gmx_rmpbc_init(const t_idef* idef, PbcType pbcType, int natoms)
{
gmx_rmpbc_t gpbc;
/* This sets pbc when we now it,
* otherwise we guess it from the instantaneous box in the trajectory.
*/
- gpbc->ePBC = ePBC;
+ gpbc->pbcType = pbcType;
gpbc->idef = idef;
if (gpbc->idef->ntypes <= 0)
{
for (i = 0; i < gpbc->ngraph; i++)
{
- done_graph(gpbc->graph[i].gr);
- sfree(gpbc->graph[i].gr);
+ delete gpbc->graph[i].gr;
}
if (gpbc->graph != nullptr)
{
}
}
-static int gmx_rmpbc_ePBC(gmx_rmpbc_t gpbc, const matrix box)
+static PbcType gmx_rmpbc_ePBC(gmx_rmpbc_t gpbc, const matrix box)
{
- if (nullptr != gpbc && gpbc->ePBC >= 0)
+ if (nullptr != gpbc && gpbc->pbcType != PbcType::Unset)
{
- return gpbc->ePBC;
+ return gpbc->pbcType;
}
else
{
- return guess_ePBC(box);
+ return guessPbcType(box);
}
}
void gmx_rmpbc(gmx_rmpbc_t gpbc, int natoms, const matrix box, rvec x[])
{
- int ePBC;
+ PbcType pbcType;
t_graph* gr;
- ePBC = gmx_rmpbc_ePBC(gpbc, box);
- gr = gmx_rmpbc_get_graph(gpbc, ePBC, natoms);
+ pbcType = gmx_rmpbc_ePBC(gpbc, box);
+ gr = gmx_rmpbc_get_graph(gpbc, pbcType, natoms);
if (gr != nullptr)
{
- mk_mshift(stdout, gr, ePBC, box, x);
+ mk_mshift(stdout, gr, pbcType, box, x);
shift_self(gr, box, x);
}
}
void gmx_rmpbc_copy(gmx_rmpbc_t gpbc, int natoms, const matrix box, rvec x[], rvec x_s[])
{
- int ePBC;
+ PbcType pbcType;
t_graph* gr;
int i;
- ePBC = gmx_rmpbc_ePBC(gpbc, box);
- gr = gmx_rmpbc_get_graph(gpbc, ePBC, natoms);
+ pbcType = gmx_rmpbc_ePBC(gpbc, box);
+ gr = gmx_rmpbc_get_graph(gpbc, pbcType, natoms);
if (gr != nullptr)
{
- mk_mshift(stdout, gr, ePBC, box, x);
+ mk_mshift(stdout, gr, pbcType, box, x);
shift_x(gr, box, x, x_s);
}
else
void gmx_rmpbc_trxfr(gmx_rmpbc_t gpbc, t_trxframe* fr)
{
- int ePBC;
+ PbcType pbcType;
t_graph* gr;
if (fr->bX && fr->bBox)
{
- ePBC = gmx_rmpbc_ePBC(gpbc, fr->box);
- gr = gmx_rmpbc_get_graph(gpbc, ePBC, fr->natoms);
+ pbcType = gmx_rmpbc_ePBC(gpbc, fr->box);
+ gr = gmx_rmpbc_get_graph(gpbc, pbcType, fr->natoms);
if (gr != nullptr)
{
- mk_mshift(stdout, gr, ePBC, fr->box, fr->x);
+ mk_mshift(stdout, gr, pbcType, fr->box, fr->x);
shift_self(gr, fr->box, fr->x);
}
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/vectypes.h"
+class InteractionDefinitions;
struct t_atoms;
struct t_idef;
struct t_trxframe;
+enum class PbcType : int;
typedef struct gmx_rmpbc* gmx_rmpbc_t;
-gmx_rmpbc_t gmx_rmpbc_init(const t_idef* idef, int ePBC, int natoms);
+gmx_rmpbc_t gmx_rmpbc_init(const InteractionDefinitions& idef, PbcType pbcType, int natoms);
+
+gmx_rmpbc_t gmx_rmpbc_init(const t_idef* idef, PbcType pbcType, int natoms);
void gmx_rmpbc_done(gmx_rmpbc_t gpbc);
* boundary conditions such that every molecule is whole.
* natoms is the size x and can be smaller than the number
* of atoms in idef, but should only contain complete molecules.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
+ * When pbcType=PbcType::Unset, the type of pbc is guessed from the box matrix.
*/
void gmx_rmpbc_copy(gmx_rmpbc_t gpbc, int natoms, const matrix box, rvec x[], rvec x_s[]);
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(PbcutilUnitTest pbcutil-test
- pbc.cpp
- pbcenums.cpp
- )
+ CPP_SOURCE_FILES
+ mshift.cpp
+ pbc.cpp
+ pbcenums.cpp
+ )
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for the graph functionality to make molecules whole that are broken over pbc.
+ *
+ * \author berk Hess <hess@kth.se>
+ * \ingroup module_pbcutil
+ */
+#include "gmxpre.h"
+
+#include "gromacs/pbcutil/mshift.h"
+
+#include <gtest/gtest.h>
+
+#include "gromacs/pbcutil/pbc.h"
+#include "gromacs/topology/topology.h"
+
+#include "testutils/testasserts.h"
+#include "testutils/testmatchers.h"
+
+namespace gmx
+{
+namespace test
+{
+namespace
+{
+
+/* TODO: Actually initialize moltype.atoms.atom when this is converted to C++ */
+
+/*! \brief Returns a molectype for generate a graph
+ *
+ * This moleculetype has the first and last atom not connected to the other atoms
+ * so we test optimizations in the shift code that generates the actual graph only
+ * for the atom range from the first to the last connected atoms.
+ */
+gmx_moltype_t moleculeType()
+{
+ gmx_moltype_t moltype = {};
+
+ moltype.atoms.nr = 5;
+ moltype.ilist[F_CONSTR].iatoms = { 0, 1, 2 };
+ moltype.ilist[F_ANGLES].iatoms = { 1, 2, 1, 3 };
+
+ return moltype;
+}
+
+//! Box to go with \p coordinates()
+constexpr matrix c_box = { { 3, 0, 0 }, { 0, 3, 0 }, { 0, 0, 3 } };
+
+/*! \brief Coordinates for \p moleculeType() broken over PBC
+ *
+ * The middle 3 atoms all need to be shifted with respect to each other
+ * to make the molecule whole. The first and last atom are not connected,
+ * so their coordinates are irrelevant for this test.
+ */
+std::vector<RVec> coordinates()
+{
+ std::vector<RVec> x;
+
+ x.emplace_back(-1, 0, 3);
+ x.emplace_back(1.5, 1.5, 4.5);
+ x.emplace_back(1.6, 1.5, 1.5);
+ x.emplace_back(1.6, -1.3, 1.5);
+ x.emplace_back(1, 4, 2);
+
+ return x;
+}
+
+/*! \brief Coordinates for \p moleculeType() made whole
+ *
+ * These coordinates assume the the periodic image for the molecule
+ * is chosen the same as the first connected atom.
+ */
+std::vector<RVec> coordinatesWhole()
+{
+ std::vector<RVec> x;
+
+ x.emplace_back(-1, 0, 3);
+ x.emplace_back(1.5, 1.5, 4.5);
+ x.emplace_back(1.6, 1.5, 4.5);
+ x.emplace_back(1.6, 1.7, 4.5);
+ x.emplace_back(1, 4, 2);
+
+ return x;
+}
+
+//! Tests where (un)shifting works to new coordinate buffers
+TEST(MShift, shiftsAndUnshifts)
+{
+ const gmx_moltype_t molType = moleculeType();
+ const std::vector<RVec> x = coordinates();
+ GMX_RELEASE_ASSERT(int(x.size()) == molType.atoms.nr, "coordinates should match moltype");
+
+ t_graph graph = mk_graph_moltype(molType);
+ mk_mshift(nullptr, &graph, PbcType::Xyz, c_box, as_rvec_array(x.data()));
+
+ std::vector<RVec> xShifted(molType.atoms.nr);
+ shift_x(&graph, c_box, as_rvec_array(x.data()), as_rvec_array(xShifted.data()));
+ EXPECT_THAT(coordinatesWhole(), Pointwise(RVecEq(defaultFloatTolerance()), xShifted));
+
+ std::vector<RVec> xUnshifted(molType.atoms.nr);
+ unshift_x(&graph, c_box, as_rvec_array(xUnshifted.data()), as_rvec_array(xShifted.data()));
+ EXPECT_THAT(x, Pointwise(RVecEq(defaultFloatTolerance()), xUnshifted));
+}
+
+//! Tests where (un)shifting works in place
+TEST(MShift, shiftsAndUnshiftsSelf)
+{
+ const gmx_moltype_t molType = moleculeType();
+ std::vector<RVec> x = coordinates();
+ GMX_RELEASE_ASSERT(int(x.size()) == molType.atoms.nr, "coordinates should match moltype");
+
+ t_graph graph = mk_graph_moltype(molType);
+ mk_mshift(nullptr, &graph, PbcType::Xyz, c_box, as_rvec_array(x.data()));
+
+ shift_self(&graph, c_box, as_rvec_array(x.data()));
+ EXPECT_THAT(coordinatesWhole(), Pointwise(RVecEq(defaultFloatTolerance()), x));
+
+ unshift_self(&graph, c_box, as_rvec_array(x.data()));
+ EXPECT_THAT(coordinates(), Pointwise(RVecEq(defaultFloatTolerance()), x));
+}
+
+} // namespace
+} // namespace test
+} // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
"date prev. COM "
"to bcast here as well as to e.g. checkpointing");
- gmx_bcast(sizeof(dvec), group.x_prev_step, cr);
+ gmx_bcast(sizeof(dvec), group.x_prev_step, cr->mpi_comm_mygroup);
}
}
}
pull->numUnregisteredExternalPotentials = pull->numCoordinatesWithExternalPotential;
pull->numExternalPotentialsStillToBeAppliedThisStep = 0;
- pull->ePBC = ir->ePBC;
- switch (pull->ePBC)
+ pull->pbcType = ir->pbcType;
+ switch (pull->pbcType)
{
- case epbcNONE: pull->npbcdim = 0; break;
- case epbcXY: pull->npbcdim = 2; break;
+ case PbcType::No: pull->npbcdim = 0; break;
+ case PbcType::XY: pull->npbcdim = 2; break;
default: pull->npbcdim = 3; break;
}
if (PAR(cr))
{
/* Only the master rank has the checkpointed COM from the previous step */
- gmx_bcast(sizeof(double) * state->pull_com_prev_step.size(), &state->pull_com_prev_step[0], cr);
+ gmx_bcast(sizeof(double) * state->pull_com_prev_step.size(),
+ &state->pull_com_prev_step[0], cr->mpi_comm_mygroup);
}
setPrevStepPullComFromState(pull_work, state);
}
else
{
t_pbc pbc;
- set_pbc(&pbc, ir->ePBC, state->box);
+ set_pbc(&pbc, ir->pbcType, state->box);
initPullComFromPrevStep(cr, pull_work, md, &pbc, state->x.rvec_array());
updatePrevStepPullCom(pull_work, state);
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#endif
class PullHistory;
+enum class PbcType : int;
enum
{
gmx_bool bConstraint; /* Are there constrained coordinates? */
gmx_bool bAngle; /* Are there angle geometry coordinates? */
- int ePBC; /* the boundary conditions */
+ PbcType pbcType; /* the boundary conditions */
int npbcdim; /* do pbc in dims 0 <= dim < npbcdim */
gmx_bool bRefAt; /* do we need reference atoms for a group COM ? */
int cosdim; /* dimension for cosine weighting, -1 if none */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#if GMX_MPI
if (PAR(cr))
{
- gmx_bcast(sizeof(erg->xc_center), erg->xc_center, cr);
+ gmx_bcast(sizeof(erg->xc_center), erg->xc_center, cr->mpi_comm_mygroup);
}
#endif
}
#if GMX_MPI
if (PAR(cr))
{
- gmx_bcast(erg->rotg->nat * sizeof(erg->xc_old[0]), erg->xc_old, cr);
+ gmx_bcast(erg->rotg->nat * sizeof(erg->xc_old[0]), erg->xc_old, cr->mpi_comm_mygroup);
}
#endif
}
er->restartWithAppending = (startingBehavior == gmx::StartingBehavior::RestartWithAppending);
/* When appending, skip first output to avoid duplicate entries in the data files */
- if (er->restartWithAppending)
- {
- er->bOut = FALSE;
- }
- else
- {
- er->bOut = TRUE;
- }
+ er->bOut = er->restartWithAppending;
if (MASTER(cr) && er->bOut)
{
* When ir->bContinuation=TRUE this has already been done, but ok. */
snew(x_pbc, mtop->natoms);
copy_rvecn(globalState->x.rvec_array(), x_pbc, 0, mtop->natoms);
- do_pbc_first_mtop(nullptr, ir->ePBC, globalState->box, mtop, x_pbc);
+ do_pbc_first_mtop(nullptr, ir->pbcType, globalState->box, mtop, x_pbc);
/* All molecules will be whole now, but not necessarily in the home box.
* Additionally, if a rotation group consists of more than one molecule
* (e.g. two strands of DNA), each one of them can end up in a different
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int pullCheckPbcWithinGroups(const pull_t& pull, const rvec* x, const t_pbc& pbc, real pbcMargin)
{
- if (pbc.ePBC == epbcNONE)
+ if (pbc.pbcType == PbcType::No)
{
return -1;
}
int groupNr,
real pbcMargin)
{
- if (pbc.ePBC == epbcNONE)
+ if (pbc.pbcType == PbcType::No)
{
return true;
}
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016, by the GROMACS development team, led by
+# Copyright (c) 2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(PullTest pull-test
- pull.cpp)
+ CPP_SOURCE_FILES
+ pull.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
protected:
PullTest() {}
- void test(int epbc, matrix box)
+ static void test(PbcType pbcType, matrix box)
{
t_pbc pbc;
// PBC stuff
- set_pbc(&pbc, epbc, box);
+ set_pbc(&pbc, pbcType, box);
GMX_ASSERT(pbc.ndim_ePBC >= 1 && pbc.ndim_ePBC <= DIM,
"Tests only support PBC along at least x and at most x, y, and z");
{
matrix box = { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 0, 10 } };
- test(epbcSCREW, box);
+ test(PbcType::Screw, box);
}
TEST_F(PullTest, MaxPullDistanceXyzCubicBox)
{
matrix box = { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 0, 10 } };
- test(epbcXYZ, box);
+ test(PbcType::Xyz, box);
}
TEST_F(PullTest, MaxPullDistanceXyzTricBox)
{
matrix box = { { 10, 0, 0 }, { 3, 10, 0 }, { 3, 4, 10 } };
- test(epbcXYZ, box);
+ test(PbcType::Xyz, box);
}
TEST_F(PullTest, MaxPullDistanceXyzLongBox)
{
matrix box = { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 0, 30 } };
- test(epbcXYZ, box);
+ test(PbcType::Xyz, box);
}
TEST_F(PullTest, MaxPullDistanceXySkewedBox)
{
matrix box = { { 10, 0, 0 }, { 5, 8, 0 }, { 0, 0, 0 } };
- test(epbcXY, box);
+ test(PbcType::XY, box);
}
} // namespace
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(RandomUnitTests random-test
- exponentialdistribution.cpp
- gammadistribution.cpp
- normaldistribution.cpp
- seed.cpp
- tabulatednormaldistribution.cpp
- threefry.cpp
- uniformintdistribution.cpp
- uniformrealdistribution.cpp
- )
+ CPP_SOURCE_FILES
+ exponentialdistribution.cpp
+ gammadistribution.cpp
+ normaldistribution.cpp
+ seed.cpp
+ tabulatednormaldistribution.cpp
+ threefry.cpp
+ uniformintdistribution.cpp
+ uniformrealdistribution.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
#include <limits>
+#include <type_traits>
#include "gromacs/math/functions.h"
#include "gromacs/utility/basedefinitions.h"
const uint64_t range = Rng::max() - Rng::min() + uint64_t(1);
uint64_t log2R = (range == 0) ? std::numeric_limits<uint64_t>::digits : log2I(range);
uint64_t k = realBits / log2R + (realBits % log2R != 0) + (realBits == 0);
- RealType r = Rng::max() - Rng::min() + RealType(1);
- RealType s = g() - Rng::min();
- RealType base = r;
- RealType result;
+ // Note that Rng::max and Rng::min are typically an integer type.
+ // Only unsigned integer types can express the range using the
+ // same type. Converting to RealType before computing the range
+ // would work but we have no need for that.
+ static_assert(std::is_unsigned<decltype(Rng::max())>::value
+ && std::is_unsigned<decltype(Rng::min())>::value,
+ "Rng::max and Rng::min must be unsigned");
+ RealType r = RealType(Rng::max() - Rng::min()) + RealType(1);
+ RealType s = g() - Rng::min();
+ RealType base = r;
+ RealType result;
for (uint64_t i = 1; i < k; ++i)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
GMX_ASSERT(mdatoms.homenr >= 0, "number of home atoms must be non-negative.");
const auto& box = forceProviderInput.box_;
- GMX_ASSERT(check_box(-1, box) == nullptr, "Invalid box.");
+ GMX_ASSERT(check_box(PbcType::Unset, box) == nullptr, "Invalid box.");
t_pbc pbc{};
- set_pbc(&pbc, -1, box);
+ set_pbc(&pbc, PbcType::Unset, box);
const auto& x = forceProviderInput.x_;
const auto& cr = forceProviderInput.cr_;
{
// Note: this assumes that all ranks are hitting this line, which is not generally true.
// I need to find the right subcommunicator. What I really want is a _scoped_ communicator...
- gmx_barrier(&cr);
+ gmx_barrier(cr.mpi_comm_mygroup);
}
// Apply restraint on all thread ranks only after any updates have been made.
GMX_ASSERT(forceProvider_, "Class invariant implies non-null ForceProvider.");
}
-IMdpOptionProvider* RestraintMDModuleImpl::mdpOptionProvider()
-{
- return nullptr;
-}
-
-IMDOutputProvider* RestraintMDModuleImpl::outputProvider()
-{
- return nullptr;
-}
-
void RestraintMDModuleImpl::initForceProviders(ForceProviders* forceProviders)
{
GMX_ASSERT(forceProvider_, "Class invariant implies non-null ForceProvider member.");
return newModule;
}
+void RestraintMDModule::subscribeToSimulationSetupNotifications(MdModulesNotifier* /*notifier*/) {}
+
+void RestraintMDModule::subscribeToPreProcessingNotifications(MdModulesNotifier* /*notifier*/) {}
+
// private constructor to implement static create() method.
RestraintMDModule::RestraintMDModule(std::unique_ptr<RestraintMDModuleImpl> restraint) :
impl_{ std::move(restraint) }
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// Forward declaration to allow opaque pointer to library internal class.
class RestraintMDModuleImpl;
+struct MdModulesNotifier;
/*! \libinternal \ingroup module_restraint
* \brief MDModule wrapper for Restraint implementations.
*/
void initForceProviders(ForceProviders* forceProviders) override;
+ //! Subscribe to simulation setup notifications
+ void subscribeToSimulationSetupNotifications(MdModulesNotifier* notifier) override;
+ //! Subscribe to pre processing notifications
+ void subscribeToPreProcessingNotifications(MdModulesNotifier* notifier) override;
+
private:
/*!
* \brief Private implementation opaque pointer.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
~RestraintMDModuleImpl();
- /*!
- * \brief Unused implementation of IMDModule aspect
- */
- IMdpOptionProvider* mdpOptionProvider();
-
- /*!
- * \brief Unused implementation of IMDModule aspect
- */
- IMDOutputProvider* outputProvider();
-
/*!
* \brief Implement IMDModule interface.
*
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018, by the GROMACS development team, led by
+# Copyright (c) 2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(RestraintTests restraintpotential-test
- manager.cpp)
+ CPP_SOURCE_FILES
+ manager.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2012,2013,2014,2015, The GROMACS development team.
+# Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
namespace gmx
{
-SelectionCompiler::SelectionCompiler() {}
-
-/*!
- * \param[in,out] coll Selection collection to be compiled.
- * \returns 0 on successful compilation, a non-zero error code on error.
- *
- * Before compilation, the selection collection should have been initialized
- * with gmx_ana_selcollection_parse_*().
- * The compiled selection collection can be passed to
- * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
- * If an error occurs, \p sc is cleared.
- *
- * The covered fraction information in \p sc is initialized to
- * \ref CFRAC_NONE.
- */
-void SelectionCompiler::compile(SelectionCollection* coll)
+void compileSelection(SelectionCollection* coll)
{
gmx_ana_selcollection_t* sc = &coll->impl_->sc_;
gmx_sel_evaluate_t evaldata;
e_poscalc_t post;
size_t i;
int flags;
- bool bDebug = (coll->impl_->debugLevel_ >= 2 && coll->impl_->debugLevel_ != 3);
+ bool bDebug = (coll->impl_->debugLevel_ == SelectionCollection::Impl::DebugLevel::Compiled
+ && coll->impl_->debugLevel_ == SelectionCollection::Impl::DebugLevel::Full);
/* FIXME: Clean up the collection on exceptions */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2013,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2013,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* \brief
* Implements selection compilation.
*
- * This class is used to implement SelectionCollection::compile().
+ * This function is used to implement SelectionCollection::compile().
* It prepares the selections in a selection collection for evaluation and
* performs some optimizations.
*
+ * Before compilation, the selection collection should have been initialized
+ * with gmx_ana_selcollection_parse_*().
+ * The compiled selection collection can be passed to
+ * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
+ * If an error occurs, \p coll is cleared.
+ *
+ * The covered fraction information in \p coll is initialized to
+ * \ref CFRAC_NONE.
+ *
* See \ref page_module_selection_compiler.
*
+ * \param[in, out] coll Selection collection to work on.
+ *
* \ingroup module_selection
*/
-class SelectionCompiler
-{
-public:
- //! Creates a selection compiler.
- SelectionCompiler();
-
- //! Compiles the given selection collection.
- void compile(SelectionCollection* coll);
-};
+void compileSelection(SelectionCollection* coll);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This is the only function that user code should call if they want to
* evaluate a selection for a new frame.
*/
+// NOLINTNEXTLINE readability-convert-member-functions-to-static
void SelectionEvaluator::evaluate(SelectionCollection* coll, t_trxframe* fr, t_pbc* pbc)
{
gmx_ana_selcollection_t* sc = &coll->impl_->sc_;
* \param[in,out] coll The selection collection to evaluate.
* \param[in] nframes Total number of frames.
*/
+// NOLINTNEXTLINE readability-convert-member-functions-to-static
void SelectionEvaluator::evaluateFinal(SelectionCollection* coll, int nframes)
{
gmx_ana_selcollection_t* sc = &coll->impl_->sc_;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2012,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2012,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2014,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/math/functions.h"
#include "gromacs/math/vec.h"
#include "gromacs/pbcutil/pbc.h"
-#include "gromacs/topology/block.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/mutex.h"
#include "gromacs/utility/stringutil.h"
*/
void init(AnalysisNeighborhood::SearchMode mode,
bool bXY,
- const t_blocka* excls,
+ const ListOfLists<int>* excls,
const t_pbc* pbc,
const AnalysisNeighborhoodPositions& positions);
PairSearchImplPointer getPairSearch();
//! Reference position indices (NULL if no indices).
const int* refIndices_;
//! Exclusions.
- const t_blocka* excls_;
+ const ListOfLists<int>* excls_;
//! PBC data.
t_pbc pbc_;
testPositions_ = nullptr;
testExclusionIds_ = nullptr;
testIndices_ = nullptr;
- nexcl_ = 0;
- excl_ = nullptr;
clear_rvec(xtest_);
clear_rvec(testcell_);
clear_ivec(currCell_);
const int* testExclusionIds_;
//! Reference to the test position indices.
const int* testIndices_;
- //! Number of excluded reference positions for current test particle.
- int nexcl_;
//! Exclusions for current test particle.
- const int* excl_;
+ ArrayRef<const int> excl_;
//! Index of the currently active test position in \p testPositions_.
int testIndex_;
//! Stores test position during a pair loop.
// or remove throughout.
GMX_UNUSED_VALUE(bForce);
- switch (pbc.ePBC)
+ switch (pbc.pbcType)
{
- case epbcNONE:
+ case PbcType::No:
bGridPBC_[XX] = false;
bGridPBC_[YY] = false;
bGridPBC_[ZZ] = false;
break;
- case epbcXY:
+ case PbcType::XY:
bGridPBC_[XX] = true;
bGridPBC_[YY] = true;
bGridPBC_[ZZ] = false;
break;
- case epbcXYZ:
+ case PbcType::Xyz:
bGridPBC_[XX] = true;
bGridPBC_[YY] = true;
bGridPBC_[ZZ] = true;
void AnalysisNeighborhoodSearchImpl::init(AnalysisNeighborhood::SearchMode mode,
bool bXY,
- const t_blocka* excls,
+ const ListOfLists<int>* excls,
const t_pbc* pbc,
const AnalysisNeighborhoodPositions& positions)
{
GMX_RELEASE_ASSERT(positions.index_ == -1,
"Individual indexed positions not supported as reference");
bXY_ = bXY;
- if (bXY_ && pbc != nullptr && pbc->ePBC != epbcNONE)
+ if (bXY_ && pbc != nullptr && pbc->pbcType != PbcType::No)
{
- if (pbc->ePBC != epbcXY && pbc->ePBC != epbcXYZ)
+ if (pbc->pbcType != PbcType::XY && pbc->pbcType != PbcType::Xyz)
{
std::string message = formatString(
"Computations in the XY plane are not supported with PBC type '%s'",
- epbc_names[pbc->ePBC]);
+ c_pbcTypeNames[pbc->pbcType].c_str());
GMX_THROW(NotImplementedError(message));
}
- if (pbc->ePBC == epbcXYZ
+ if (pbc->pbcType == PbcType::Xyz
&& (std::fabs(pbc->box[ZZ][XX]) > GMX_REAL_EPS * pbc->box[ZZ][ZZ]
|| std::fabs(pbc->box[ZZ][YY]) > GMX_REAL_EPS * pbc->box[ZZ][ZZ]))
{
matrix box;
copy_mat(pbc->box, box);
clear_rvec(box[ZZ]);
- set_pbc(&pbc_, epbcXY, box);
+ set_pbc(&pbc_, PbcType::XY, box);
}
else if (pbc != nullptr)
{
}
else
{
- pbc_.ePBC = epbcNONE;
+ pbc_.pbcType = PbcType::No;
clear_mat(pbc_.box);
}
nref_ = positions.count_;
if (search_.excls_ != nullptr)
{
const int exclIndex = testExclusionIds_[index];
- if (exclIndex < search_.excls_->nr)
+ if (exclIndex < search_.excls_->ssize())
{
- const int startIndex = search_.excls_->index[exclIndex];
- nexcl_ = search_.excls_->index[exclIndex + 1] - startIndex;
- excl_ = &search_.excls_->a[startIndex];
+ excl_ = (*search_.excls_)[exclIndex];
}
else
{
- nexcl_ = 0;
- excl_ = nullptr;
+ excl_ = ArrayRef<const int>();
}
}
}
bool AnalysisNeighborhoodPairSearchImpl::isExcluded(int j)
{
- if (exclind_ < nexcl_)
+ const int nexcl = excl_.ssize();
+ if (exclind_ < nexcl)
{
const int index = (search_.refIndices_ != nullptr ? search_.refIndices_[j] : j);
const int refId = search_.refExclusionIds_[index];
- while (exclind_ < nexcl_ && excl_[exclind_] < refId)
+ while (exclind_ < nexcl && excl_[exclind_] < refId)
{
++exclind_;
}
- if (exclind_ < nexcl_ && refId == excl_[exclind_])
+ if (exclind_ < nexcl && refId == excl_[exclind_])
{
++exclind_;
return true;
continue;
}
rvec dx;
- if (search_.pbc_.ePBC != epbcNONE)
+ if (search_.pbc_.pbcType != PbcType::No)
{
pbc_dx(&search_.pbc_, search_.xref_[i], xtest_, dx);
}
SearchImplPointer getSearch();
- Mutex createSearchMutex_;
- SearchList searchList_;
- real cutoff_;
- const t_blocka* excls_;
- SearchMode mode_;
- bool bXY_;
+ Mutex createSearchMutex_;
+ SearchList searchList_;
+ real cutoff_;
+ const ListOfLists<int>* excls_;
+ SearchMode mode_;
+ bool bXY_;
};
AnalysisNeighborhood::Impl::SearchImplPointer AnalysisNeighborhood::Impl::getSearch()
impl_->bXY_ = bXY;
}
-void AnalysisNeighborhood::setTopologyExclusions(const t_blocka* excls)
+void AnalysisNeighborhood::setTopologyExclusions(const ListOfLists<int>* excls)
{
GMX_RELEASE_ASSERT(impl_->searchList_.empty(),
"Changing the exclusions after initSearch() not currently supported");
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/real.h"
-struct t_blocka;
struct t_pbc;
namespace gmx
{
+template<typename>
+class ListOfLists;
namespace internal
{
*
* \see AnalysisNeighborhoodPositions::exclusionIds()
*/
- void setTopologyExclusions(const t_blocka* excls);
+ void setTopologyExclusions(const ListOfLists<int>* excls);
/*! \brief
* Sets the algorithm to use for searching.
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
case POS_ATOM: return INDEX_ATOM;
case POS_RES: return INDEX_RES;
case POS_MOL: return INDEX_MOL;
- case POS_ALL: return INDEX_ALL;
+ case POS_ALL: // Intended fall through
case POS_ALL_PBC: return INDEX_ALL;
}
return INDEX_UNKNOWN;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2009-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
switch (method->type)
{
- case INT_VALUE: return METHOD_NUMERIC;
+ case INT_VALUE: // Intended fall through
case REAL_VALUE: return METHOD_NUMERIC;
case POS_VALUE: return METHOD_POS;
case GROUP_VALUE: return METHOD_GROUP;
yylval->sel = new gmx::SelectionTreeElementPointer(var);
switch (var->v.type)
{
- case INT_VALUE: return VARIABLE_NUMERIC;
+ case INT_VALUE: // Intended fall through
case REAL_VALUE: return VARIABLE_NUMERIC;
case POS_VALUE: return VARIABLE_POS;
case GROUP_VALUE: return VARIABLE_GROUP;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* SelectionCollection::Impl
*/
-SelectionCollection::Impl::Impl() : debugLevel_(0), bExternalGroupsSet_(false), grps_(nullptr)
+SelectionCollection::Impl::Impl() :
+ debugLevel_(DebugLevel::None),
+ bExternalGroupsSet_(false),
+ grps_(nullptr)
{
sc_.nvars = 0;
sc_.varstrs = nullptr;
SelectionTopologyProperties
-SelectionCollection::Impl::requiredTopologyPropertiesForPositionType(const std::string& post, bool forces) const
+SelectionCollection::Impl::requiredTopologyPropertiesForPositionType(const std::string& post, bool forces)
{
SelectionTopologyProperties props;
if (!post.empty())
void SelectionCollection::initOptions(IOptionsContainer* options, SelectionTypeOption selectionTypeOption)
{
- const char* const debug_levels[] = { "no", "basic", "compile", "eval", "full" };
+ static const EnumerationArray<Impl::DebugLevel, const char*> s_debugLevelNames = {
+ { "no", "basic", "compile", "eval", "full" }
+ };
const char* const* postypes = PositionCalculationCollection::typeEnumValues;
options->addOption(StringOption("selrpos")
{
impl_->spost_ = postypes[0];
}
- GMX_RELEASE_ASSERT(impl_->debugLevel_ >= 0 && impl_->debugLevel_ <= 4,
- "Debug level out of range");
- options->addOption(EnumIntOption("seldebug")
- .hidden(impl_->debugLevel_ == 0)
- .enumValue(debug_levels)
+ GMX_RELEASE_ASSERT(impl_->debugLevel_ != Impl::DebugLevel::Count, "Debug level out of range");
+ options->addOption(EnumOption<Impl::DebugLevel>("seldebug")
+ .hidden(impl_->debugLevel_ == Impl::DebugLevel::None)
+ .enumValue(s_debugLevelNames)
.store(&impl_->debugLevel_)
.description("Print out selection trees for debugging"));
}
void SelectionCollection::setDebugLevel(int debugLevel)
{
- impl_->debugLevel_ = debugLevel;
+ impl_->debugLevel_ = Impl::DebugLevel(debugLevel);
}
SelectionList SelectionCollection::parseFromStdin(int count, bool bInteractive, const std::string& context)
{
- return parseInteractive(count, &StandardInputStream::instance(),
+ StandardInputStream inputStream;
+ return parseInteractive(count, &inputStream,
bInteractive ? &TextOutputFile::standardError() : nullptr, context);
}
{
setIndexGroups(nullptr);
}
- if (impl_->debugLevel_ >= 1)
+ if (impl_->debugLevel_ != Impl::DebugLevel::None)
{
printTree(stderr, false);
}
- SelectionCompiler compiler;
- compiler.compile(this);
+ compileSelection(this);
- if (impl_->debugLevel_ >= 1)
+ if (impl_->debugLevel_ != Impl::DebugLevel::None)
{
std::fprintf(stderr, "\n");
printTree(stderr, false);
std::fprintf(stderr, "\n");
}
impl_->sc_.pcc.initEvaluation();
- if (impl_->debugLevel_ >= 1)
+ if (impl_->debugLevel_ != Impl::DebugLevel::None)
{
impl_->sc_.pcc.printTree(stderr);
std::fprintf(stderr, "\n");
SelectionEvaluator evaluator;
evaluator.evaluate(this, fr, pbc);
- if (impl_->debugLevel_ >= 3)
+ if (impl_->debugLevel_ == Impl::DebugLevel::Evaluated || impl_->debugLevel_ == Impl::DebugLevel::Full)
{
std::fprintf(stderr, "\n");
printTree(stderr, true);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
PrivateImplPointer<Impl> impl_;
- /*! \brief
- * Needed for the compiler to freely modify the collection.
- */
- friend class SelectionCompiler;
- /*! \brief
- * Needed for the evaluator to freely modify the collection.
- */
+ // Needed for the compiler to freely modify the collection.
+ friend void compileSelection(SelectionCollection* coll);
+ // Needed for the evaluator to freely modify the collection.
friend class SelectionEvaluator;
};
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2009-2016, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief
* Returns topology properties needed for a certain position type.
*/
- SelectionTopologyProperties requiredTopologyPropertiesForPositionType(const std::string& post,
- bool forces) const;
+ static SelectionTopologyProperties requiredTopologyPropertiesForPositionType(const std::string& post,
+ bool forces);
+
+ //! Describes the available debugging levels
+ enum class DebugLevel : int
+ {
+ //! No debugging
+ None,
+ //! Print selection trees after parsing and compilation
+ Basic,
+ //! As PrintCompiled, also print intermediate compilation trees
+ Compiled,
+ //! As PrintCompiled, also print the tree after evaluation
+ Evaluated,
+ //! Combine Compiled and Evaluated
+ Full,
+ //! Ends the enumeration
+ Count
+ };
//! Internal data, used for interfacing with old C code.
gmx_ana_selcollection_t sc_;
std::string spost_;
//! Atoms needed for evaluating the selections.
gmx_ana_index_t requiredAtoms_;
- /*! \brief
- * Debugging level for the collection.
- *
- * Possible values:
- * - 0: no debugging
- * - 1: print selection trees after parsing and compilation
- * - 2: like 1, also print intermediate compilation trees
- * - 3: like 1, also print the tree after evaluation
- * - 4: combine 2 and 3
- */
- int debugLevel_;
+ //! Debugging level for the collection.
+ DebugLevel debugLevel_;
//! Whether setIndexGroups() has been called.
bool bExternalGroupsSet_;
//! External index groups (can be NULL).
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void promptSelections()
{
- const bool isInteractive = StandardInputStream::instance().isInteractive();
+ const bool isInteractive = StandardInputStream::isInteractive();
initIndexGroups();
manager_.parseRequestedFromStdin(isInteractive);
doneIndexGroups();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*! \brief
* Prints markup for starting a list of keywords.
*/
- void writeKeywordListStart(const HelpWriterContext& context, const char* heading) const;
+ static void writeKeywordListStart(const HelpWriterContext& context, const char* heading);
/*! \brief
* Prints markup for ending a list of keywords.
*/
- void writeKeywordListEnd(const HelpWriterContext& context, const char* extraInfo) const;
+ static void writeKeywordListEnd(const HelpWriterContext& context, const char* extraInfo);
/*! \brief
* Prints a brief list of keywords (selection methods) available.
writeKeywordSubTopics(context);
}
-void KeywordsHelpTopic::writeKeywordListStart(const HelpWriterContext& context, const char* heading) const
+void KeywordsHelpTopic::writeKeywordListStart(const HelpWriterContext& context, const char* heading)
{
context.paragraphBreak();
std::string fullHeading("* ");
}
}
-void KeywordsHelpTopic::writeKeywordListEnd(const HelpWriterContext& context, const char* extraInfo) const
+void KeywordsHelpTopic::writeKeywordListEnd(const HelpWriterContext& context, const char* extraInfo)
{
if (context.outputFormat() == eHelpOutputFormat_Rst)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2012,2013,2014,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(SelectionUnitTests selection-test
- indexutil.cpp
- nbsearch.cpp
- poscalc.cpp
- selectioncollection.cpp
- selectionoption.cpp
- toputils.cpp)
+ CPP_SOURCE_FILES
+ indexutil.cpp
+ nbsearch.cpp
+ poscalc.cpp
+ selectioncollection.cpp
+ selectionoption.cpp
+ toputils.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/random/threefry.h"
#include "gromacs/random/uniformrealdistribution.h"
#include "gromacs/topology/block.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
GMX_RELEASE_ASSERT(testPos_.empty(), "Cannot add positions after testPositions() call");
testPositions_.emplace_back(x);
}
- gmx::RVec generateRandomPosition();
- std::vector<int> generateIndex(int count, uint64_t seed) const;
- void generateRandomRefPositions(int count);
- void generateRandomTestPositions(int count);
- void useRefPositionsAsTestPositions();
- void computeReferences(t_pbc* pbc) { computeReferencesInternal(pbc, false); }
- void computeReferencesXY(t_pbc* pbc) { computeReferencesInternal(pbc, true); }
+ gmx::RVec generateRandomPosition();
+ static std::vector<int> generateIndex(int count, uint64_t seed);
+ void generateRandomRefPositions(int count);
+ void generateRandomTestPositions(int count);
+ void useRefPositionsAsTestPositions();
+ void computeReferences(t_pbc* pbc) { computeReferencesInternal(pbc, false); }
+ void computeReferencesXY(t_pbc* pbc) { computeReferencesInternal(pbc, true); }
bool containsPair(int testIndex, const RefPair& pair) const
{
refPosCount_(0)
{
clear_mat(box_);
- set_pbc(&pbc_, epbcNONE, box_);
+ set_pbc(&pbc_, PbcType::No, box_);
}
gmx::RVec NeighborhoodSearchTestData::generateRandomPosition()
return x;
}
-std::vector<int> NeighborhoodSearchTestData::generateIndex(int count, uint64_t seed) const
+std::vector<int> NeighborhoodSearchTestData::generateIndex(int count, uint64_t seed)
{
gmx::DefaultRandomEngine rngIndex(seed);
gmx::UniformRealDistribution<real> dist;
class ExclusionsHelper
{
public:
- static void markExcludedPairs(RefPairList* refPairs, int testIndex, const t_blocka* excls);
+ static void markExcludedPairs(RefPairList* refPairs, int testIndex, const gmx::ListOfLists<int>* excls);
ExclusionsHelper(int refPosCount, int testPosCount);
void generateExclusions();
- const t_blocka* exclusions() const { return &excls_; }
+ const gmx::ListOfLists<int>* exclusions() const { return &excls_; }
gmx::ArrayRef<const int> refPosIds() const
{
}
private:
- int refPosCount_;
- int testPosCount_;
- std::vector<int> exclusionIds_;
- std::vector<int> exclsIndex_;
- std::vector<int> exclsAtoms_;
- t_blocka excls_;
+ int refPosCount_;
+ int testPosCount_;
+ std::vector<int> exclusionIds_;
+ gmx::ListOfLists<int> excls_;
};
// static
-void ExclusionsHelper::markExcludedPairs(RefPairList* refPairs, int testIndex, const t_blocka* excls)
+void ExclusionsHelper::markExcludedPairs(RefPairList* refPairs, int testIndex, const gmx::ListOfLists<int>* excls)
{
int count = 0;
- for (int i = excls->index[testIndex]; i < excls->index[testIndex + 1]; ++i)
+ for (const int excludedIndex : (*excls)[testIndex])
{
- const int excludedIndex = excls->a[i];
NeighborhoodSearchTestData::RefPair searchPair(excludedIndex, 0.0);
RefPairList::iterator excludedRefPair =
std::lower_bound(refPairs->begin(), refPairs->end(), searchPair);
exclusionIds_.resize(std::max(refPosCount, testPosCount), 1);
exclusionIds_[0] = 0;
std::partial_sum(exclusionIds_.begin(), exclusionIds_.end(), exclusionIds_.begin());
-
- excls_.nr = 0;
- excls_.index = nullptr;
- excls_.nra = 0;
- excls_.a = nullptr;
- excls_.nalloc_index = 0;
- excls_.nalloc_a = 0;
}
void ExclusionsHelper::generateExclusions()
// particles would be higher, or where the exclusions would not be random,
// to make a higher percentage of the exclusions to actually be within the
// cutoff.
- exclsIndex_.reserve(testPosCount_ + 1);
- exclsAtoms_.reserve(testPosCount_ * 20);
- exclsIndex_.push_back(0);
for (int i = 0; i < testPosCount_; ++i)
{
+ excls_.pushBackListOfSize(20);
+ gmx::ArrayRef<int> exclusionsForAtom = excls_.back();
for (int j = 0; j < 20; ++j)
{
- exclsAtoms_.push_back(i + j * 3);
+ exclusionsForAtom[j] = i + j * 3;
}
- exclsIndex_.push_back(exclsAtoms_.size());
}
- excls_.nr = exclsIndex_.size();
- excls_.index = exclsIndex_.data();
- excls_.nra = exclsAtoms_.size();
- excls_.a = exclsAtoms_.data();
}
/********************************************************************
class NeighborhoodSearchTest : public ::testing::Test
{
public:
- void testIsWithin(gmx::AnalysisNeighborhoodSearch* search, const NeighborhoodSearchTestData& data);
- void testMinimumDistance(gmx::AnalysisNeighborhoodSearch* search,
+ static void testIsWithin(gmx::AnalysisNeighborhoodSearch* search,
const NeighborhoodSearchTestData& data);
- void testNearestPoint(gmx::AnalysisNeighborhoodSearch* search, const NeighborhoodSearchTestData& data);
- void testPairSearch(gmx::AnalysisNeighborhoodSearch* search, const NeighborhoodSearchTestData& data);
- void testPairSearchIndexed(gmx::AnalysisNeighborhood* nb,
- const NeighborhoodSearchTestData& data,
- uint64_t seed);
- void testPairSearchFull(gmx::AnalysisNeighborhoodSearch* search,
- const NeighborhoodSearchTestData& data,
- const gmx::AnalysisNeighborhoodPositions& pos,
- const t_blocka* excls,
- const gmx::ArrayRef<const int>& refIndices,
- const gmx::ArrayRef<const int>& testIndices,
- bool selfPairs);
+ static void testMinimumDistance(gmx::AnalysisNeighborhoodSearch* search,
+ const NeighborhoodSearchTestData& data);
+ static void testNearestPoint(gmx::AnalysisNeighborhoodSearch* search,
+ const NeighborhoodSearchTestData& data);
+ static void testPairSearch(gmx::AnalysisNeighborhoodSearch* search,
+ const NeighborhoodSearchTestData& data);
+ static void testPairSearchIndexed(gmx::AnalysisNeighborhood* nb,
+ const NeighborhoodSearchTestData& data,
+ uint64_t seed);
+ static void testPairSearchFull(gmx::AnalysisNeighborhoodSearch* search,
+ const NeighborhoodSearchTestData& data,
+ const gmx::AnalysisNeighborhoodPositions& pos,
+ const gmx::ListOfLists<int>* excls,
+ const gmx::ArrayRef<const int>& refIndices,
+ const gmx::ArrayRef<const int>& testIndices,
+ bool selfPairs);
gmx::AnalysisNeighborhood nb_;
};
void NeighborhoodSearchTest::testPairSearchFull(gmx::AnalysisNeighborhoodSearch* search,
const NeighborhoodSearchTestData& data,
const gmx::AnalysisNeighborhoodPositions& pos,
- const t_blocka* excls,
+ const gmx::ListOfLists<int>* excls,
const gmx::ArrayRef<const int>& refIndices,
const gmx::ArrayRef<const int>& testIndices,
bool selfPairs)
data_.box_[ZZ][ZZ] = 3.0;
data_.generateRandomRefPositions(10);
data_.generateRandomTestPositions(5);
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferences(&data_.pbc_);
}
data_.box_[ZZ][ZZ] = 3.0;
data_.generateRandomRefPositions(20);
data_.useRefPositionsAsTestPositions();
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferences(&data_.pbc_);
}
// test coverage.
data_.generateRandomRefPositions(1000);
data_.generateRandomTestPositions(100);
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferences(&data_.pbc_);
}
data_.box_[ZZ][ZZ] = 7.0;
data_.generateRandomRefPositions(1000);
data_.useRefPositionsAsTestPositions();
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferences(&data_.pbc_);
}
// test coverage.
data_.generateRandomRefPositions(1000);
data_.generateRandomTestPositions(100);
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferencesXY(&data_.pbc_);
}
// test coverage.
data_.generateRandomRefPositions(1000);
data_.generateRandomTestPositions(100);
- set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::Xyz, data_.box_);
data_.computeReferences(&data_.pbc_);
}
// test coverage.
data_.generateRandomRefPositions(1000);
data_.generateRandomTestPositions(100);
- set_pbc(&data_.pbc_, epbcXY, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::XY, data_.box_);
data_.computeReferences(&data_.pbc_);
}
// test coverage.
data_.generateRandomRefPositions(1000);
data_.generateRandomTestPositions(100);
- set_pbc(&data_.pbc_, epbcNONE, data_.box_);
+ set_pbc(&data_.pbc_, PbcType::No, data_.box_);
data_.computeReferences(nullptr);
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
typedef std::vector<PositionTest> PositionTestList;
- void setTopologyIfRequired();
- void checkPositions(gmx::test::TestReferenceChecker* checker, const char* name, gmx_ana_pos_t* p, bool bCoordinates);
+ void setTopologyIfRequired();
+ static void checkPositions(gmx::test::TestReferenceChecker* checker,
+ const char* name,
+ gmx_ana_pos_t* p,
+ bool bCoordinates);
std::vector<gmx_ana_poscalc_t*> pcList_;
PositionTestList posList_;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void TopologyManager::loadTopology(const char* filename)
{
- bool fullTopology;
- int ePBC;
- rvec* xtop = nullptr;
- matrix box;
+ bool fullTopology;
+ PbcType pbcType;
+ rvec* xtop = nullptr;
+ matrix box;
GMX_RELEASE_ASSERT(mtop_ == nullptr, "Topology initialized more than once");
mtop_ = std::make_unique<gmx_mtop_t>();
readConfAndTopology(gmx::test::TestFileManager::getInputFilePath(filename).c_str(), &fullTopology,
- mtop_.get(), &ePBC, frame_ != nullptr ? &xtop : nullptr, nullptr, box);
+ mtop_.get(), &pbcType, frame_ != nullptr ? &xtop : nullptr, nullptr, box);
if (frame_ != nullptr)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2015,2016,2017,2018, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017,2018,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(SimdUnitTests simd-test
- bootstrap_loadstore.cpp
- base.cpp
- simd.cpp
- simd_floatingpoint.cpp
- simd_floatingpoint_util.cpp
- simd_vector_operations.cpp
- simd_math.cpp
- simd_memory.cpp
- simd_integer.cpp
- simd4.cpp
- simd4_floatingpoint.cpp
- simd4_vector_operations.cpp
- simd4_math.cpp
- scalar.cpp
- scalar_util.cpp
- scalar_math.cpp)
+ CPP_SOURCE_FILES
+ base.cpp
+ bootstrap_loadstore.cpp
+ scalar.cpp
+ scalar_util.cpp
+ scalar_math.cpp
+ simd.cpp
+ simd_floatingpoint.cpp
+ simd_floatingpoint_util.cpp
+ simd_integer.cpp
+ simd_math.cpp
+ simd_memory.cpp
+ simd_vector_operations.cpp
+ simd4.cpp
+ simd4_floatingpoint.cpp
+ simd4_math.cpp
+ simd4_vector_operations.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2.0), cvtI2R(SimdInt32(2)));
GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2.0), cvtI2R(SimdInt32(-2)));
- GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(102448689), cvtI2R(SimdInt32(102448689)));
- GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-102448689), cvtI2R(SimdInt32(-102448689)));
+ GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(102448689._real), cvtI2R(SimdInt32(102448689)));
+ GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-102448689._real), cvtI2R(SimdInt32(-102448689)));
}
# endif // GMX_SIMD_HAVE_REAL
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* to avoid altering any value the user has set on the command line; since
* it's a static member, changing it would have permanent effect.
*/
- std::vector<real> generateTestPoints(Range range, std::size_t points);
+ static std::vector<real> generateTestPoints(Range range, std::size_t points);
/*! \brief Test routine for the test point vector generation
*/
- void generateTestPointsTest();
+ static void generateTestPointsTest();
};
/*! \brief Test approximate equality of SIMD vs reference version of a function.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
IMdpOptionProvider* mdpOptionProvider() override { return nullptr; }
IMDOutputProvider* outputProvider() override { return nullptr; }
void initForceProviders(ForceProviders* /* forceProviders */) override {}
+ void subscribeToSimulationSetupNotifications(MdModulesNotifier* /* notifier */) override {}
+ void subscribeToPreProcessingNotifications(MdModulesNotifier* /* notifier */) override {}
};
std::unique_ptr<IMDModule> createSwapCoordinatesModule()
for (ic = 0; ic < eCompNR; ic++)
{
- gmx_bcast(sizeof(g->comp[ic].nMolReq), &(g->comp[ic].nMolReq), cr);
- gmx_bcast(sizeof(g->comp[ic].nMol), &(g->comp[ic].nMol), cr);
- gmx_bcast(swap->nAverage * sizeof(g->comp[ic].nMolPast[0]), g->comp[ic].nMolPast, cr);
+ gmx_bcast(sizeof(g->comp[ic].nMolReq), &(g->comp[ic].nMolReq), cr->mpi_comm_mygroup);
+ gmx_bcast(sizeof(g->comp[ic].nMol), &(g->comp[ic].nMol), cr->mpi_comm_mygroup);
+ gmx_bcast(swap->nAverage * sizeof(g->comp[ic].nMolPast[0]), g->comp[ic].nMolPast,
+ cr->mpi_comm_mygroup);
}
}
}
* If this is not correct, the ion counts per channel will be very likely
* wrong.
*/
-static void outputStartStructureIfWanted(gmx_mtop_t* mtop, rvec* x, int ePBC, const matrix box)
+static void outputStartStructureIfWanted(gmx_mtop_t* mtop, rvec* x, PbcType pbcType, const matrix box)
{
char* env = getenv("GMX_COMPELDUMP");
SwS, SwSEmpty);
write_sto_conf_mtop("CompELAssumedWholeConfiguration.pdb", *mtop->name, mtop, x, nullptr,
- ePBC, box);
+ pbcType, box);
}
}
copy_rvecn(x, x_pbc, 0, mtop->natoms);
/* This can only make individual molecules whole, not multimers */
- do_pbc_mtop(ir->ePBC, box, mtop, x_pbc);
+ do_pbc_mtop(ir->pbcType, box, mtop, x_pbc);
/* Output the starting structure? */
- outputStartStructureIfWanted(mtop, x_pbc, ir->ePBC, box);
+ outputStartStructureIfWanted(mtop, x_pbc, ir->pbcType, box);
/* If this is the first run (i.e. no checkpoint present) we assume
* that the starting positions give us the correct PBC representation */
for (int ig = eGrpSplit0; ig <= eGrpSplit1; ig++)
{
g = &(s->group[ig]);
- gmx_bcast((g->atomset.numAtomsGlobal()) * sizeof((g->xc_old)[0]), g->xc_old, (cr));
+ gmx_bcast((g->atomset.numAtomsGlobal()) * sizeof((g->xc_old)[0]), g->xc_old,
+ cr->mpi_comm_mygroup);
}
}
sc = ir->swap;
- set_pbc(s->pbc, ir->ePBC, box);
+ set_pbc(s->pbc, ir->pbcType, box);
/* Assemble the positions of the split groups, i.e. the channels.
* Here we also pass a shifts array to communicate_group_positions(), so that it can make
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/fileio/xvgr.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/multidimarray.h"
#include "gromacs/math/units.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
+#include "gromacs/mdspan/extensions.h"
#include "gromacs/mdtypes/fcdata.h"
+#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/mdtypes/nblist.h"
#include "gromacs/utility/arrayref.h"
etabLJ6Switch,
etabLJ12Switch,
etabCOULSwitch,
- etabLJ6Encad,
- etabLJ12Encad,
- etabCOULEncad,
etabEXPMIN,
etabUSER,
etabNR
/* This structure holds name and a flag that tells whether
this is a Coulomb type funtion */
static const t_tab_props tprops[etabNR] = {
- { "LJ6", FALSE },
- { "LJ12", FALSE },
- { "LJ6Shift", FALSE },
- { "LJ12Shift", FALSE },
- { "Shift", TRUE },
- { "RF", TRUE },
- { "RF-zero", TRUE },
- { "COUL", TRUE },
- { "Ewald", TRUE },
- { "Ewald-Switch", TRUE },
- { "Ewald-User", TRUE },
- { "Ewald-User-Switch", TRUE },
- { "LJ6Ewald", FALSE },
- { "LJ6Switch", FALSE },
- { "LJ12Switch", FALSE },
- { "COULSwitch", TRUE },
- { "LJ6-Encad shift", FALSE },
- { "LJ12-Encad shift", FALSE },
- { "COUL-Encad shift", TRUE },
- { "EXPMIN", FALSE },
- { "USER", FALSE },
+ { "LJ6", FALSE }, { "LJ12", FALSE }, { "LJ6Shift", FALSE },
+ { "LJ12Shift", FALSE }, { "Shift", TRUE }, { "RF", TRUE },
+ { "RF-zero", TRUE }, { "COUL", TRUE }, { "Ewald", TRUE },
+ { "Ewald-Switch", TRUE }, { "Ewald-User", TRUE }, { "Ewald-User-Switch", TRUE },
+ { "LJ6Ewald", FALSE }, { "LJ6Switch", FALSE }, { "LJ12Switch", FALSE },
+ { "COULSwitch", TRUE }, { "EXPMIN", FALSE }, { "USER", FALSE },
};
typedef struct
static void read_tables(FILE* fp, const char* filename, int ntab, int angle, t_tabledata td[])
{
char buf[STRLEN];
- double **yy = nullptr, start, end, dx0, dx1, ssd, vm, vp, f, numf;
- int k, i, nx, nx0 = 0, ny, nny, ns;
+ double start, end, dx0, dx1, ssd, vm, vp, f, numf;
+ int k, i, nx0 = 0, nny, ns;
gmx_bool bAllZero, bZeroV, bZeroF;
double tabscale;
nny = 2 * ntab + 1;
std::string libfn = gmx::findLibraryFile(filename);
- nx = read_xvg(libfn.c_str(), &yy, &ny);
- if (ny != nny)
+ gmx::MultiDimArray<std::vector<double>, gmx::dynamicExtents2D> xvgData = readXvgData(libfn);
+ int numColumns = xvgData.extent(0);
+ if (numColumns != nny)
{
gmx_fatal(FARGS, "Trying to read file %s, but nr columns = %d, should be %d", libfn.c_str(),
- ny, nny);
+ numColumns, nny);
}
+ int numRows = xvgData.extent(1);
+
+ const auto& yy = xvgData.asView();
if (angle == 0)
{
if (yy[0][0] != 0.0)
start = -180.0;
}
end = 180.0;
- if (yy[0][0] != start || yy[0][nx - 1] != end)
+ if (yy[0][0] != start || yy[0][numRows - 1] != end)
{
gmx_fatal(FARGS, "The angles in file %s should go from %f to %f instead of %f to %f\n",
- libfn.c_str(), start, end, yy[0][0], yy[0][nx - 1]);
+ libfn.c_str(), start, end, yy[0][0], yy[0][numRows - 1]);
}
}
- tabscale = (nx - 1) / (yy[0][nx - 1] - yy[0][0]);
+ tabscale = (numRows - 1) / (yy[0][numRows - 1] - yy[0][0]);
if (fp)
{
- fprintf(fp, "Read user tables from %s with %d data points.\n", libfn.c_str(), nx);
+ fprintf(fp, "Read user tables from %s with %d data points.\n", libfn.c_str(), numRows);
if (angle == 0)
{
fprintf(fp, "Tabscale = %g points/nm\n", tabscale);
{
bZeroV = TRUE;
bZeroF = TRUE;
- for (i = 0; (i < nx); i++)
+ for (i = 0; (i < numRows); i++)
{
if (i >= 2)
{
if (!bZeroV && bZeroF)
{
- set_forces(fp, angle, nx, 1 / tabscale, yy[1 + k * 2], yy[1 + k * 2 + 1], k);
+ set_forces(fp, angle, numRows, 1 / tabscale, yy[1 + k * 2].data(),
+ yy[1 + k * 2 + 1].data(), k);
}
else
{
*/
ssd = 0;
ns = 0;
- for (i = 1; (i < nx - 1); i++)
+ for (i = 1; (i < numRows - 1); i++)
{
vm = yy[1 + 2 * k][i - 1];
vp = yy[1 + 2 * k][i + 1];
for (k = 0; (k < ntab); k++)
{
- init_table(nx, nx0, tabscale, &(td[k]), TRUE);
- for (i = 0; (i < nx); i++)
+ init_table(numRows, nx0, tabscale, &(td[k]), TRUE);
+ for (i = 0; (i < numRows); i++)
{
td[k].x[i] = yy[0][i];
td[k].v[i] = yy[2 * k + 1][i];
td[k].f[i] = yy[2 * k + 2][i];
}
}
- for (i = 0; (i < ny); i++)
- {
- sfree(yy[i]);
- }
- sfree(yy);
}
static void done_tabledata(t_tabledata* td)
int i;
double reppow, p;
double r1, rc, r12, r13;
- double r, r2, r6, rc2, rc6, rc12;
+ double r, r2, r6, rc2;
double expr, Vtab, Ftab;
/* Parameters for David's function */
double A = 0, B = 0, C = 0, A_3 = 0, B_4 = 0;
if (bPotentialShift)
{
- rc2 = rc * rc;
- rc6 = 1.0 / (rc2 * rc2 * rc2);
+ rc2 = rc * rc;
+ double rc6 = 1.0 / (rc2 * rc2 * rc2);
+ double rc12;
if (gmx_within_tol(reppow, 12.0, 10 * GMX_DOUBLE_EPS))
{
rc12 = rc6 * rc6;
swi1 = 0.0;
}
- rc6 = rc * rc * rc;
- rc6 = 1.0 / (rc6 * rc6);
-
switch (tp)
{
case etabLJ6:
Ftab = reppow * Vtab / r;
}
break;
- case etabLJ6Encad:
- if (r < rc)
- {
- Vtab = -(r6 - 6.0 * (rc - r) * rc6 / rc - rc6);
- Ftab = -(6.0 * r6 / r - 6.0 * rc6 / rc);
- }
- else /* r>rc */
- {
- Vtab = 0;
- Ftab = 0;
- }
- break;
- case etabLJ12Encad:
- if (r < rc)
- {
- Vtab = -(r6 - 6.0 * (rc - r) * rc6 / rc - rc6);
- Ftab = -(6.0 * r6 / r - 6.0 * rc6 / rc);
- }
- else /* r>rc */
- {
- Vtab = 0;
- Ftab = 0;
- }
- break;
case etabCOUL:
Vtab = 1.0 / r;
Ftab = 1.0 / r2;
Vtab = expr;
Ftab = expr;
break;
- case etabCOULEncad:
- if (r < rc)
- {
- Vtab = 1.0 / r - (rc - r) / (rc * rc) - 1.0 / rc;
- Ftab = 1.0 / r2 - 1.0 / (rc * rc);
- }
- else /* r>rc */
- {
- Vtab = 0;
- Ftab = 0;
- }
- break;
default:
gmx_fatal(FARGS, "Table type %d not implemented yet. (%s,%d)", tp, __FILE__, __LINE__);
}
case eelRF_ZERO: tabsel[etiCOUL] = etabRF_ZERO; break;
case eelSWITCH: tabsel[etiCOUL] = etabCOULSwitch; break;
case eelUSER: tabsel[etiCOUL] = etabUSER; break;
- case eelENCADSHIFT: tabsel[etiCOUL] = etabCOULEncad; break;
default: gmx_fatal(FARGS, "Invalid eeltype %d", eltype);
}
tabsel[etiLJ6] = etabLJ6;
tabsel[etiLJ12] = etabLJ12;
break;
- case evdwENCADSHIFT:
- tabsel[etiLJ6] = etabLJ6Encad;
- tabsel[etiLJ12] = etabLJ12Encad;
- break;
case evdwPME:
tabsel[etiLJ6] = etabLJ6Ewald;
tabsel[etiLJ12] = etabLJ12;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <memory>
-#include "gromacs/mdtypes/fcdata.h"
-#include "gromacs/mdtypes/forcerec.h"
-#include "gromacs/mdtypes/interaction_const.h"
#include "gromacs/utility/real.h"
+struct EwaldCorrectionTables;
+struct bondedtable_t;
+struct interaction_const_t;
+struct t_forcetable;
+
/*! \brief Flag to select user tables for make_tables */
#define GMX_MAKETABLES_FORCEUSER (1 << 0)
/*! \brief Flag to only make 1,4 pair tables for make_tables */
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2016, by the GROMACS development team, led by
+# Copyright (c) 2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(TableUnitTests table-test
- splinetable.cpp
- )
+ CPP_SOURCE_FILES
+ splinetable.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+ * Copyright (c) 2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/hardware/hardwaretopology.h"
#include "gromacs/hardware/hw_info.h"
#include "gromacs/mdlib/gmx_omp_nthreads.h"
-#include "gromacs/mdlib/update_constrain_cuda.h"
+#include "gromacs/mdlib/update_constrain_gpu.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/inputrec.h"
#include "gromacs/mdtypes/md_enums.h"
// The graph is needed, but not supported
errorMessage += "Orientation restraints are not supported.\n";
}
- if (inputrec.efep != efepNO)
+ if (inputrec.efep != efepNO
+ && (haveFreeEnergyType(inputrec, efptBONDED) || haveFreeEnergyType(inputrec, efptMASS)))
{
- // Actually all free-energy options except for mass and constraint perturbation are supported
- errorMessage += "Free energy perturbations are not supported.\n";
+ errorMessage += "Free energy perturbation for mass and constraints are not supported.\n";
}
const auto particleTypes = gmx_mtop_particletype_count(mtop);
if (particleTypes[eptShell] > 0)
{
errorMessage += "Non-connecting constraints are not supported";
}
- if (!UpdateConstrainCuda::isNumCoupledConstraintsSupported(mtop))
+ if (!UpdateConstrainGpu::isNumCoupledConstraintsSupported(mtop))
{
errorMessage +=
- "The number of coupled constraints is higher than supported in the CUDA LINCS "
+ "The number of coupled constraints is higher than supported in the GPU LINCS "
"code.\n";
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
namespace gmx
{
-SimulationWorkload createSimulationWorkload(bool useGpuForNonbonded,
- PmeRunMode pmeRunMode,
- bool useGpuForBonded,
- bool useGpuForUpdate,
- bool useGpuForBufferOps,
- bool useGpuHaloExchange,
- bool useGpuPmePpComm,
- bool haveEwaldSurfaceContribution)
+SimulationWorkload createSimulationWorkload(const t_inputrec& inputrec,
+ bool useGpuForNonbonded,
+ PmeRunMode pmeRunMode,
+ bool useGpuForBonded,
+ bool useGpuForUpdate,
+ bool useGpuForBufferOps,
+ bool useGpuHaloExchange,
+ bool useGpuPmePpComm)
{
SimulationWorkload simulationWorkload;
+ simulationWorkload.computeMuTot = inputrecNeedMutot(&inputrec);
simulationWorkload.useCpuNonbonded = !useGpuForNonbonded;
simulationWorkload.useGpuNonbonded = useGpuForNonbonded;
simulationWorkload.useCpuPme = (pmeRunMode == PmeRunMode::CPU);
simulationWorkload.useGpuHaloExchange = useGpuHaloExchange;
simulationWorkload.useGpuPmePpCommunication = useGpuPmePpComm && (pmeRunMode == PmeRunMode::GPU);
simulationWorkload.useGpuDirectCommunication = useGpuHaloExchange || useGpuPmePpComm;
- simulationWorkload.haveEwaldSurfaceContribution = haveEwaldSurfaceContribution;
+ simulationWorkload.haveEwaldSurfaceContribution = haveEwaldSurfaceContribution(inputrec);
return simulationWorkload;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Build datastructure that contains decisions whether to run different workload
* task on GPUs.
*
+ * \param[in] inputrec The input record
* \param[in] useGpuForNonbonded Whether we have short-range nonbonded interactions
* calculations on GPU(s).
* \param[in] pmeRunMode Run mode indicating what resource is PME execured on.
* \param[in] useGpuForBufferOps Whether buffer ops / reduction are calculated on GPU(s).
* \param[in] useGpuHaloExchange Whether GPU direct communication is used in halo exchange.
* \param[in] useGpuPmePpComm Whether GPU direct communication is used in PME-PP communication.
- * \param[in] haveEwaldSurfaceContribution Whether there is an Ewald surface contribution
* \returns Simulation lifetime constant workload description.
*/
-SimulationWorkload createSimulationWorkload(bool useGpuForNonbonded,
- PmeRunMode pmeRunMode,
- bool useGpuForBonded,
- bool useGpuForUpdate,
- bool useGpuForBufferOps,
- bool useGpuHaloExchange,
- bool useGpuPmePpComm,
- bool haveEwaldSurfaceContribution);
+SimulationWorkload createSimulationWorkload(const t_inputrec& inputrec,
+ bool useGpuForNonbonded,
+ PmeRunMode pmeRunMode,
+ bool useGpuForBonded,
+ bool useGpuForUpdate,
+ bool useGpuForBufferOps,
+ bool useGpuHaloExchange,
+ bool useGpuPmePpComm);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstring>
#include <algorithm>
+#include <array>
#include "gromacs/ewald/pme.h"
#include "gromacs/hardware/cpuinfo.h"
#if GMX_OPENMP && GMX_MPI
GMX_UNUSED_VALUE(hwinfo);
- int nth_omp_min, nth_omp_max;
+ int nth_omp_max;
char buf[1000];
const char* mpi_option = GMX_THREAD_MPI ? " (option -ntmpi)" : "";
GMX_RELEASE_ASSERT(gmx_omp_nthreads_get(emntDefault) >= 1,
"Must have at least one OpenMP thread");
- nth_omp_min = gmx_omp_nthreads_get(emntDefault);
nth_omp_max = gmx_omp_nthreads_get(emntDefault);
bool anyRankIsUsingGpus = willUsePhysicalGpu;
/* Thread-MPI seems to have a bug with reduce on 1 node, so use a cond. */
if (cr->nnodes > 1)
{
- int count[3], count_max[3];
+ std::array<int, 2> count, count_max;
- count[0] = -nth_omp_min;
- count[1] = nth_omp_max;
- count[2] = int(willUsePhysicalGpu);
+ count[0] = nth_omp_max;
+ count[1] = int(willUsePhysicalGpu);
- MPI_Allreduce(count, count_max, 3, MPI_INT, MPI_MAX, cr->mpi_comm_mysim);
+ MPI_Allreduce(count.data(), count_max.data(), count.size(), MPI_INT, MPI_MAX, cr->mpi_comm_mysim);
/* In case of an inhomogeneous run setup we use the maximum counts */
- nth_omp_min = -count_max[0];
- nth_omp_max = count_max[1];
- anyRankIsUsingGpus = count_max[2] > 0;
+ nth_omp_max = count_max[0];
+ anyRankIsUsingGpus = count_max[1] > 0;
}
int nthreads_omp_mpi_ok_min;
numRanksOnThisNode_, printHostName, useGpuForBonded, pmeRunMode, useGpuForUpdate);
}
-gmx_device_info_t* GpuTaskAssignments::initNonbondedDevice(const t_commrec* cr) const
+/*! \brief Function for whether the task of \c mapping has value \c TaskType.
+ *
+ * \param[in] mapping Current GPU task mapping.
+ * \returns If \c TaskType task was assigned to the \c mapping.
+ */
+template<GpuTask TaskType>
+static bool hasTaskType(const GpuTaskMapping& mapping)
{
- gmx_device_info_t* deviceInfo = nullptr;
- const GpuTaskAssignment& gpuTaskAssignment = assignmentForAllRanksOnThisNode_[indexOfThisRank_];
-
- // This works because only one task of each type per rank is currently permitted.
- auto nbGpuTaskMapping = std::find_if(gpuTaskAssignment.begin(), gpuTaskAssignment.end(),
- hasTaskType<GpuTask::Nonbonded>);
- if (nbGpuTaskMapping != gpuTaskAssignment.end())
- {
- int deviceId = nbGpuTaskMapping->deviceId_;
- deviceInfo = getDeviceInfo(hardwareInfo_.gpu_info, deviceId);
- init_gpu(deviceInfo);
+ return mapping.task_ == TaskType;
+}
- // TODO Setting up this sharing should probably part of
- // init_domain_decomposition after further refactoring.
- if (DOMAINDECOMP(cr))
- {
- /* When we share GPUs over ranks, we need to know this for the DLB */
- dd_setup_dlb_resource_sharing(cr, deviceId);
- }
- }
- return deviceInfo;
+/*! \brief Function for whether the \c mapping has the GPU PME or Nonbonded task.
+ *
+ * \param[in] mapping Current GPU task mapping.
+ * \returns If PME on Nonbonded GPU task was assigned to this mapping.
+ */
+static bool hasPmeOrNonbondedTask(const GpuTaskMapping& mapping)
+{
+ return hasTaskType<GpuTask::Pme>(mapping) || hasTaskType<GpuTask::Nonbonded>(mapping);
}
-gmx_device_info_t* GpuTaskAssignments::initPmeDevice() const
+DeviceInformation* GpuTaskAssignments::initDevice(int* deviceId) const
{
- gmx_device_info_t* deviceInfo = nullptr;
+ DeviceInformation* deviceInfo = nullptr;
const GpuTaskAssignment& gpuTaskAssignment = assignmentForAllRanksOnThisNode_[indexOfThisRank_];
- // This works because only one task of each type is currently permitted.
- auto pmeGpuTaskMapping = std::find_if(gpuTaskAssignment.begin(), gpuTaskAssignment.end(),
- hasTaskType<GpuTask::Pme>);
- const bool thisRankHasPmeGpuTask = (pmeGpuTaskMapping != gpuTaskAssignment.end());
- if (thisRankHasPmeGpuTask)
+ // This works because only one task of each type per rank is currently permitted.
+ auto gpuTaskMapping =
+ std::find_if(gpuTaskAssignment.begin(), gpuTaskAssignment.end(), hasPmeOrNonbondedTask);
+
+ if (gpuTaskMapping != gpuTaskAssignment.end())
{
- deviceInfo = getDeviceInfo(hardwareInfo_.gpu_info, pmeGpuTaskMapping->deviceId_);
+ *deviceId = gpuTaskMapping->deviceId_;
+ deviceInfo = getDeviceInfo(hardwareInfo_.gpu_info, *deviceId);
init_gpu(deviceInfo);
}
return deviceInfo;
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/gmxmpi.h"
-struct gmx_device_info_t;
+struct DeviceInformation;
struct gmx_hw_info_t;
struct t_commrec;
* \throws std::bad_alloc If out of memory.
* InconsistentInputError If user and/or detected inputs are inconsistent.
*/
- GpuTaskAssignments build(const std::vector<int>& gpuIdsToUse,
- const std::vector<int>& userGpuTaskAssignment,
- const gmx_hw_info_t& hardwareInfo,
- MPI_Comm gromacsWorldComm,
- const PhysicalNodeCommunicator& physicalNodeComm,
- TaskTarget nonbondedTarget,
- TaskTarget pmeTarget,
- TaskTarget bondedTarget,
- TaskTarget updateTarget,
- bool useGpuForNonbonded,
- bool useGpuForPme,
- bool rankHasPpTask,
- bool rankHasPmeTask);
+ static GpuTaskAssignments build(const std::vector<int>& gpuIdsToUse,
+ const std::vector<int>& userGpuTaskAssignment,
+ const gmx_hw_info_t& hardwareInfo,
+ MPI_Comm gromacsWorldComm,
+ const PhysicalNodeCommunicator& physicalNodeComm,
+ TaskTarget nonbondedTarget,
+ TaskTarget pmeTarget,
+ TaskTarget bondedTarget,
+ TaskTarget updateTarget,
+ bool useGpuForNonbonded,
+ bool useGpuForPme,
+ bool rankHasPpTask,
+ bool rankHasPmeTask);
};
/*! \libinternal
* \param[in] numCompatibleGpusOnThisNode The number of compatible GPUs on this node.
* */
void logPerformanceHints(const MDLogger& mdlog, size_t numCompatibleGpusOnThisNode);
- /*! \brief Return handle to the initialized GPU to use for the
- * nonbonded task on this rank, if any.
+ /*! \brief Return handle to the initialized GPU to use in the this rank.
*
- * Returns nullptr if no such task is assigned to this rank.
+ * \param[out] deviceId Index of the assigned device.
*
- * \todo This also sets up DLB for device sharing, where
- * appropriate, but that responsbility should move
- * elsewhere. */
- gmx_device_info_t* initNonbondedDevice(const t_commrec* cr) const;
- /*! \brief Return handle to the initialized GPU to use for the
- * PME task on this rank, if any.
- *
- * Returns nullptr if no such task is assigned to this rank. */
- gmx_device_info_t* initPmeDevice() const;
+ * \returns Device information on the selected devicce. Returns nullptr if no GPU task
+ * is assigned to this rank.
+ */
+ DeviceInformation* initDevice(int* deviceId) const;
//! Return whether this rank has a PME task running on a GPU
bool thisRankHasPmeGpuTask() const;
//! Return whether this rank has any task running on a GPU
bool thisRankHasAnyGpuTask() const;
};
-//! Function for whether the task of \c mapping has value \c TaskType.
-template<GpuTask TaskType>
-bool hasTaskType(const GpuTaskMapping& mapping)
-{
- return mapping.task_ == TaskType;
-}
-
} // namespace gmx
#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2017, by the GROMACS development team, led by
+# Copyright (c) 2017,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(TaskAssignmentUnitTests taskassignment-test
- usergpuids.cpp
- )
+ CPP_SOURCE_FILES
+ usergpuids.cpp
+ )
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2006 David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 1991-2006 David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#elif defined(_MSC_VER)
# include <windows.h>
-typedef __int64 gmx_cycles_t;
+typedef __int64 gmx_cycles_t;
#elif (defined(__hpux) || defined(__HP_cc)) && defined(__ia64)
/* HP compiler on ia64 */
# include <machine/sys/inline.h>
-typedef unsigned long gmx_cycles_t;
+typedef unsigned long gmx_cycles_t;
#elif (defined(__INTEL_COMPILER) || defined(__ECC)) && defined(__ia64__)
/* Intel compiler on ia64 */
# include <ia64intrin.h>
-typedef unsigned long gmx_cycles_t;
+typedef unsigned long gmx_cycles_t;
#elif defined(__GNUC__) && defined(__ia64__)
/* ia64 with GCC inline assembly */
#elif ((defined(__hppa__) || defined(__hppa)) && defined(__hpux))
/* HP PA-RISC, instruction when using HP compiler */
# include <machine/inline.h>
-typedef unsigned long gmx_cycles_t;
+typedef unsigned long gmx_cycles_t;
#elif defined(__GNUC__) && defined(__s390__)
/* S390, taken from FFTW who got it from James Treacy */
-typedef unsigned long long gmx_cycles_t;
+typedef unsigned long long gmx_cycles_t;
#elif defined(__GNUC__) && defined(__alpha__)
/* gcc inline assembly on alpha CPUs */
#elif defined(__DECC) && defined(__alpha)
/* Digital GEM C compiler on alpha */
# include <c_asm.h>
-typedef unsigned long gmx_cycles_t;
+typedef unsigned long gmx_cycles_t;
#elif (defined(__sgi) && defined(CLOCK_SGI_CYCLE))
/* Irix compilers on SGI hardware. Get nanoseconds from struct timespec */
#elif (defined(__SVR4) && defined(__SUNPRO_CC))
/* Solaris high-resolution timers */
-typedef hrtime_t gmx_cycles_t;
+typedef hrtime_t gmx_cycles_t;
#elif defined(__xlC__) && defined(_AIX)
/* AIX compilers */
#elif ((defined(__GNUC__) || defined(__IBM_GCC_ASM) || defined(__IBM_STDCPP_ASM)) \
&& (defined(__powerpc__) || defined(__ppc__)))
/* PowerPC using gcc inline assembly (also works on xlc>=7.0 with -qasm=gcc) */
-typedef unsigned long long gmx_cycles_t;
+typedef unsigned long long gmx_cycles_t;
#elif (defined(__MWERKS__) && (defined(MAC) || defined(macintosh)))
/* Metrowerks on macintosh */
#elif defined(__sun) && defined(__sparcv9)
-typedef unsigned long gmx_cycles_t;
+typedef unsigned long gmx_cycles_t;
#else
/*! \brief Integer-like datatype for cycle counter values
* the difference between two gmx_cycles_t values returned from this
* routine.
*/
-#if (GMX_CYCLECOUNTERS == 0)
-static __inline__ gmx_cycles_t gmx_cycles_read(void)
-{
- return 0;
-}
-#elif ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)) \
- && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC))
+#if ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)) \
+ && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC))
static __inline__ gmx_cycles_t gmx_cycles_read()
{
/* x86 with GCC inline assembly - pentium TSC register */
* one when later linking to the library it might happen that the
* library supports cyclecounters but not the headers, or vice versa.
*/
-#if (GMX_CYCLECOUNTERS == 0)
-static __inline__ bool gmx_cycles_have_counter(void)
-{
- return 0;
-}
-#elif ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) \
- || defined(__PGIC__) || defined(_CRAYC)) \
- && (defined(__i386__) || defined(__x86_64__)))
+#if ((defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) \
+ || defined(__PGIC__) || defined(_CRAYC)) \
+ && (defined(__i386__) || defined(__x86_64__)))
static __inline__ bool gmx_cycles_have_counter()
{
/* x86 or x86-64 with GCC inline assembly - pentium TSC register */
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
WallcycleCounts cycles_sum;
wallcc_t* wcc;
- double cycles[ewcNR + ewcsNR];
+ double cycles[int(ewcNR) + int(ewcsNR)];
#if GMX_MPI
- double cycles_n[ewcNR + ewcsNR + 1];
+ double cycles_n[int(ewcNR) + int(ewcsNR) + 1];
#endif
int i;
int nsum;
#if GMX_MPI
if (cr->nnodes > 1)
{
- double buf[ewcNR + ewcsNR + 1];
+ double buf[int(ewcNR) + int(ewcsNR) + 1];
// TODO this code is used only at the end of the run, so we
// can just do a simple reduce of haveInvalidCount in
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_wallclock_gpu_nbnxn_t;
struct gmx_wallclock_gpu_pme_t;
-typedef std::array<double, ewcNR + ewcsNR> WallcycleCounts;
+typedef std::array<double, int(ewcNR) + int(ewcsNR)> WallcycleCounts;
/* Convenience typedef */
WallcycleCounts wallcycle_sum(const t_commrec* cr, gmx_wallcycle_t wc);
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
}
}
-static void chk_bonds(t_idef* idef, int ePBC, rvec* x, matrix box, real tol)
+static void chk_bonds(const InteractionDefinitions* idef, PbcType pbcType, rvec* x, matrix box, real tol)
{
int ftype, k, ai, aj, type;
real b0, blen, deviation;
t_pbc pbc;
rvec dx;
- set_pbc(&pbc, ePBC, box);
+ gmx::ArrayRef<const t_iparams> iparams = idef->iparams;
+
+ set_pbc(&pbc, pbcType, box);
for (ftype = 0; (ftype < F_NRE); ftype++)
{
if ((interaction_function[ftype].flags & IF_CHEMBOND) == IF_CHEMBOND)
{
- for (k = 0; (k < idef->il[ftype].nr);)
+ for (k = 0; (k < idef->il[ftype].size());)
{
type = idef->il[ftype].iatoms[k++];
ai = idef->il[ftype].iatoms[k++];
b0 = 0;
switch (ftype)
{
- case F_BONDS: b0 = idef->iparams[type].harmonic.rA; break;
- case F_G96BONDS: b0 = std::sqrt(idef->iparams[type].harmonic.rA); break;
- case F_MORSE: b0 = idef->iparams[type].morse.b0A; break;
- case F_CUBICBONDS: b0 = idef->iparams[type].cubic.b0; break;
- case F_CONSTR: b0 = idef->iparams[type].constr.dA; break;
+ case F_BONDS: b0 = iparams[type].harmonic.rA; break;
+ case F_G96BONDS: b0 = std::sqrt(iparams[type].harmonic.rA); break;
+ case F_MORSE: b0 = iparams[type].morse.b0A; break;
+ case F_CUBICBONDS: b0 = iparams[type].cubic.b0; break;
+ case F_CONSTR: b0 = iparams[type].constr.dA; break;
default: break;
}
if (b0 != 0)
static void chk_trj(const gmx_output_env_t* oenv, const char* fn, const char* tpr, real tol)
{
- t_trxframe fr;
- t_count count;
- t_fr_time first, last;
- int j = -1, new_natoms, natoms;
- real old_t1, old_t2;
- gmx_bool bShowTimestep = TRUE, newline = FALSE;
- t_trxstatus* status;
- gmx_mtop_t mtop;
- gmx_localtop_t top;
- t_state state;
- t_inputrec ir;
-
+ t_trxframe fr;
+ t_count count;
+ t_fr_time first, last;
+ int j = -1, new_natoms, natoms;
+ real old_t1, old_t2;
+ gmx_bool bShowTimestep = TRUE, newline = FALSE;
+ t_trxstatus* status;
+ gmx_mtop_t mtop;
+ t_state state;
+ t_inputrec ir;
+
+ std::unique_ptr<gmx_localtop_t> top;
if (tpr)
{
read_tpx_state(tpr, &ir, &state, &mtop);
- gmx_mtop_generate_local_top(mtop, &top, ir.efep != efepNO);
+ top = std::make_unique<gmx_localtop_t>(mtop.ffparams);
+ gmx_mtop_generate_local_top(mtop, top.get(), ir.efep != efepNO);
}
new_natoms = -1;
natoms = -1;
natoms = new_natoms;
if (tpr)
{
- chk_bonds(&top.idef, ir.ePBC, fr.x, fr.box, tol);
+ chk_bonds(&top->idef, ir.pbcType, fr.x, fr.box, tol);
}
if (fr.bX)
{
{
int natom, i, j, k;
t_topology top;
- int ePBC;
+ PbcType pbcType;
t_atoms* atoms;
rvec * x, *v;
rvec dx;
real* atom_vdw;
fprintf(stderr, "Checking coordinate file %s\n", fn);
- read_tps_conf(fn, &top, &ePBC, &x, &v, box, TRUE);
+ read_tps_conf(fn, &top, &pbcType, &x, &v, box, TRUE);
atoms = &top.atoms;
natom = atoms->nr;
fprintf(stderr, "%d atoms in file\n", atoms->nr);
}
if (bB)
{
- set_pbc(&pbc, ePBC, box);
+ set_pbc(&pbc, pbcType, box);
}
bFirst = TRUE;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
"of atoms in the tpr file (%d)", \
(i), (n))
-static gmx_bool* bKeepIt(int gnx, int natoms, int index[])
+static std::vector<bool> bKeepIt(int gnx, int natoms, int index[])
{
- gmx_bool* b;
- int i;
+ std::vector<bool> b(natoms);
- snew(b, natoms);
- for (i = 0; (i < gnx); i++)
+ for (int i = 0; (i < gnx); i++)
{
RANGECHK(index[i], natoms);
- b[index[i]] = TRUE;
+ b[index[i]] = true;
}
return b;
}
-static int* invind(int gnx, int natoms, int index[])
+static std::vector<int> invind(int gnx, int natoms, int index[])
{
- int* inv;
- int i;
+ std::vector<int> inv(natoms);
- snew(inv, natoms);
- for (i = 0; (i < gnx); i++)
+ for (int i = 0; (i < gnx); i++)
{
RANGECHK(index[i], natoms);
inv[index[i]] = i;
return inv;
}
-static void reduce_block(const gmx_bool bKeep[], t_block* block, const char* name)
+static gmx::ListOfLists<int> reduce_listoflists(gmx::ArrayRef<const int> invindex,
+ const std::vector<bool>& bKeep,
+ const gmx::ListOfLists<int>& src,
+ const char* name)
{
- int* index;
- int i, j, newi, newj;
+ gmx::ListOfLists<int> lists;
- snew(index, block->nr);
-
- newi = newj = 0;
- for (i = 0; (i < block->nr); i++)
+ std::vector<int> exclusionsForAtom;
+ for (gmx::index i = 0; i < src.ssize(); i++)
{
- for (j = block->index[i]; (j < block->index[i + 1]); j++)
+ if (bKeep[i])
{
- if (bKeep[j])
+ exclusionsForAtom.clear();
+ for (const int j : src[i])
{
- newj++;
+ if (bKeep[j])
+ {
+ exclusionsForAtom.push_back(invindex[j]);
+ }
}
- }
- if (newj > index[newi])
- {
- newi++;
- index[newi] = newj;
+ lists.pushBack(exclusionsForAtom);
}
}
- fprintf(stderr, "Reduced block %8s from %6d to %6d index-, %6d to %6d a-entries\n", name,
- block->nr, newi, block->index[block->nr], newj);
- block->index = index;
- block->nr = newi;
-}
-
-static void reduce_blocka(const int invindex[], const gmx_bool bKeep[], t_blocka* block, const char* name)
-{
- int *index, *a;
- int i, j, k, newi, newj;
-
- snew(index, block->nr);
- snew(a, block->nra);
-
- newi = newj = 0;
- for (i = 0; (i < block->nr); i++)
- {
- for (j = block->index[i]; (j < block->index[i + 1]); j++)
- {
- k = block->a[j];
- if (bKeep[k])
- {
- a[newj] = invindex[k];
- newj++;
- }
- }
- if (newj > index[newi])
- {
- newi++;
- index[newi] = newj;
- }
- }
+ fprintf(stderr, "Reduced block %8s from %6zu to %6zu index-, %6d to %6d a-entries\n", name,
+ src.size(), lists.size(), src.numElements(), lists.numElements());
- fprintf(stderr, "Reduced block %8s from %6d to %6d index-, %6d to %6d a-entries\n", name,
- block->nr, newi, block->nra, newj);
- block->index = index;
- block->a = a;
- block->nr = newi;
- block->nra = newj;
+ return lists;
}
static void reduce_rvec(int gnx, const int index[], rvec vv[])
sfree(rinfo);
}
-static void reduce_ilist(const int invindex[], const gmx_bool bKeep[], t_ilist* il, int nratoms, const char* name)
+static void reduce_ilist(gmx::ArrayRef<const int> invindex,
+ const std::vector<bool>& bKeep,
+ InteractionList* il,
+ int nratoms,
+ const char* name)
{
- t_iatom* ia;
- int i, j, newnr;
- gmx_bool bB;
-
- if (il->nr)
+ if (!il->empty())
{
- snew(ia, il->nr);
- newnr = 0;
- for (i = 0; (i < il->nr); i += nratoms + 1)
+ std::vector<int> newAtoms(nratoms);
+ InteractionList ilReduced;
+ for (int i = 0; i < il->size(); i += nratoms + 1)
{
- bB = TRUE;
- for (j = 1; (j <= nratoms); j++)
+ bool bB = true;
+ for (int j = 0; j < nratoms; j++)
{
- bB = bB && bKeep[il->iatoms[i + j]];
+ bB = bB && bKeep[il->iatoms[i + 1 + j]];
}
if (bB)
{
- ia[newnr++] = il->iatoms[i];
- for (j = 1; (j <= nratoms); j++)
+ for (int j = 0; j < nratoms; j++)
{
- ia[newnr++] = invindex[il->iatoms[i + j]];
+ newAtoms[j] = invindex[il->iatoms[i + 1 + j]];
}
+ ilReduced.push_back(il->iatoms[i], nratoms, newAtoms.data());
}
}
- fprintf(stderr, "Reduced ilist %8s from %6d to %6d entries\n", name, il->nr / (nratoms + 1),
- newnr / (nratoms + 1));
-
- il->nr = newnr;
- for (i = 0; (i < newnr); i++)
- {
- il->iatoms[i] = ia[i];
- }
+ fprintf(stderr, "Reduced ilist %8s from %6d to %6d entries\n", name,
+ il->size() / (nratoms + 1), ilReduced.size() / (nratoms + 1));
- sfree(ia);
+ *il = std::move(ilReduced);
}
}
static void reduce_topology_x(int gnx, int index[], gmx_mtop_t* mtop, rvec x[], rvec v[])
{
- t_topology top;
- gmx_bool* bKeep;
- int* invindex;
- int i;
+ gmx_localtop_t top(mtop->ffparams);
+ gmx_mtop_generate_local_top(*mtop, &top, false);
+ t_atoms atoms = gmx_mtop_global_atoms(mtop);
- top = gmx_mtop_t_to_t_topology(mtop, false);
- bKeep = bKeepIt(gnx, top.atoms.nr, index);
- invindex = invind(gnx, top.atoms.nr, index);
+ const std::vector<bool> bKeep = bKeepIt(gnx, atoms.nr, index);
+ const std::vector<int> invindex = invind(gnx, atoms.nr, index);
- reduce_block(bKeep, &(top.mols), "mols");
- reduce_blocka(invindex, bKeep, &(top.excls), "excls");
reduce_rvec(gnx, index, x);
reduce_rvec(gnx, index, v);
- reduce_atom(gnx, index, top.atoms.atom, top.atoms.atomname, &(top.atoms.nres), top.atoms.resinfo);
+ reduce_atom(gnx, index, atoms.atom, atoms.atomname, &(atoms.nres), atoms.resinfo);
- for (i = 0; (i < F_NRE); i++)
+ for (int i = 0; (i < F_NRE); i++)
{
reduce_ilist(invindex, bKeep, &(top.idef.il[i]), interaction_function[i].nratoms,
interaction_function[i].name);
}
- top.atoms.nr = gnx;
+ atoms.nr = gnx;
mtop->moltype.resize(1);
mtop->moltype[0].name = mtop->name;
- mtop->moltype[0].atoms = top.atoms;
- for (i = 0; i < F_NRE; i++)
+ mtop->moltype[0].atoms = atoms;
+ mtop->moltype[0].excls = reduce_listoflists(invindex, bKeep, top.excls, "excls");
+ for (int i = 0; i < F_NRE; i++)
{
- InteractionList& ilist = mtop->moltype[0].ilist[i];
- ilist.iatoms.resize(top.idef.il[i].nr);
- for (int j = 0; j < top.idef.il[i].nr; j++)
- {
- ilist.iatoms[j] = top.idef.il[i].iatoms[j];
- }
+ mtop->moltype[0].ilist[i] = std::move(top.idef.il[i]);
}
- mtop->moltype[0].atoms = top.atoms;
- mtop->moltype[0].excls = top.excls;
mtop->molblock.resize(1);
mtop->molblock[0].type = 0;
mtop->molblock[0].nmol = 1;
- mtop->natoms = top.atoms.nr;
+ mtop->natoms = atoms.nr;
}
static void zeroq(const int index[], gmx_mtop_t* mtop)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int j;
t_atoms atoms;
rvec * x, *v;
- int ePBC;
+ PbcType pbcType;
matrix box;
t_blocka * block, *block2;
char ** gnames, **gnames2;
{
bool haveFullTopology = false;
fprintf(stderr, "\nReading structure file\n");
- readConfAndTopology(stxfile, &haveFullTopology, &mtop, &ePBC, &x, &v, box);
+ readConfAndTopology(stxfile, &haveFullTopology, &mtop, &pbcType, &x, &v, box);
atoms = gmx_mtop_global_atoms(&mtop);
if (atoms.pdbinfo == nullptr)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
sprintf(buf, "RB-A1=%.2f", idef->iparams[i].rbdihs.rbcA[1]);
break;
case F_RESTRANGLES:
- sprintf(buf, "Theta=%.1f_%.2f", idef->iparams[i].harmonic.rA,
- idef->iparams[i].harmonic.krA);
- break;
+ // Fall through intended
case F_RESTRDIHS:
sprintf(buf, "Theta=%.1f_%.2f", idef->iparams[i].harmonic.rA,
idef->iparams[i].harmonic.krA);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2017,2018,2019 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/* Broadcast the random number array to the other nodes */
if (PAR(cr))
{
- nblock_bc(cr, xtot, numbers);
+ nblock_bc(cr->mpi_comm_mygroup, xtot, numbers);
}
if (bVerbose && MASTER(cr))
if (PAR(cr))
{
/* Transfer the number of charges */
- block_bc(cr, nq);
- snew_bc(cr, *x, nq);
- snew_bc(cr, *q, nq);
- nblock_bc(cr, nq, *x);
- nblock_bc(cr, nq, *q);
+ block_bc(cr->mpi_comm_mygroup, nq);
+ snew_bc(MASTER(cr), *x, nq);
+ snew_bc(MASTER(cr), *q, nq);
+ nblock_bc(cr->mpi_comm_mygroup, nq, *x);
+ nblock_bc(cr->mpi_comm_mygroup, nq, *q);
}
return nq;
/* Transfer what we need for parallelizing the reciprocal error estimate */
static void bcast_info(t_inputinfo* info, const t_commrec* cr)
{
- nblock_bc(cr, info->n_entries, info->nkx);
- nblock_bc(cr, info->n_entries, info->nky);
- nblock_bc(cr, info->n_entries, info->nkz);
- nblock_bc(cr, info->n_entries, info->ewald_beta);
- nblock_bc(cr, info->n_entries, info->pme_order);
- nblock_bc(cr, info->n_entries, info->e_dir);
- nblock_bc(cr, info->n_entries, info->e_rec);
- block_bc(cr, info->volume);
- block_bc(cr, info->recipbox);
- block_bc(cr, info->natoms);
- block_bc(cr, info->fracself);
- block_bc(cr, info->bTUNE);
- block_bc(cr, info->q2all);
- block_bc(cr, info->q2allnr);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->nkx);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->nky);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->nkz);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->ewald_beta);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->pme_order);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->e_dir);
+ nblock_bc(cr->mpi_comm_mygroup, info->n_entries, info->e_rec);
+ block_bc(cr->mpi_comm_mygroup, info->volume);
+ block_bc(cr->mpi_comm_mygroup, info->recipbox);
+ block_bc(cr->mpi_comm_mygroup, info->natoms);
+ block_bc(cr->mpi_comm_mygroup, info->fracself);
+ block_bc(cr->mpi_comm_mygroup, info->bTUNE);
+ block_bc(cr->mpi_comm_mygroup, info->q2all);
+ block_bc(cr->mpi_comm_mygroup, info->q2allnr);
}
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-gmx_add_unit_test(ToolUnitTests tool-test
- dump.cpp
- report_methods.cpp
- trjconv.cpp)
-
+gmx_add_gtest_executable(tool-test
+ CPP_SOURCE_FILES
+ dump.cpp
+ report_methods.cpp
+ trjconv.cpp
+ )
+gmx_register_gtest_test(ToolUnitTests tool-test SLOW_TEST)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
public:
//! Run test case.
- void runTest(CommandLine* cmdline);
+ static void runTest(CommandLine* cmdline);
protected:
// TODO this is changed in newer googletest versions
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real* w_rls = nullptr;
int m, i, d, frame, outframe, natoms, nout, ncent, newstep = 0, model_nr;
#define SKIP 10
- t_topology* top = nullptr;
- gmx_conect gc = nullptr;
- int ePBC = -1;
- t_atoms * atoms = nullptr, useatoms;
+ t_topology* top = nullptr;
+ gmx_conect gc = nullptr;
+ PbcType pbcType = PbcType::Unset;
+ t_atoms * atoms = nullptr, useatoms;
matrix top_box;
int * index = nullptr, *cindex = nullptr;
char* grpnm = nullptr;
if (bTPS)
{
snew(top, 1);
- read_tps_conf(top_file, top, &ePBC, &xp, nullptr, top_box, bReset || bPBCcomRes);
+ read_tps_conf(top_file, top, &pbcType, &xp, nullptr, top_box, bReset || bPBCcomRes);
std::strncpy(top_title, *top->name, 255);
top_title[255] = '\0';
atoms = &top->atoms;
}
if (bRmPBC)
{
- gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr);
+ gpbc = gmx_rmpbc_init(&top->idef, pbcType, top->atoms.nr);
}
}
read_first_frame(oenv, &trxin, in_file, &fr, flags);
}
- set_trxframe_ePBC(&fr, ePBC);
+ setTrxFramePbcType(&fr, pbcType);
natoms = fr.natoms;
if (bSetTime)
}
else if (bCluster)
{
- calc_pbc_cluster(ecenter, ifit, top, ePBC, fr.x, ind_fit, fr.box);
+ calc_pbc_cluster(ecenter, ifit, top, pbcType, fr.x, ind_fit, fr.box);
}
if (bPFit)
switch (unitcell_enum)
{
case euRect:
- put_atoms_in_box(ePBC, fr.box, positionsArrayRef);
+ put_atoms_in_box(pbcType, fr.box, positionsArrayRef);
break;
case euTric:
put_atoms_in_triclinic_unitcell(ecenter, fr.box, positionsArrayRef);
break;
case euCompact:
- put_atoms_in_compact_unitcell(ePBC, ecenter, fr.box, positionsArrayRef);
+ put_atoms_in_compact_unitcell(pbcType, ecenter, fr.box,
+ positionsArrayRef);
break;
}
}
if (bPBCcomRes)
{
put_residue_com_in_box(unitcell_enum, ecenter, natoms, atoms->atom,
- ePBC, fr.box, fr.x);
+ pbcType, fr.box, fr.x);
}
if (bPBCcomMol)
{
put_molecule_com_in_box(unitcell_enum, ecenter, &top->mols, natoms,
- atoms->atom, ePBC, fr.box, fr.x);
+ atoms->atom, pbcType, fr.box, fr.x);
}
/* Copy the input trxframe struct to the output trxframe struct */
frout = fr;
model_nr++;
}
write_pdbfile(out, title.c_str(), &useatoms, frout.x,
- frout.ePBC, frout.box, ' ', model_nr, gc);
+ frout.pbcType, frout.box, ' ', model_nr, gc);
break;
case efG96:
const char* outputTitle = "";
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/txtdump.h"
return indent;
}
+static int pr_listoflists_title(FILE* fp, int indent, const char* title, const gmx::ListOfLists<int>* lists)
+{
+ if (available(fp, lists, indent, title))
+ {
+ indent = pr_title(fp, indent, title);
+ pr_indent(fp, indent);
+ fprintf(fp, "numLists=%zu\n", lists->size());
+ pr_indent(fp, indent);
+ fprintf(fp, "numElements=%d\n", lists->numElements());
+ }
+ return indent;
+}
+
static void low_pr_blocka(FILE* fp, int indent, const char* title, const t_blocka* block, gmx_bool bShowNumbers)
{
int i;
}
}
+void pr_listoflists(FILE* fp, int indent, const char* title, const gmx::ListOfLists<int>* lists, gmx_bool bShowNumbers)
+{
+ if (available(fp, lists, indent, title))
+ {
+ indent = pr_listoflists_title(fp, indent, title, lists);
+ for (gmx::index i = 0; i < lists->ssize(); i++)
+ {
+ int size = pr_indent(fp, indent);
+ gmx::ArrayRef<const int> list = (*lists)[i];
+ if (list.empty())
+ {
+ size += fprintf(fp, "%s[%d]={", title, int(i));
+ }
+ else
+ {
+ size += fprintf(fp, "%s[%d][num=%zu]={", title, bShowNumbers ? int(i) : -1, list.size());
+ }
+ bool isFirst = true;
+ for (const int j : list)
+ {
+ if (!isFirst)
+ {
+ size += fprintf(fp, ", ");
+ }
+ if ((size) > (USE_WIDTH))
+ {
+ fprintf(fp, "\n");
+ size = pr_indent(fp, indent + INDENT);
+ }
+ size += fprintf(fp, "%d", j);
+ isFirst = false;
+ }
+ fprintf(fp, "}\n");
+ }
+ }
+}
+
void copy_block(const t_block* src, t_block* dst)
{
dst->nr = src->nr;
namespace gmx
{
+template<typename>
+class ListOfLists;
+
/*! \brief Division of a range of indices into consecutive blocks
*
* A range of consecutive indices 0 to full.range.end() is divided
void pr_block(FILE* fp, int indent, const char* title, const t_block* block, gmx_bool bShowNumbers);
void pr_blocka(FILE* fp, int indent, const char* title, const t_blocka* block, gmx_bool bShowNumbers);
+void pr_listoflists(FILE* fp, int indent, const char* title, const gmx::ListOfLists<int>* block, gmx_bool bShowNumbers);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/block.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
#include "gromacs/utility/stringutil.h"
namespace gmx
{
+namespace
+{
+
+//! Converts ListOfLists to a list of ExclusionBlocks
+void listOfListsToExclusionBlocks(const ListOfLists<int>& b, gmx::ArrayRef<ExclusionBlock> b2)
+{
+ for (gmx::index i = 0; i < b.ssize(); i++)
+ {
+ for (int jAtom : b[i])
+ {
+ b2[i].atomNumber.push_back(jAtom);
+ }
+ }
+}
+
+//! Converts a list of ExclusionBlocks to ListOfLists
+void exclusionBlocksToListOfLists(gmx::ArrayRef<const ExclusionBlock> b2, ListOfLists<int>* b)
+{
+ b->clear();
+
+ for (const auto& block : b2)
+ {
+ b->pushBack(block.atomNumber);
+ }
+}
+
+} // namespace
+
void blockaToExclusionBlocks(const t_blocka* b, gmx::ArrayRef<ExclusionBlock> b2)
{
for (int i = 0; (i < b->nr); i++)
b->index[i] = nra;
}
-void mergeExclusions(t_blocka* excl, gmx::ArrayRef<ExclusionBlock> b2)
+namespace
{
- if (b2.empty())
- {
- return;
- }
- GMX_RELEASE_ASSERT(b2.ssize() == excl->nr,
- "Cannot merge exclusions for "
- "blocks that do not describe the same number "
- "of particles");
- /* Convert the t_blocka entries to ExclusionBlock form */
- blockaToExclusionBlocks(excl, b2);
-
- /* Count and sort the exclusions */
+//! Counts and sorts the exclusions
+int countAndSortExclusions(gmx::ArrayRef<ExclusionBlock> b2)
+{
int nra = 0;
for (auto& block : b2)
{
nra += block.nra();
}
}
- excl->nra = nra;
- srenew(excl->a, excl->nra);
- exclusionBlocksToBlocka(b2, excl);
+ return nra;
+}
+
+} // namespace
+
+void mergeExclusions(ListOfLists<int>* excl, gmx::ArrayRef<ExclusionBlock> b2)
+{
+ if (b2.empty())
+ {
+ return;
+ }
+ GMX_RELEASE_ASSERT(b2.ssize() == excl->ssize(),
+ "Cannot merge exclusions for "
+ "blocks that do not describe the same number "
+ "of particles");
+
+ /* Convert the t_blocka entries to ExclusionBlock form */
+ listOfListsToExclusionBlocks(*excl, b2);
+
+ countAndSortExclusions(b2);
+
+ exclusionBlocksToListOfLists(b2, excl);
}
} // namespace gmx
namespace gmx
{
+template<typename>
+class ListOfLists;
/*! \libinternal \brief
* Describes exclusions for a single atom.
* Requires that \c b2 and \c excl describe the same number of
* particles, if \c b2 describes a non-zero number.
*/
-void mergeExclusions(t_blocka* excl, gmx::ArrayRef<ExclusionBlock> b2);
+void mergeExclusions(ListOfLists<int>* excl, gmx::ArrayRef<ExclusionBlock> b2);
/*! \brief
* Convert the exclusions.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
GMX_ASSERT(iparams.size() == functype.size(), "Parameters and function types go together");
- return gmx::ssize(functype);
+ return static_cast<int>(functype.size());
}
/* TODO: Consider merging functype and iparams, either by storing
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <cstdio>
+#include "gromacs/topology/forcefieldparameters.h"
#include "gromacs/topology/ifunc.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
indent = pr_title(fp, indent, title);
pr_indent(fp, indent);
fprintf(fp, "nr: %d\n", ilist.size());
- if (ilist.size() > 0)
+ if (!ilist.empty())
{
pr_indent(fp, indent);
fprintf(fp, "iatoms:\n");
idef->iparams_fbposres = nullptr;
for (int f = 0; f < F_NRE; ++f)
{
- idef->il[f].iatoms = nullptr;
- idef->il[f].nalloc = 0;
- idef->il[f].nr = 0;
- idef->il[f].nr_nonperturbed = 0;
+ idef->il[f].iatoms = nullptr;
+ idef->il[f].nalloc = 0;
+ idef->il[f].nr = 0;
}
- idef->cmap_grid = nullptr;
- idef->iparams_posres_nalloc = 0;
- idef->iparams_fbposres_nalloc = 0;
- idef->ilsort = 0;
+}
+
+InteractionDefinitions::InteractionDefinitions(const gmx_ffparams_t& ffparams) :
+ iparams(ffparams.iparams),
+ functype(ffparams.functype),
+ cmap_grid(ffparams.cmap_grid)
+{
+}
+
+void InteractionDefinitions::clear()
+{
+ /* Clear the counts */
+ for (auto& ilist : il)
+ {
+ ilist.clear();
+ }
+ iparams_posres.clear();
+ iparams_fbposres.clear();
}
void done_idef(t_idef* idef)
sfree(idef->il[f].iatoms);
}
- delete idef->cmap_grid;
init_idef(idef);
}
-
-void copy_ilist(const t_ilist* src, t_ilist* dst)
-{
- dst->nr = src->nr;
- dst->nr_nonperturbed = src->nr_nonperturbed;
- dst->nalloc = src->nalloc;
-
- snew(dst->iatoms, dst->nr);
- for (int i = 0; i < dst->nr; ++i)
- {
- dst->iatoms[i] = src->iatoms[i];
- }
-}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
+struct gmx_ffparams_t;
+
typedef union t_iparams {
/* Some parameters have A and B values for free energy calculations.
* The B values are not used for regular simulations of course.
struct InteractionList
{
/* Returns the total number of elements in iatoms */
- int size() const { return gmx::ssize(iatoms); }
+ int size() const { return static_cast<int>(iatoms.size()); }
+
+ /* Returns whether the list is empty */
+ bool empty() const { return iatoms.empty(); }
+
+ /* Adds one interaction to the list */
+ template<std::size_t numAtoms>
+ void push_back(const int parameterType, const std::array<int, numAtoms>& atoms)
+ {
+ const std::size_t oldSize = iatoms.size();
+ iatoms.resize(iatoms.size() + 1 + numAtoms);
+ iatoms[oldSize] = parameterType;
+ for (std::size_t i = 0; i < numAtoms; i++)
+ {
+ iatoms[oldSize + 1 + i] = atoms[i];
+ }
+ }
+
+ /* Adds one interaction to the list */
+ void push_back(const int parameterType, const int numAtoms, const int* atoms)
+ {
+ const std::size_t oldSize = iatoms.size();
+ iatoms.resize(iatoms.size() + 1 + numAtoms);
+ iatoms[oldSize] = parameterType;
+ for (int i = 0; i < numAtoms; i++)
+ {
+ iatoms[oldSize + 1 + i] = atoms[i];
+ }
+ }
+
+ /* Appends \p ilist at the back of the list */
+ void append(const InteractionList& ilist)
+ {
+ iatoms.insert(iatoms.end(), ilist.iatoms.begin(), ilist.iatoms.end());
+ }
+
+ /* Clears the list */
+ void clear() { iatoms.clear(); }
/* List of interactions, see explanation further down */
std::vector<int> iatoms;
*
* TODO: Consider only including entries in use instead of all F_NRE
*/
-typedef std::array<InteractionList, F_NRE> InteractionLists;
+using InteractionLists = std::array<InteractionList, F_NRE>;
-/* Deprecated list of listed interactions.
- *
- * The nonperturbed/perturbed interactions are now separated (sorted) in the
- * ilist, such that the first 0..(nr_nonperturbed-1) ones are exactly that, and
- * the remaining ones from nr_nonperturbed..(nr-1) are perturbed bonded
- * interactions.
- */
+/* Deprecated list of listed interactions */
struct t_ilist
{
/* Returns the total number of elements in iatoms */
int size() const { return nr; }
+ /* Returns whether the list is empty */
+ bool empty() const { return nr == 0; }
+
int nr;
- int nr_nonperturbed;
t_iatom* iatoms;
int nalloc;
};
-/* TODO: Replace t_ilist in gmx_localtop_t by InteractionList.
- * The nr_nonperturbed functionality needs to be ported.
- * Remove t_topology.
- * Remove t_ilist and remove templating on list type
- * in mshift.cpp, constr.cpp, vsite.cpp and domdec_topology.cpp.
- */
+/* TODO: Remove t_ilist and remove templating on list type in mshift.cpp */
/*
* The structs InteractionList and t_ilist defines a list of atoms with their interactions.
std::vector<InteractionListHandle> handles;
for (size_t ftype = 0; ftype < ilists.size(); ftype++)
{
- if ((interaction_function[ftype].flags & flags) && ilists[ftype].size() > 0)
+ if ((interaction_function[ftype].flags & flags) && !ilists[ftype].empty())
{
handles.push_back({ static_cast<int>(ftype), ilists[ftype].iatoms });
}
ilsortFE_SORTED
};
-typedef struct t_idef
+/* Struct with list of interaction parameters and lists of interactions
+ *
+ * TODO: Convert to a proper class with private data members so we can
+ * ensure that the free-energy sorting and sorting setting is consistent.
+ */
+class InteractionDefinitions
+{
+public:
+ /* Constructor
+ *
+ * \param[in] ffparams The interaction parameters, the lifetime of the created object should not exceed the lifetime of the passed parameters
+ */
+ InteractionDefinitions(const gmx_ffparams_t& ffparams);
+
+ // Clears data not read in from ffparams
+ void clear();
+
+ // The interaction parameters
+ const std::vector<t_iparams>& iparams;
+ // The function type per type
+ const std::vector<int>& functype;
+ // Position restraint interaction parameters
+ std::vector<t_iparams> iparams_posres;
+ // Flat-bottomed position restraint parameters
+ std::vector<t_iparams> iparams_fbposres;
+ // The list of interactions for each type. Note that some, such as LJ and COUL will have 0 entries.
+ std::array<InteractionList, F_NRE> il;
+ /* The number of non-perturbed interactions at the start of each entry in il */
+ std::array<int, F_NRE> numNonperturbedInteractions;
+ // The sorting state of interaction in il
+ int ilsort = ilsortUNKNOWN;
+ // The dihedral correction maps
+ gmx_cmap_t cmap_grid;
+};
+
+/* Deprecated interation definitions, used in t_topology */
+struct t_idef
{
int ntypes;
int atnr;
t_functype* functype;
t_iparams* iparams;
real fudgeQQ;
- gmx_cmap_t* cmap_grid;
t_iparams * iparams_posres, *iparams_fbposres;
- int iparams_posres_nalloc, iparams_fbposres_nalloc;
t_ilist il[F_NRE];
int ilsort;
-} t_idef;
+};
/*
* The struct t_idef defines all the interactions for the complete
*/
void done_idef(t_idef* idef);
-void copy_ilist(const t_ilist* src, t_ilist* dst);
-
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2008,2009,2010,
- * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2008,2009,2010, The GROMACS development team.
+ * Copyright (c) 2012,2013,2014,2015,2016 The GROMACS development team.
* Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
int a_offset;
} t_gmx_mtop_ilist_all;
-gmx_mtop_ilistloop_all_t gmx_mtop_ilistloop_all_init(const gmx_mtop_t* mtop)
-{
- struct gmx_mtop_ilistloop_all* iloop;
-
- snew(iloop, 1);
-
- iloop->mtop = mtop;
- iloop->mblock = 0;
- iloop->mol = -1;
- iloop->a_offset = 0;
-
- return iloop;
-}
-
-static void gmx_mtop_ilistloop_all_destroy(gmx_mtop_ilistloop_all_t iloop)
-{
- sfree(iloop);
-}
-
-const InteractionLists* gmx_mtop_ilistloop_all_next(gmx_mtop_ilistloop_all_t iloop, int* atnr_offset)
-{
-
- if (iloop == nullptr)
- {
- gmx_incons(
- "gmx_mtop_ilistloop_all_next called without calling gmx_mtop_ilistloop_all_init");
- }
-
- if (iloop->mol >= 0)
- {
- iloop->a_offset += iloop->mtop->moleculeBlockIndices[iloop->mblock].numAtomsPerMolecule;
- }
-
- iloop->mol++;
-
- /* Inter-molecular interactions, if present, are indexed with
- * iloop->mblock == iloop->mtop->nmolblock, thus we should separately
- * check for this value in this conditional.
- */
- if (iloop->mblock == iloop->mtop->molblock.size()
- || iloop->mol >= iloop->mtop->molblock[iloop->mblock].nmol)
- {
- iloop->mblock++;
- iloop->mol = 0;
- if (iloop->mblock >= iloop->mtop->molblock.size())
- {
- if (iloop->mblock == iloop->mtop->molblock.size() && iloop->mtop->bIntermolecularInteractions)
- {
- *atnr_offset = 0;
- return iloop->mtop->intermolecular_ilist.get();
- }
-
- gmx_mtop_ilistloop_all_destroy(iloop);
- return nullptr;
- }
- }
-
- *atnr_offset = iloop->a_offset;
-
- return &iloop->mtop->moltype[iloop->mtop->molblock[iloop->mblock].type].ilist;
-}
-
int gmx_mtop_ftype_count(const gmx_mtop_t* mtop, int ftype)
{
gmx_mtop_ilistloop_t iloop;
* The cat routines below are old code from src/kernel/topcat.c
*/
-static void blockacat(t_blocka* dest, const t_blocka* src, int copies, int dnum, int snum)
+static void ilistcat(int ftype, InteractionList* dest, const InteractionList& src, int copies, int dnum, int snum)
{
- int i, j, l, size;
- int destnr = dest->nr;
- int destnra = dest->nra;
+ int nral, c, i, a;
- if (src->nr)
- {
- size = (dest->nr + copies * src->nr + 1);
- srenew(dest->index, size);
- }
- if (src->nra)
- {
- size = (dest->nra + copies * src->nra);
- srenew(dest->a, size);
- }
+ nral = NRAL(ftype);
- for (l = destnr, j = 0; (j < copies); j++)
- {
- for (i = 0; (i < src->nr); i++)
- {
- dest->index[l++] = dest->nra + src->index[i];
- }
- dest->nra += src->nra;
- }
- for (l = destnra, j = 0; (j < copies); j++)
+ size_t destIndex = dest->iatoms.size();
+ dest->iatoms.resize(dest->iatoms.size() + copies * src.size());
+
+ for (c = 0; c < copies; c++)
{
- for (i = 0; (i < src->nra); i++)
+ for (i = 0; i < src.size();)
{
- dest->a[l++] = dnum + src->a[i];
+ dest->iatoms[destIndex++] = src.iatoms[i++];
+ for (a = 0; a < nral; a++)
+ {
+ dest->iatoms[destIndex++] = dnum + src.iatoms[i++];
+ }
}
dnum += snum;
- dest->nr += src->nr;
}
- dest->index[dest->nr] = dest->nra;
- dest->nalloc_index = dest->nr;
- dest->nalloc_a = dest->nra;
}
static void ilistcat(int ftype, t_ilist* dest, const InteractionList& src, int copies, int dnum, int snum)
}
}
-static void set_posres_params(t_idef* idef, const gmx_molblock_t* molb, int i0, int a_offset)
+static const t_iparams& getIparams(const InteractionDefinitions& idef, const int index)
+{
+ return idef.iparams[index];
+}
+
+static const t_iparams& getIparams(const t_idef& idef, const int index)
+{
+ return idef.iparams[index];
+}
+
+static void resizeIParams(std::vector<t_iparams>* iparams, const int newSize)
+{
+ iparams->resize(newSize);
+}
+
+static void resizeIParams(t_iparams** iparams, const int newSize)
+{
+ srenew(*iparams, newSize);
+}
+
+template<typename IdefType>
+static void set_posres_params(IdefType* idef, const gmx_molblock_t* molb, int i0, int a_offset)
{
- t_ilist* il;
int i1, i, a_molb;
t_iparams* ip;
- il = &idef->il[F_POSRES];
- i1 = il->nr / 2;
- idef->iparams_posres_nalloc = i1;
- srenew(idef->iparams_posres, idef->iparams_posres_nalloc);
+ auto* il = &idef->il[F_POSRES];
+ i1 = il->size() / 2;
+ resizeIParams(&idef->iparams_posres, i1);
for (i = i0; i < i1; i++)
{
ip = &idef->iparams_posres[i];
/* Copy the force constants */
- *ip = idef->iparams[il->iatoms[i * 2]];
+ *ip = getIparams(*idef, il->iatoms[i * 2]);
a_molb = il->iatoms[i * 2 + 1] - a_offset;
if (molb->posres_xA.empty())
{
}
}
-static void set_fbposres_params(t_idef* idef, const gmx_molblock_t* molb, int i0, int a_offset)
+template<typename IdefType>
+static void set_fbposres_params(IdefType* idef, const gmx_molblock_t* molb, int i0, int a_offset)
{
- t_ilist* il;
int i1, i, a_molb;
t_iparams* ip;
- il = &idef->il[F_FBPOSRES];
- i1 = il->nr / 2;
- idef->iparams_fbposres_nalloc = i1;
- srenew(idef->iparams_fbposres, idef->iparams_fbposres_nalloc);
+ auto* il = &idef->il[F_FBPOSRES];
+ i1 = il->size() / 2;
+ resizeIParams(&idef->iparams_fbposres, i1);
for (i = i0; i < i1; i++)
{
ip = &idef->iparams_fbposres[i];
/* Copy the force constants */
- *ip = idef->iparams[il->iatoms[i * 2]];
+ *ip = getIparams(*idef, il->iatoms[i * 2]);
a_molb = il->iatoms[i * 2 + 1] - a_offset;
if (molb->posres_xA.empty())
{
}
}
-/*! \brief Copy idef structure from mtop.
+/*! \brief Copy parameters to idef structure from mtop.
*
- * Makes a deep copy of an idef data structure from a gmx_mtop_t.
+ * Makes a deep copy of the force field parameters data structure from a gmx_mtop_t.
* Used to initialize legacy topology types.
*
* \param[in] mtop Reference to input mtop.
* \param[in] idef Pointer to idef to populate.
- * \param[in] mergeConstr Decide if constraints will be merged.
- * \param[in] freeEnergyInteractionsAtEnd Decide if free energy stuff should
- * be added at the end.
*/
-static void copyIdefFromMtop(const gmx_mtop_t& mtop, t_idef* idef, bool freeEnergyInteractionsAtEnd, bool mergeConstr)
+static void copyFFParametersFromMtop(const gmx_mtop_t& mtop, t_idef* idef)
{
const gmx_ffparams_t* ffp = &mtop.ffparams;
{
idef->iparams = nullptr;
}
- idef->iparams_posres = nullptr;
- idef->iparams_posres_nalloc = 0;
- idef->iparams_fbposres = nullptr;
- idef->iparams_fbposres_nalloc = 0;
- idef->fudgeQQ = ffp->fudgeQQ;
- idef->cmap_grid = new gmx_cmap_t;
- *idef->cmap_grid = ffp->cmap_grid;
- idef->ilsort = ilsortUNKNOWN;
-
- for (int ftype = 0; ftype < F_NRE; ftype++)
- {
- idef->il[ftype].nr = 0;
- idef->il[ftype].nalloc = 0;
- idef->il[ftype].iatoms = nullptr;
- }
+ idef->iparams_posres = nullptr;
+ idef->iparams_fbposres = nullptr;
+ idef->fudgeQQ = ffp->fudgeQQ;
+ idef->ilsort = ilsortUNKNOWN;
+}
+/*! \brief Copy idef structure from mtop.
+ *
+ * Makes a deep copy of an idef data structure from a gmx_mtop_t.
+ * Used to initialize legacy topology types.
+ *
+ * \param[in] mtop Reference to input mtop.
+ * \param[in] idef Pointer to idef to populate.
+ * \param[in] mergeConstr Decide if constraints will be merged.
+ */
+template<typename IdefType>
+static void copyIListsFromMtop(const gmx_mtop_t& mtop, IdefType* idef, bool mergeConstr)
+{
int natoms = 0;
for (const gmx_molblock_t& molb : mtop.molblock)
{
int srcnr = molt.atoms.nr;
int destnr = natoms;
- int nposre_old = idef->il[F_POSRES].nr;
- int nfbposre_old = idef->il[F_FBPOSRES].nr;
+ int nposre_old = idef->il[F_POSRES].size();
+ int nfbposre_old = idef->il[F_FBPOSRES].size();
for (int ftype = 0; ftype < F_NRE; ftype++)
{
- if (mergeConstr && ftype == F_CONSTR && molt.ilist[F_CONSTRNC].size() > 0)
+ if (mergeConstr && ftype == F_CONSTR && !molt.ilist[F_CONSTRNC].empty())
{
/* Merge all constrains into one ilist.
* This simplifies the constraint code.
ilistcat(ftype, &idef->il[ftype], molt.ilist[ftype], molb.nmol, destnr, srcnr);
}
}
- if (idef->il[F_POSRES].nr > nposre_old)
+ if (idef->il[F_POSRES].size() > nposre_old)
{
/* Executing this line line stops gmxdump -sys working
* correctly. I'm not aware there's an elegant fix. */
set_posres_params(idef, &molb, nposre_old / 2, natoms);
}
- if (idef->il[F_FBPOSRES].nr > nfbposre_old)
+ if (idef->il[F_FBPOSRES].size() > nfbposre_old)
{
set_fbposres_params(idef, &molb, nfbposre_old / 2, natoms);
}
}
}
- if (freeEnergyInteractionsAtEnd && gmx_mtop_bondeds_free_energy(&mtop))
- {
- std::vector<real> qA(mtop.natoms);
- std::vector<real> qB(mtop.natoms);
- for (const AtomProxy atomP : AtomRange(mtop))
- {
- const t_atom& local = atomP.atom();
- int index = atomP.globalAtomNumber();
- qA[index] = local.q;
- qB[index] = local.qB;
- }
- gmx_sort_ilist_fe(idef, qA.data(), qB.data());
- }
- else
- {
- idef->ilsort = ilsortNO_FE;
- }
+ // We have not (yet) sorted free-energy interactions to the end of the ilists
+ idef->ilsort = ilsortNO_FE;
}
/*! \brief Copy atomtypes from mtop
}
}
-/*! \brief Copy excls from mtop.
- *
- * Makes a deep copy of excls(t_blocka) from gmx_mtop_t.
- * Used to initialize legacy topology types.
+/*! \brief Generate a single list of lists of exclusions for the whole system
*
* \param[in] mtop Reference to input mtop.
- * \param[in] excls Pointer to final excls data structure.
*/
-static void copyExclsFromMtop(const gmx_mtop_t& mtop, t_blocka* excls)
+static gmx::ListOfLists<int> globalExclusionLists(const gmx_mtop_t& mtop)
{
- init_blocka(excls);
- int natoms = 0;
+ gmx::ListOfLists<int> excls;
+
+ int atomIndex = 0;
for (const gmx_molblock_t& molb : mtop.molblock)
{
const gmx_moltype_t& molt = mtop.moltype[molb.type];
- int srcnr = molt.atoms.nr;
- int destnr = natoms;
-
- blockacat(excls, &molt.excls, molb.nmol, destnr, srcnr);
+ for (int mol = 0; mol < molb.nmol; mol++)
+ {
+ excls.appendListOfLists(molt.excls, atomIndex);
- natoms += molb.nmol * srcnr;
+ atomIndex += molt.atoms.nr;
+ }
}
+
+ return excls;
}
/*! \brief Updates inter-molecular exclusion lists
* \param[inout] excls existing exclusions in local topology
* \param[in] ids list of global IDs of atoms
*/
-static void addMimicExclusions(t_blocka* excls, const gmx::ArrayRef<const int> ids)
+static void addMimicExclusions(gmx::ListOfLists<int>* excls, const gmx::ArrayRef<const int> ids)
{
t_blocka inter_excl{};
init_blocka(&inter_excl);
size_t n_q = ids.size();
- inter_excl.nr = excls->nr;
+ inter_excl.nr = excls->ssize();
inter_excl.nra = n_q * n_q;
size_t total_nra = n_q * n_q;
- snew(inter_excl.index, excls->nr + 1);
+ snew(inter_excl.index, excls->ssize() + 1);
snew(inter_excl.a, total_nra);
- for (int i = 0; i < excls->nr; ++i)
+ for (int i = 0; i < inter_excl.nr; ++i)
{
inter_excl.index[i] = 0;
}
inter_excl.index[inter_excl.nr] = n_q * n_q;
- std::vector<gmx::ExclusionBlock> qmexcl2(excls->nr);
+ std::vector<gmx::ExclusionBlock> qmexcl2(excls->size());
gmx::blockaToExclusionBlocks(&inter_excl, qmexcl2);
// Merge the created exclusion list with the existing one
gmx::mergeExclusions(excls, qmexcl2);
}
+static void sortFreeEnergyInteractionsAtEnd(const gmx_mtop_t& mtop, InteractionDefinitions* idef)
+{
+ std::vector<real> qA(mtop.natoms);
+ std::vector<real> qB(mtop.natoms);
+ for (const AtomProxy atomP : AtomRange(mtop))
+ {
+ const t_atom& local = atomP.atom();
+ int index = atomP.globalAtomNumber();
+ qA[index] = local.q;
+ qB[index] = local.qB;
+ }
+ gmx_sort_ilist_fe(idef, qA.data(), qB.data());
+}
+
static void gen_local_top(const gmx_mtop_t& mtop,
bool freeEnergyInteractionsAtEnd,
bool bMergeConstr,
gmx_localtop_t* top)
{
- copyAtomtypesFromMtop(mtop, &top->atomtypes);
- copyIdefFromMtop(mtop, &top->idef, freeEnergyInteractionsAtEnd, bMergeConstr);
- copyExclsFromMtop(mtop, &top->excls);
+ copyIListsFromMtop(mtop, &top->idef, bMergeConstr);
+ if (freeEnergyInteractionsAtEnd)
+ {
+ sortFreeEnergyInteractionsAtEnd(mtop, &top->idef);
+ }
+ top->excls = globalExclusionLists(mtop);
if (!mtop.intermolecularExclusionGroup.empty())
{
addMimicExclusions(&top->excls, mtop.intermolecularExclusionGroup);
return mols;
}
-static void gen_t_topology(const gmx_mtop_t& mtop,
- bool freeEnergyInteractionsAtEnd,
- bool bMergeConstr,
- t_topology* top)
+static void gen_t_topology(const gmx_mtop_t& mtop, bool bMergeConstr, t_topology* top)
{
copyAtomtypesFromMtop(mtop, &top->atomtypes);
- copyIdefFromMtop(mtop, &top->idef, freeEnergyInteractionsAtEnd, bMergeConstr);
- copyExclsFromMtop(mtop, &top->excls);
+ for (int ftype = 0; ftype < F_NRE; ftype++)
+ {
+ top->idef.il[ftype].nr = 0;
+ top->idef.il[ftype].nalloc = 0;
+ top->idef.il[ftype].iatoms = nullptr;
+ }
+ copyFFParametersFromMtop(mtop, &top->idef);
+ copyIListsFromMtop(mtop, &top->idef, bMergeConstr);
top->name = mtop.name;
top->atoms = gmx_mtop_global_atoms(&mtop);
{
t_topology top;
- gen_t_topology(*mtop, false, false, &top);
+ gen_t_topology(*mtop, false, &top);
if (freeMTop)
{
gmx_mtop_finalize(mtop);
}
+
+bool haveFepPerturbedNBInteractions(const gmx_mtop_t* mtop)
+{
+ for (size_t mb = 0; mb < mtop->molblock.size(); mb++)
+ {
+ const gmx_molblock_t& molb = mtop->molblock[mb];
+ const gmx_moltype_t& molt = mtop->moltype[molb.type];
+ for (int m = 0; m < molb.nmol; m++)
+ {
+ for (int a = 0; a < molt.atoms.nr; a++)
+ {
+ const t_atom& atom = molt.atoms.atom[a];
+ if (PERTURBED(atom))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct t_atoms;
struct t_block;
struct t_symtab;
-enum struct GmxQmmmMode;
// TODO All of the functions taking a const gmx_mtop * are deprecated
// and should be replaced by versions taking const gmx_mtop & when
*/
const InteractionLists* gmx_mtop_ilistloop_next(gmx_mtop_ilistloop_t iloop, int* nmol);
-/* Abstract type for ilist loop over all ilists of all molecules */
-typedef struct gmx_mtop_ilistloop_all* gmx_mtop_ilistloop_all_t;
-
-/* Initialize an ilist loop over all molecule types in the system.
- * Only use this when you really need to loop over all molecules,
- * i.e. when you use groups which might differ per molecule,
- * otherwise use gmx_mtop_ilistloop.
- */
-gmx_mtop_ilistloop_all_t gmx_mtop_ilistloop_all_init(const gmx_mtop_t* mtop);
-
-/* Loop to the next molecule,
- * When not at the end:
- * returns a valid pointer to the next array ilist_mol[F_NRE],
- * writes the atom offset which should be added to iatoms in atnr_offset.
- * When at the end, destroys iloop and returns nullptr.
- */
-const InteractionLists* gmx_mtop_ilistloop_all_next(gmx_mtop_ilistloop_all_t iloop, int* atnr_offset);
-
-
/* Returns the total number of interactions in the system of type ftype */
int gmx_mtop_ftype_count(const gmx_mtop_t* mtop, int ftype);
*/
void convertAtomsToMtop(t_symtab* symtab, char** name, t_atoms* atoms, gmx_mtop_t* mtop);
+/*! \brief Checks if the non-bonded FEP should be performed in this run.
+ *
+ * \param[in] mtop Molecular topology.
+ * \returns Whether FEP non-bonded is requested.
+ */
+bool haveFepPerturbedNBInteractions(const gmx_mtop_t* mtop);
+
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
#include <iterator>
+#include <optional>
#include <string>
-#include "gromacs/compat/optional.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
* \param[in] residueName Name of a residue to compare to database.
* \returns An optional iterator to the residue entry that was found.
*/
-static gmx::compat::optional<gmx::ArrayRef<const ResidueTypeEntry>::const_iterator>
+static std::optional<gmx::ArrayRef<const ResidueTypeEntry>::const_iterator>
findResidueEntryWithName(gmx::ArrayRef<const ResidueTypeEntry> entries, const std::string& residueName)
{
auto foundIt =
std::find_if(entries.begin(), entries.end(), [&residueName](const ResidueTypeEntry& old) {
return gmx::equalCaseInsensitive(residueName, old.residueName);
});
- return (foundIt != entries.end()) ? gmx::compat::make_optional(foundIt) : gmx::compat::nullopt;
+ return (foundIt != entries.end()) ? std::make_optional(foundIt) : std::nullopt;
}
bool ResidueType::nameIndexedInResidueTypes(const std::string& residueName)
return foundIt ? (*foundIt)->residueType : c_undefinedResidueType;
}
-gmx::compat::optional<std::string> ResidueType::optionalTypeOfNamedDatabaseResidue(const std::string& residueName)
+std::optional<std::string> ResidueType::optionalTypeOfNamedDatabaseResidue(const std::string& residueName)
{
auto foundIt = findResidueEntryWithName(impl_->entry, residueName);
- return foundIt ? gmx::compat::make_optional((*foundIt)->residueType) : gmx::compat::nullopt;
+ return foundIt ? std::make_optional((*foundIt)->residueType) : std::nullopt;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2014,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_TOPOLOGY_RESIDUETYPES_H
#define GMX_TOPOLOGY_RESIDUETYPES_H
+#include <optional>
#include <string>
-#include "gromacs/compat/optional.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/classhelpers.h"
* \param[in] residueName Name of the residue to search for.
* \returns An optional containing the residue type of any matching residue
*/
- gmx::compat::optional<std::string> optionalTypeOfNamedDatabaseResidue(const std::string& residueName);
+ std::optional<std::string> optionalTypeOfNamedDatabaseResidue(const std::string& residueName);
private:
//! Implementation pointer.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ * \brief
+ * Implements new and legacy symbol table routines.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \author Paul Bauer <paul.bauer.q@gmail.com>
+ * \ingroup module_topology
+ */
#include "gmxpre.h"
#include "symtab.h"
#include "gromacs/utility/basedefinitions.h"
#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/iserializer.h"
#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
#include "gromacs/utility/txtdump.h"
-constexpr int c_trimSize = 1024;
+StringTableEntry StringTableBuilder::addString(const std::string& theString)
+{
+ int size = map_.size();
+ std::string stripped = gmx::stripString(theString);
+
+ const auto foundEntry = map_.insert(StringTablePair(stripped, size));
+ return StringTableEntry(foundEntry.first->first, foundEntry.first->second);
+}
+
+int StringTableBuilder::findEntryByName(const std::string& name) const
+{
+ auto foundEntry = map_.find(name);
+ if (foundEntry != map_.end())
+ {
+ return foundEntry->second;
+ }
+ else
+ {
+ GMX_THROW(gmx::InternalError(
+ gmx::formatString("Could not find string \"%s\" in SymbolTable", name.c_str())));
+ }
+}
+
+StringTable StringTableBuilder::build()
+{
+ std::vector<std::string> table(map_.size());
+ for (const auto& entry : map_)
+ {
+ table[entry.second] = entry.first;
+ }
+ map_.clear();
+ return StringTable(table);
+}
+
+void StringTable::printStringTableStorageToFile(FILE* fp, int indent, const char* title) const
+{
+ indent = pr_title_n(fp, indent, title, table_.size());
+ int i = 0;
+ for (const auto& entry : table_)
+ {
+ pr_indent(fp, indent);
+ fprintf(fp, "%s[%d]=\"%s\"\n", title, i++, entry.c_str());
+ }
+}
+
+StringTable::StringTable(gmx::ISerializer* serializer)
+{
+ GMX_RELEASE_ASSERT(serializer->reading(),
+ "Can not use writing serializer to read string table");
+ int nr = 0;
+ serializer->doInt(&nr);
+ table_.resize(nr);
+ for (auto& entry : table_)
+ {
+ serializer->doString(&entry);
+ }
+}
+
+void StringTable::serializeStringTable(gmx::ISerializer* serializer)
+{
+ GMX_RELEASE_ASSERT(!serializer->reading(),
+ "Can not use reading serializer to write string table");
+ int nr = table_.size();
+ serializer->doInt(&nr);
+ for (auto& entry : table_)
+ {
+ serializer->doString(&entry);
+ }
+}
+
+StringTableEntry StringTable::at(gmx::index index) const
+{
+ if (index >= gmx::ssize(table_))
+ {
+ GMX_THROW(gmx::InternalError("Can't read beyond last entry"));
+ }
+ return StringTableEntry(table_[index], index);
+}
+
+StringTableEntry StringTable::operator[](gmx::index index) const
+{
+ GMX_ASSERT(index < gmx::ssize(table_), "Can't read beyond last entry");
+ return StringTableEntry(table_[index], index);
+}
+
+void StringTableEntry::serialize(gmx::ISerializer* serializer) const
+{
+ GMX_RELEASE_ASSERT(!serializer->reading(),
+ "Can not use reading serializer to write string index");
+ int entry = tableIndex_;
+ serializer->doInt(&entry);
+}
+
+StringTableEntry readStringTableEntry(gmx::ISerializer* serializer, const StringTable& table)
+{
+ GMX_RELEASE_ASSERT(serializer->reading(),
+ "Can not use writing serializer to read string index");
+ int entry = 0;
+ serializer->doInt(&entry);
+ return table.at(entry);
+}
+
+// Old code for legacy data structure starts below.
+//! Maximum size of character string in table.
+constexpr int c_trimSize = 1024;
+//! Maximum number of entries in each element of the linked list.
constexpr int c_maxBufSize = 5;
-static char* trim_string(const char* s, char* out, int maxlen)
-/*
- * Returns a pointer to a static area which contains a copy
- * of s without leading or trailing spaces. Strings are
- * truncated to c_trimSize positions.
+/*! \brief
+ * Remove leading and trailing whitespace from string and enforce maximum length.
*
- * TODO This partially duplicates code in trim(), but perhaps
- * replacing symtab with a std::map is a better fix.
+ * \param[in] s String to trim.
+ * \param[inout] out String to return.
+ * \param[in] maxlen Maximum string length to use.
+ * \returns New pruned string.
*/
+static char* trim_string(const char* s, char* out, int maxlen)
{
int len, i;
gmx_fatal(FARGS, "symtab get_symtab_handle %d not found", name);
}
+//! Returns a new initialized entry into the symtab linked list.
static t_symbuf* new_symbuf()
{
t_symbuf* symbuf;
return symbuf;
}
+/*! \brief
+ * Low level function to enter new string into legacy symtab.
+ *
+ * \param[inout] symtab Symbol table to add entry to.
+ * \param[in] name New string to add to symtab.
+ * \returns Pointer to new entry in the legacy symbol table, or to existing entry if it already existed.
+ */
static char** enter_buf(t_symtab* symtab, char* name)
{
int i;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2010,2014,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2014,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \file
+ * \brief
+ * Declares modern and legacy symbol table used to store strings of characters.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \author Paul Bauer <paul.bauer.q@gmail.com>
+ *
+ * \ingroup module_topology
+ * \inlibraryapi
+ */
#ifndef GMX_TOPOLOGY_SYMTAB_H
#define GMX_TOPOLOGY_SYMTAB_H
#include <stdio.h>
-typedef struct t_symbuf
+#include <functional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "gromacs/utility/gmxassert.h"
+
+struct t_commrec;
+struct t_fileio;
+
+namespace gmx
+{
+class ISerializer;
+namespace test
+{
+class StringTableTest;
+} // namespace test
+} // namespace gmx
+
+//! Convenience typedef for pair stored in map.
+using StringTablePair = std::pair<std::string, int>;
+//! Convenience typedef for string reference wrapper.
+using StringReference = std::reference_wrapper<const std::string>;
+
+class StringTableBuilder;
+class StringTableEntry;
+/*! \brief
+ * A class to store strings for lookup.
+ *
+ * We store the strings in a dedicated object to avoid
+ * wrong usage of the flat string vector, and forcing people
+ * to use an object that can only be constructed from the transitional
+ * StringTableBuilder or filled during file IO.
+ *
+ * Note that strings are stripped of trailing and leading whitespace.
+ */
+class StringTable
+{
+public:
+ //! Constructor used to generate table object from file reading.
+ StringTable(gmx::ISerializer* serializer);
+ //! Can move construct.
+ StringTable(StringTable&&) = default;
+ //! Can move assign.
+ StringTable& operator=(StringTable&&) = default;
+ //! No copy constructor.
+ StringTable(const StringTable&) = delete;
+ //! No copy assign.
+ StringTable& operator=(const StringTable&) = delete;
+ /*! \brief
+ * Access string at \p index.
+ *
+ * \returns Entry type that constains both the string and the index,
+ * with the index needed during (de-)serialization.
+ * \throws On index being out of range.
+ */
+ StringTableEntry at(gmx::index index) const;
+ //! Bracket operator.
+ StringTableEntry operator[](gmx::index index) const;
+ //! Handle file IO.
+ void serializeStringTable(gmx::ISerializer* serializer);
+
+ //! Print human readable format of storage.
+ void printStringTableStorageToFile(FILE* fp, int indent, const char* title) const;
+
+ friend class StringTableBuilder;
+
+private:
+ /*! \brief
+ * Private constructor so that only builder can create the final table.
+ *
+ * \param[in] table A vector of strings to be stored in the table.
+ */
+ StringTable(const std::vector<std::string>& table) : table_(table) {}
+
+ //! The table is stored as a vector of strings.
+ std::vector<std::string> table_;
+};
+
+/*! \brief
+ * Helper class to access members in StringTable.
+ *
+ * This class is a wrapper around a string reference to access
+ * the actual entry in the table, as well as an index used for
+ * serializing the datastructure.
+ *
+ * This also provides efficient comparison calls between different entries.
+ */
+class StringTableEntry
+{
+public:
+ //! Copy construct.
+ StringTableEntry(const StringTableEntry&) = default;
+ //! Move construct.
+ StringTableEntry(StringTableEntry&&) noexcept = default;
+ //! Copy assign.
+ StringTableEntry& operator=(const StringTableEntry&) = default;
+ //! Move assign.
+ StringTableEntry& operator=(StringTableEntry&&) = default;
+
+ //! Compare entries by indices. Same string should always have same index.
+ bool operator==(const StringTableEntry& o) const { return tableIndex_ == o.tableIndex_; }
+ //! Unequal comparisson.
+ bool operator!=(const StringTableEntry& o) const { return !(*this == o); }
+ //! Access to underlying view.
+ const std::string& operator*() const { return entry_; }
+ //! Access to underlying view.
+ const std::string* operator->() const { return &entry_.get(); }
+ //! Serialize index.
+ void serialize(gmx::ISerializer* serializer) const;
+
+ // We only allow construction from the places that are known to create
+ // valid objects for us.
+ friend StringTableEntry readStringTableEntry(gmx::ISerializer* serializer, const StringTable& table);
+ friend class StringTableBuilder;
+ friend class StringTable;
+
+private:
+ //! Only allow construct with all information present.
+ StringTableEntry(StringReference entry, int tableIndex) : entry_(entry), tableIndex_(tableIndex)
+ {
+ }
+ //! The actual string reference that is stored.
+ StringReference entry_;
+ //! The index into the table.
+ int tableIndex_ = -1;
+};
+
+/*! \brief
+ * De-serialize StringTableEntry using the index into the \p table.
+ *
+ * \param[in] serializer The object containing the serialized index.
+ * \param[in] table The storage object holding all strings.
+ * \returns The entry into the Table as StringTableEntry.
+ */
+StringTableEntry readStringTableEntry(gmx::ISerializer* serializer, const StringTable& table);
+
+/*! \libinternal \brief
+ * Builds a memory efficient storage for strings of characters.
+ *
+ * Allows storing strings of characters with unique entries.
+ */
+class StringTableBuilder
+{
+public:
+ /*! \brief
+ * Place new unique string in storage object.
+ *
+ * Enters new string into the underlying storage or recovers existing entry.
+ * \param[in] theString New string to enter.
+ * \returns New entry object with reference to string and index into storage.
+ * The reference is only valid while the builder is in use, and becomes
+ * invalidated when generating the StringTable.
+ */
+ StringTableEntry addString(const std::string& theString);
+ //! Find matching entry in storage by name as string.
+ int findEntryByName(const std::string& name) const;
+ /*! \brief
+ * Build the StringTable from the internal map of strings.
+ *
+ * The unique indices returned from addString() can be used
+ * to index into the returned StringTable. Clears the
+ * temporary storage so that the StringTableBuilder can be re-used to
+ * build a distinct StringTable.
+ */
+ StringTable build();
+
+private:
+ //! Storage object for entries.
+ std::unordered_map<std::string, int> map_;
+};
+
+// Below this is the legacy code for the old symbol table, only used in
+// deprecated datastructures.
+/*! \libinternal \brief
+ * Legacy symbol table entry as linked list.
+ */
+struct t_symbuf
{
- int bufsize;
- char** buf;
+ //! Number of entries in this item
+ int bufsize;
+ //! Storage for strings in this item.
+ char** buf;
+ //! Next item in linked list.
struct t_symbuf* next;
-} t_symbuf;
+};
-typedef struct t_symtab
+/* \libinternal \brief
+ * Legacy symbol table.
+ */
+struct t_symtab
{
- int nr;
+ //! Total number of entries stored.
+ int nr;
+ //! First item in linked list of storage elements.
t_symbuf* symbuf;
-} t_symtab;
+};
/*
* This module handles symbol table manipulation. All text strings
* back to a text string handle by get_symtab_handle().
*/
+//! Initialises the symbol table symtab.
void open_symtab(t_symtab* symtab);
-/* Initialises the symbol table symtab.
- */
-void close_symtab(t_symtab* symtab);
-/* Undoes the effect of open_symtab(), after invoking this function,
- * no value can be added to the symbol table, only values can be
- * retrieved using get_symtab().
+/*! \brief
+ * Undoes the effect of open_symtab()
+ *
+ * After invoking this function, no value can be added to the
+ * symbol table, only values can be retrieved using get_symtab_handle().
*
* Note that this does no work.
+ * \param[inout] symtab Symbol table to close.
*/
+void close_symtab(t_symtab* symtab);
/*! \brief Returns a deep copy of \c symtab. */
t_symtab* duplicateSymtab(const t_symtab* symtab);
+//! Frees the space allocated by the symbol table itself.
void free_symtab(t_symtab* symtab);
-/* Frees the space allocated by the symbol table itself */
+//! Frees the space allocated by the symbol table, including all entries in it.
void done_symtab(t_symtab* symtab);
-/* Frees the space allocated by the symbol table, including all
- * entries in it */
-
-char** put_symtab(t_symtab* symtab, const char* name);
-/* Enters a string into the symbol table symtab, if it was not
- * available, a reference to a copy is returned else a reference
- * to the earlier entered value is returned. Strings are trimmed
- * of spaces.
- */
-int lookup_symtab(t_symtab* symtab, char** name);
-/* Returns a unique handle for **name, without a memory reference.
- * It is a failure when name cannot be found in the symbol table,
- * it should be entered before with put_symtab().
+/*! \brief
+ * Enters a string into the symbol table.
+ *
+ * If the string \p name was not present before, a reference to a copy is returned,
+ * else a reference to the earlier entered value is returned. Strings are trimmed of spaces.
+ *
+ * \param[inout] symtab Symbol table to add string to.
+ * \param[in] name String to add.
+ * \returns Pointer to entry of string in symtab.
*/
+char** put_symtab(t_symtab* symtab, const char* name);
-char** get_symtab_handle(t_symtab* symtab, int name);
-/* Returns a text string handle for name. Name should be a value
- * returned from lookup_symtab(). So get_symtab_handle() and
- * lookup_symtab() are inverse functions.
+/*! \brief
+ * Returns unique handle for \p name.
+ *
+ * Looks up the string pointer \p name in the symbol table and returns the
+ * index in it to the matching entry. Gives fatal error if \p name is
+ * not found. \p name has to be entered first using put_symtab().
+ *
+ * \param[in] symtab Symbol table to search.
+ * \param[in] name String pointer into \p symtab.
+ * \returns Unique index to position in symbol table.
*/
+int lookup_symtab(t_symtab* symtab, char** name);
-long wr_symtab(FILE* fp, t_symtab* symtab);
-/* Writes the symbol table symtab to the file, specified by fp.
- * The function returns the number of bytes written.
+/*! \brief
+ * Returns text string corresponding to \p index.
+ *
+ * \p index needs to be value obtained from call to lookup_symtab().
+ * get_symtab_handle() and lookup_symtab() are inverse functions.
+ *
+ * \param[in] symtab Symbol table to search.
+ * \param[in] index Entry to find in table.
+ * \returns String pointer into \p symtab corresponding to the entry.
*/
+char** get_symtab_handle(t_symtab* symtab, int index);
-long rd_symtab(FILE* fp, t_symtab* symtab);
-/* Reads the symbol table symtab from the file, specified by fp.
- * This will include allocating the needed space. The function
- * returns the number of bytes read. The symtab is in the closed
- * state afterwards, so no strings can be added to it.
+/*! \brief
+ * Prints human readable form of \p symtab.
+ *
+ * \param[in] fp File to print to.
+ * \param[in] indent Number of spaces to use for indentation.
+ * \param[in] title Name for header text.
+ * \param[in] symtab Symbol table to print out.
*/
-
void pr_symtab(FILE* fp, int indent, const char* title, t_symtab* symtab);
-/* This routine prints out a (human) readable representation of
- * the symbol table symtab to the file fp. Ident specifies the
- * number of spaces the text should be indented. Title is used
- * to print a header text.
- */
#endif
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2019, by the GROMACS development team, led by
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(TopologyTest topology-test
- exclusionblocks.cpp
- mtop.cpp
- symtab.cpp)
+ CPP_SOURCE_FILES
+ exclusionblocks.cpp
+ mtop.cpp
+ symtab.cpp
+ )
#include "gromacs/topology/exclusionblocks.h"
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "gromacs/topology/block.h"
#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/smalloc.h"
#include "testutils/cmdlinetest.h"
addGroupToBlocka(ba, indices);
}
+//! Return ListOfLists filled with some datastructures
+ListOfLists<int> makeTestListOfLists()
+{
+ ListOfLists<int> list;
+
+ std::vector<int> indices = { 12, 11, 9, 6, 2 };
+ list.pushBack(indices);
+ indices = { 10, 8, 5, 1 };
+ list.pushBack(indices);
+ indices = { 7, 4, 0 };
+ list.pushBack(indices);
+
+ return list;
+}
+
class ExclusionBlockTest : public ::testing::Test
{
public:
{
const int natom = 3;
makeTestBlockAData(&ba_);
+ list_ = makeTestListOfLists();
b_.resize(natom);
}
~ExclusionBlockTest() override { done_blocka(&ba_); }
}
}
+ void compareBlocksAndList()
+ {
+ GMX_RELEASE_ASSERT(ssize(b_) == list_.ssize(), "The list counts should match");
+ for (index i = 0; i < ssize(b_); i++)
+ {
+ gmx::ArrayRef<const int> jList = list_[i];
+ ASSERT_EQ(b_[i].nra(), jList.ssize()) << "Block size mismatch at " << i << ".";
+ EXPECT_THAT(b_[i].atomNumber, ::testing::Pointwise(::testing::Eq(), jList));
+ }
+ }
+
protected:
t_blocka ba_;
+ ListOfLists<int> list_;
std::vector<ExclusionBlock> b_;
};
TEST_F(ExclusionBlockTest, MergeExclusions)
{
- mergeExclusions(&ba_, b_);
- compareBlocks();
+ mergeExclusions(&list_, b_);
+ compareBlocksAndList();
}
} // namespace
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Sequence Name="Complete dump of SymbolTable">
+ <Int Name="Length">8</Int>
+ <String>Symtab[0]="0"</String>
+ <String>Symtab[1]="1"</String>
+ <String>Symtab[2]="2"</String>
+ <String>Symtab[3]="3"</String>
+ <String>Symtab[4]="4"</String>
+ <String>Symtab[5]="5"</String>
+ <String>Symtab[6]="6"</String>
+ <String>Symtab[7]="foobar"</String>
+ </Sequence>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Sequence Name="Complete dump of SymbolTable">
+ <Int Name="Length">15</Int>
+ <String>Symtab[0]="0"</String>
+ <String>Symtab[1]="1"</String>
+ <String>Symtab[2]="2"</String>
+ <String>Symtab[3]="3"</String>
+ <String>Symtab[4]="4"</String>
+ <String>Symtab[5]="5"</String>
+ <String>Symtab[6]="6"</String>
+ <String>Symtab[7]="baz"</String>
+ <String>Symtab[8]="7"</String>
+ <String>Symtab[9]="8"</String>
+ <String>Symtab[10]="9"</String>
+ <String>Symtab[11]="10"</String>
+ <String>Symtab[12]="11"</String>
+ <String>Symtab[13]="12"</String>
+ <String>Symtab[14]="13"</String>
+ </Sequence>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (8):
+ Test title[0]="0"
+ Test title[1]="1"
+ Test title[2]="2"
+ Test title[3]="3"
+ Test title[4]="4"
+ Test title[5]="5"
+ Test title[6]="6"
+ Test title[7]="foobar"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (1):
+ Test title[0]="foo"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (2):
+ Test title[0]="foo"
+ Test title[1]="Bar"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (1):
+ Test title[0]="foo"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (1):
+ Test title[0]="foo"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (15):
+ Test title[0]="0"
+ Test title[1]="1"
+ Test title[2]="2"
+ Test title[3]="3"
+ Test title[4]="4"
+ Test title[5]="5"
+ Test title[6]="6"
+ Test title[7]="baz"
+ Test title[8]="7"
+ Test title[9]="8"
+ Test title[10]="9"
+ Test title[11]="10"
+ Test title[12]="11"
+ Test title[13]="12"
+ Test title[14]="13"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (1):
+ Test title[0]="foo"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (1):
+ Test title[0]="foo"
+]]></String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="Output"><![CDATA[
+ Test title (3):
+ Test title[0]="foo"
+ Test title[1]="Bar"
+ Test title[2]="Foo"
+]]></String>
+</ReferenceData>
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <gtest/gtest.h>
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/inmemoryserializer.h"
#include "gromacs/utility/strconvert.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textreader.h"
#include "testutils/refdata.h"
+#include "testutils/testfilemanager.h"
namespace gmx
{
namespace test
{
+class StringTableTest : public ::testing::Test
+{
+public:
+ StringTableTest() {}
+ //! Get handle to symbol table.
+ StringTableBuilder& builder() { return stringTableBuilder_; }
+ /* \brief
+ * Check human readable format of the table.
+ * \todo change when table writing to users is done also with serializer.
+ * \parm[in] table The string table to check the serialization.
+ */
+ void checkTable(const StringTable& table);
+
+private:
+ //! Get reference checker using lazy initialization
+ TestReferenceChecker* checker()
+ {
+ if (!checker_)
+ {
+ checker_ = std::make_unique<TestReferenceChecker>(data_.rootChecker());
+ }
+ return checker_.get();
+ }
+ //! Symbol table for testing purposes.
+ StringTableBuilder stringTableBuilder_;
+ //! Handler for reference data.
+ TestReferenceData data_;
+ //! Handler for checking reference data.
+ std::unique_ptr<TestReferenceChecker> checker_;
+};
+
+void StringTableTest::checkTable(const StringTable& table)
+{
+ TestFileManager files;
+ std::string filename(files.getTemporaryFilePath("table.txt"));
+ FILE* fp = fopen(filename.c_str(), "w");
+ table.printStringTableStorageToFile(fp, 4, "Test title");
+ fclose(fp);
+ const std::string text = TextReader::readFileToString(filename);
+ checker()->checkTextBlock(text, "Output");
+}
+
+/*! \brief
+ * Check that symbols obtained from symtab compare correctly.
+ *
+ * Helper function to find out if two entries obtained by a symtab lookup
+ * are equivalent or not, according to testing criteria.
+ * Checks that the indices match before finalizing storage.
+ *
+ * \param[in] builder StringTableBuilder table that contains the entries to validate.
+ * \param[in] firstSymbol Handle into \p builder obtained from placing string in \p builder.
+ * \param[in] otherSymbol Other handle from obtained from separate string deposit.
+ * \param[in] expectedOutcome If the handles should result in equal entries or not.
+ */
+static void compareDifferentIndices(const StringTableBuilder& builder,
+ const StringTableEntry& firstSymbol,
+ const StringTableEntry& otherSymbol,
+ bool expectedOutcome)
+{
+ EXPECT_EQ(expectedOutcome, (firstSymbol == otherSymbol));
+ auto firstIndex = builder.findEntryByName(*firstSymbol);
+ auto otherIndex = builder.findEntryByName(*otherSymbol);
+ EXPECT_EQ(expectedOutcome, (firstIndex == otherIndex))
+ << "Expected was " << expectedOutcome << " firstIndex is " << firstIndex
+ << " otherIndex is " << otherIndex;
+}
+
+/*! \brief
+ * Helper to obtain the integer index from an entry.
+ *
+ * As the index is only used during (de-) serialization, use this machinery
+ * to obtain it.
+ *
+ * \param[in] symbol Single StringTableEntry to obtain the index of.
+ * \returns Integer index to be used to obtain value from StringTable.
+ */
+static int readIndexFromSerializer(const StringTableEntry& symbol)
+{
+ gmx::InMemorySerializer writer;
+ symbol.serialize(&writer);
+ auto buffer = writer.finishAndGetBuffer();
+ gmx::InMemoryDeserializer reader(buffer, false);
+ int index = 0;
+ reader.doInt(&index);
+ return index;
+}
+
+/*! \brief
+ * Helper function to check that a string in matches when looked up in non finalized table.
+ *
+ * Checks that a string looked up by using the index in the symbol table matches
+ * the string stored in the wrapper object obtained by entering a string.
+ *
+ * \param[in] symtab Symbol table that contains the entries.
+ * \param[in] symbol The entry obtained from placing a string in the symbol table.
+ * \param[in] string The string the entry should match.
+ */
+static void stringMatches(const StringTable& symtab, const StringTableEntry& symbol, const char* string)
+{
+ int index = readIndexFromSerializer(symbol);
+ auto entryFromIndex = symtab.at(index);
+
+ EXPECT_EQ(*entryFromIndex, string)
+ << "Index is " << index << " Entry from index is " << entryFromIndex->c_str();
+}
+
+
+TEST_F(StringTableTest, AddSingleEntry)
+{
+ builder().addString("foo");
+ StringTable table = builder().build();
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, CanAccessWithAt)
+{
+ builder().addString("foo");
+ StringTable table = builder().build();
+ EXPECT_NO_THROW(table.at(0));
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, CanAccessWithBracket)
+{
+ builder().addString("foo");
+ StringTable table = builder().build();
+ checkTable(table);
+ auto entry = table[0];
+ EXPECT_EQ(*entry, "foo");
+}
+
+TEST_F(StringTableTest, ThrowsOutOfRange)
+{
+ builder().addString("foo");
+ StringTable table = builder().build();
+ EXPECT_THROW(table.at(1), InternalError);
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, StringCompareIsCorrect)
+{
+ auto fooSymbol = builder().addString("foo");
+ StringTable table = builder().build();
+ stringMatches(table, fooSymbol, "foo");
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, AddTwoDistinctEntries)
+{
+ auto fooSymbol = builder().addString("foo");
+ auto barSymbol = builder().addString("Bar");
+
+ EXPECT_FALSE(fooSymbol == barSymbol);
+ compareDifferentIndices(builder(), fooSymbol, barSymbol, false);
+ EXPECT_TRUE("foo" == *fooSymbol);
+ EXPECT_TRUE("Bar" == *barSymbol);
+ auto table = builder().build();
+ stringMatches(table, fooSymbol, "foo");
+ stringMatches(table, barSymbol, "Bar");
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, TryToAddDuplicates)
+{
+ auto fooSymbol = builder().addString("foo");
+ auto barSymbol = builder().addString("Bar");
+
+ EXPECT_FALSE(fooSymbol == barSymbol);
+ EXPECT_FALSE(fooSymbol->empty());
+ compareDifferentIndices(builder(), fooSymbol, barSymbol, false);
+ EXPECT_TRUE("foo" == *fooSymbol);
+ EXPECT_TRUE("Bar" == *barSymbol);
+
+ // Insert a duplicate element
+ auto anotherFooSymbol = builder().addString("foo");
+ // Insert element with different case
+ auto capitalFooSymbol = builder().addString("Foo");
+
+ // Check that no duplicate is made
+ EXPECT_TRUE(fooSymbol == anotherFooSymbol);
+ // Check case sensitivity
+ EXPECT_FALSE(fooSymbol == capitalFooSymbol);
+
+ // Check that underlying representation is same
+ EXPECT_TRUE("foo" == *anotherFooSymbol);
+ EXPECT_TRUE("foo" == *fooSymbol);
+ EXPECT_FALSE(*fooSymbol == *capitalFooSymbol);
+ EXPECT_TRUE("Bar" == *barSymbol);
+
+ // Check for correct behaviours with new and old symbols
+ compareDifferentIndices(builder(), fooSymbol, anotherFooSymbol, true);
+ compareDifferentIndices(builder(), barSymbol, anotherFooSymbol, false);
+ compareDifferentIndices(builder(), fooSymbol, barSymbol, false);
+ compareDifferentIndices(builder(), fooSymbol, capitalFooSymbol, false);
+ auto table = builder().build();
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, AddLargeNumberOfEntries)
+{
+ int numStringsToAdd = 7; // Random number of strings.
+ std::vector<StringTableEntry> symbolsAdded;
+ symbolsAdded.reserve(numStringsToAdd);
+ for (int i = 0; i < numStringsToAdd; ++i)
+ {
+ symbolsAdded.push_back(builder().addString(toString(i)));
+ }
+ for (int i = 0; i < numStringsToAdd; ++i)
+ {
+ EXPECT_TRUE(toString(i) == *symbolsAdded[i]) << "index is " << i;
+ }
+ // Add something unrelated and check that indices still work afterward.
+ builder().addString("foobar");
+ for (int i = 0; i < numStringsToAdd; ++i)
+ {
+ EXPECT_TRUE(toString(i) == *symbolsAdded[i]) << "index is " << i;
+ }
+ auto table = builder().build();
+ for (int i = 0; i < numStringsToAdd; ++i)
+ {
+ stringMatches(table, symbolsAdded[i], toString(i).c_str());
+ }
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, NoDuplicatesInLargeTable)
+{
+ int halfOfStringsToAdd = 7; // Random number of strings.
+ int totalNumStringsToAdd = 2 * halfOfStringsToAdd;
+ std::vector<StringTableEntry> symbolsAdded;
+ symbolsAdded.reserve(halfOfStringsToAdd);
+ for (int i = 0; i < halfOfStringsToAdd; ++i)
+ {
+ symbolsAdded.push_back(builder().addString(toString(i)));
+ }
+
+ // We now try to mess around in the symtab.
+ auto bazSymbol = builder().addString("baz");
+
+ // Now try to add more symbols, also including those that are already there.
+ for (int i = 0; i < totalNumStringsToAdd; i++)
+ {
+ symbolsAdded.push_back(builder().addString(toString(i)));
+ }
+
+ //! Check that entries that should be equal are, and new ones are not.
+ for (int i = 0; i < halfOfStringsToAdd; i++)
+ {
+ compareDifferentIndices(builder(), symbolsAdded[i], symbolsAdded[halfOfStringsToAdd + i], true);
+ compareDifferentIndices(builder(), symbolsAdded[i], symbolsAdded[2 * halfOfStringsToAdd + i], false);
+ compareDifferentIndices(builder(), symbolsAdded[i], bazSymbol, false);
+ }
+ EXPECT_TRUE("baz" == *bazSymbol);
+ symbolsAdded.emplace_back(bazSymbol);
+ auto table = builder().build();
+ checkTable(table);
+}
+
+TEST_F(StringTableTest, CanWriteToBuffer)
+{
+ builder().addString("foo");
+ builder().addString("bar");
+ builder().addString("baz");
+ auto finalTable = builder().build();
+ InMemorySerializer writer;
+ finalTable.serializeStringTable(&writer);
+
+ auto buffer = writer.finishAndGetBuffer();
+ EXPECT_EQ(buffer.size(), 37); // 4 (size) + 3*(8 (string size) + 3*1 (char size) )
+}
+
+TEST_F(StringTableTest, Roundtrip)
+{
+ // First generate a buffer from a string table
+ builder().addString("foo");
+ builder().addString("bar");
+ builder().addString("baz");
+ auto finalTable = builder().build();
+ InMemorySerializer writer;
+ finalTable.serializeStringTable(&writer);
+
+ auto buffer = writer.finishAndGetBuffer();
+ EXPECT_EQ(buffer.size(), 37); // 4 (size) + 3*(8 (string size) + 3*1 (char size) )
+
+ // Now try to make a new table from it.
+ InMemoryDeserializer reader(buffer, false);
+ StringTable readInTable(&reader);
+ EXPECT_EQ(*(finalTable.at(0)), *(readInTable.at(0)));
+ EXPECT_EQ(*(finalTable.at(1)), *(readInTable.at(1)));
+ EXPECT_EQ(*(finalTable.at(2)), *(readInTable.at(2)));
+}
+
+TEST_F(StringTableTest, RoundtripWithCorrectStringIndices)
+{
+ std::vector<StringTableEntry> testEntries;
+ // First generate a buffer from a string table
+ testEntries.emplace_back(builder().addString("foo"));
+ testEntries.emplace_back(builder().addString("bar"));
+ testEntries.emplace_back(builder().addString("baz"));
+ auto finalTable = builder().build();
+ InMemorySerializer writer;
+ finalTable.serializeStringTable(&writer);
+ for (const auto& stringEntry : testEntries)
+ {
+ stringEntry.serialize(&writer);
+ }
+
+ auto buffer = writer.finishAndGetBuffer();
+ EXPECT_EQ(buffer.size(), 49); // 4 (size) + 3*(8 (string size) + 3*1 (char size) + 3*4 (int size))
+
+ // Now try to make a new table from it.
+ InMemoryDeserializer reader(buffer, false);
+ StringTable readInTable(&reader);
+ std::vector<StringTableEntry> deserializedEntries;
+ for (index gmx_unused i = 0; i < gmx::ssize(testEntries); i++)
+ {
+ deserializedEntries.emplace_back(readStringTableEntry(&reader, readInTable));
+ }
+ EXPECT_EQ(*(finalTable.at(0)), *(deserializedEntries[0]));
+ EXPECT_EQ(*(finalTable.at(1)), *(deserializedEntries[1]));
+ EXPECT_EQ(*(finalTable.at(2)), *(deserializedEntries[2]));
+}
+
+
namespace
{
-class SymtabTest : public ::testing::Test
+class LegacySymtabTest : public ::testing::Test
{
public:
- SymtabTest() { open_symtab(&symtab_); }
- ~SymtabTest() override
+ LegacySymtabTest() { open_symtab(&symtab_); }
+ ~LegacySymtabTest() override
{
done_symtab(&symtab_);
EXPECT_EQ(symtab_.nr, 0);
std::unique_ptr<TestReferenceChecker> checker_;
};
-void SymtabTest::dumpSymtab()
+void LegacySymtabTest::dumpSymtab()
{
int nr = symtab_.nr;
t_symbuf* symbuf = symtab_.symbuf;
EXPECT_EQ(expectedOutcome, entriesAreEqual(symtab, otherSymbol, firstIndex));
}
-TEST_F(SymtabTest, EmptyOnOpen)
+TEST_F(LegacySymtabTest, EmptyOnOpen)
{
ASSERT_EQ(0, symtab()->nr);
ASSERT_EQ(nullptr, symtab()->symbuf);
}
-TEST_F(SymtabTest, AddSingleEntry)
+TEST_F(LegacySymtabTest, AddSingleEntry)
{
auto fooSymbol = put_symtab(symtab(), "Foo");
ASSERT_EQ(1, symtab()->nr);
EXPECT_STREQ("Foo", *fooSymbol);
}
-TEST_F(SymtabTest, AddTwoDistinctEntries)
+TEST_F(LegacySymtabTest, AddTwoDistinctEntries)
{
auto fooSymbol = put_symtab(symtab(), "Foo");
auto barSymbol = put_symtab(symtab(), "Bar");
EXPECT_STREQ("Bar", *barSymbol);
}
-TEST_F(SymtabTest, TryToAddDuplicates)
+TEST_F(LegacySymtabTest, TryToAddDuplicates)
{
auto fooSymbol = put_symtab(symtab(), "Foo");
auto barSymbol = put_symtab(symtab(), "Bar");
compareDifferentHandles(symtab(), fooSymbol, barSymbol, false);
}
-TEST_F(SymtabTest, AddLargeNumberOfEntries)
+TEST_F(LegacySymtabTest, AddLargeNumberOfEntries)
{
int numStringsToAdd = 7; // Larger than c_maxBufSize limit for size of symbuf.
std::vector<char**> symbolsAdded;
dumpSymtab();
}
-TEST_F(SymtabTest, NoDuplicatesInLargeTable)
+TEST_F(LegacySymtabTest, NoDuplicatesInLargeTable)
{
int halfOfStringsToAdd = 7; // Larger than c_maxBufSize limit for size of symbuf.
int totalNumStringsToAdd = 2 * halfOfStringsToAdd;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
init_atom(&(top->atoms));
init_atomtypes(&(top->atomtypes));
init_block(&top->mols);
- init_blocka(&top->excls);
open_symtab(&top->symtab);
}
-gmx_moltype_t::gmx_moltype_t() : name(nullptr), excls()
+gmx_moltype_t::gmx_moltype_t() : name(nullptr)
{
init_t_atoms(&atoms, 0, FALSE);
}
gmx_moltype_t::~gmx_moltype_t()
{
done_atom(&atoms);
- done_blocka(&excls);
}
gmx_mtop_t::gmx_mtop_t()
done_symtab(&(top->symtab));
done_block(&(top->mols));
- done_blocka(&(top->excls));
}
void done_top_mtop(t_topology* top, gmx_mtop_t* mtop)
{
done_idef(&top->idef);
done_atom(&top->atoms);
- done_blocka(&top->excls);
done_block(&top->mols);
done_symtab(&top->symtab);
open_symtab(&mtop->symtab);
}
}
-gmx_localtop_t::gmx_localtop_t()
-{
- init_blocka_null(&excls);
- init_idef(&idef);
- init_atomtypes(&atomtypes);
-}
-
-gmx_localtop_t::~gmx_localtop_t()
-{
- if (!useInDomainDecomp_)
- {
- done_idef(&idef);
- done_blocka(&excls);
- done_atomtypes(&atomtypes);
- }
-}
+gmx_localtop_t::gmx_localtop_t(const gmx_ffparams_t& ffparams) : idef(ffparams) {}
bool gmx_mtop_has_masses(const gmx_mtop_t* mtop)
{
pr_indent(fp, indent);
fprintf(fp, "name=\"%s\"\n", *(molt->name));
pr_atoms(fp, indent, "atoms", &(molt->atoms), bShowNumbers);
- pr_blocka(fp, indent, "excls", &molt->excls, bShowNumbers);
+ pr_listoflists(fp, indent, "excls", &molt->excls, bShowNumbers);
for (j = 0; (j < F_NRE); j++)
{
pr_ilist(fp, indent, interaction_function[j].longname, ffparams->functype.data(),
pr_block(fp, indent, "mols", &top->mols, bShowNumbers);
pr_str(fp, indent, "bIntermolecularInteractions",
gmx::boolToString(top->bIntermolecularInteractions));
- pr_blocka(fp, indent, "excls", &top->excls, bShowNumbers);
pr_idef(fp, indent, "idef", &top->idef, bShowNumbers, bShowParameters);
}
}
}
}
-static void cmp_blocka(FILE* fp, const t_blocka* b1, const t_blocka* b2, const char* s)
+static void cmp_listoflists(FILE* fp,
+ const gmx::ListOfLists<int>& list1,
+ const gmx::ListOfLists<int>& list2,
+ const char* s)
{
char buf[32];
fprintf(fp, "comparing blocka %s\n", s);
- sprintf(buf, "%s.nr", s);
- cmp_int(fp, buf, -1, b1->nr, b2->nr);
- sprintf(buf, "%s.nra", s);
- cmp_int(fp, buf, -1, b1->nra, b2->nra);
+ sprintf(buf, "%s.numLists", s);
+ cmp_int(fp, buf, -1, list1.ssize(), list2.ssize());
+ sprintf(buf, "%s.numElements", s);
+ cmp_int(fp, buf, -1, list1.numElements(), list2.numElements());
}
static void compareFfparams(FILE* fp,
compareAtoms(fp, &mt1[i].atoms, &mt2[i].atoms, relativeTolerance, absoluteTolerance);
compareInteractionLists(fp, &mt1[i].ilist, &mt2[i].ilist);
std::string buf = gmx::formatString("excls[%d]", i);
- cmp_blocka(fp, &mt1[i].excls, &mt2[i].excls, buf.c_str());
+ cmp_listoflists(fp, mt1[i].excls, mt2[i].excls, buf.c_str());
}
}
void copy_moltype(const gmx_moltype_t* src, gmx_moltype_t* dst)
{
- dst->name = src->name;
- copy_blocka(&src->excls, &dst->excls);
+ dst->name = src->name;
+ dst->excls = src->excls;
t_atoms* atomsCopy = copy_t_atoms(&src->atoms);
dst->atoms = *atomsCopy;
sfree(atomsCopy);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/topology/idef.h"
#include "gromacs/topology/symtab.h"
#include "gromacs/utility/enumerationhelpers.h"
+#include "gromacs/utility/listoflists.h"
#include "gromacs/utility/unique_cptr.h"
enum class SimulationAtomGroupType : int
/*! \brief Default copy constructor */
gmx_moltype_t(const gmx_moltype_t&) = default;
- char** name; /**< Name of the molecule type */
- t_atoms atoms; /**< The atoms in this molecule */
- InteractionLists ilist; /**< Interaction list with local indices */
- t_blocka excls; /**< The exclusions */
+ char** name; /**< Name of the molecule type */
+ t_atoms atoms; /**< The atoms in this molecule */
+ InteractionLists ilist; /**< Interaction list with local indices */
+ gmx::ListOfLists<int> excls; /**< The exclusions */
};
/*! \brief Block of molecules of the same type, used in gmx_mtop_t */
*/
int numberOfGroupNumbers(SimulationAtomGroupType group) const
{
- return gmx::ssize(groupNumbers[group]);
+ return static_cast<int>(groupNumbers[group].size());
}
};
struct gmx_localtop_t
{
//! Constructor used for normal operation, manages own resources.
- gmx_localtop_t();
-
- ~gmx_localtop_t();
+ gmx_localtop_t(const gmx_ffparams_t& ffparams);
//! The interaction function definition
- t_idef idef;
- //! Atomtype properties
- t_atomtypes atomtypes;
+ InteractionDefinitions idef;
//! The exclusions
- t_blocka excls;
- //! Flag for domain decomposition so we don't free already freed memory.
- bool useInDomainDecomp_ = false;
+ gmx::ListOfLists<int> excls;
};
/* The old topology struct, completely written out, used in analysis tools */
t_atomtypes atomtypes; /* Atomtype properties */
t_block mols; /* The molecules */
gmx_bool bIntermolecularInteractions; /* Inter.mol. int. ? */
- t_blocka excls; /* The exclusions */
- t_symtab symtab; /* The symbol table */
+ /* Note that the exclusions are not stored in t_topology */
+ t_symtab symtab; /* The symbol table */
} t_topology;
void init_top(t_topology* top);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2008, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return bPert;
}
-void gmx_sort_ilist_fe(t_idef* idef, const real* qA, const real* qB)
+void gmx_sort_ilist_fe(InteractionDefinitions* idef, const real* qA, const real* qB)
{
int ftype, nral, i, ic, ib, a;
- t_ilist* ilist;
- t_iatom* iatoms;
t_iatom* iabuf;
int iabuf_nalloc;
iabuf_nalloc = 0;
iabuf = nullptr;
- const t_iparams* iparams = idef->iparams;
-
for (ftype = 0; ftype < F_NRE; ftype++)
{
if (interaction_function[ftype].flags & IF_BOND)
{
- ilist = &idef->il[ftype];
- iatoms = ilist->iatoms;
- nral = NRAL(ftype);
- ic = 0;
- ib = 0;
- i = 0;
- while (i < ilist->nr)
+ InteractionList* ilist = &idef->il[ftype];
+ int* iatoms = ilist->iatoms.data();
+ nral = NRAL(ftype);
+ ic = 0;
+ ib = 0;
+ i = 0;
+ while (i < ilist->size())
{
/* Check if this interaction is perturbed */
- if (ip_q_pert(ftype, iatoms + i, iparams, qA, qB))
+ if (ip_q_pert(ftype, iatoms + i, idef->iparams.data(), qA, qB))
{
/* Copy to the perturbed buffer */
if (ib + 1 + nral > iabuf_nalloc)
}
}
}
- /* Now we now the number of non-perturbed interactions */
- ilist->nr_nonperturbed = ic;
+ /* Now we know the number of non-perturbed interactions */
+ idef->numNonperturbedInteractions[ftype] = ic;
/* Copy the buffer with perturbed interactions to the ilist */
for (a = 0; a < ib; a++)
if (debug)
{
+ const int numNonperturbed = idef->numNonperturbedInteractions[ftype];
fprintf(debug, "%s non-pert %d pert %d\n", interaction_function[ftype].longname,
- ilist->nr_nonperturbed, ilist->nr - ilist->nr_nonperturbed);
+ numNonperturbed, ilist->size() - numNonperturbed);
}
}
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2008,2009,2010,2013,2014,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2008,2009,2010,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/real.h"
struct gmx_mtop_t;
-struct t_idef;
+class InteractionDefinitions;
/* Returns if there are perturbed bonded interactions */
gmx_bool gmx_mtop_bondeds_free_energy(const struct gmx_mtop_t* mtop);
/* Sort all the bonded ilists in idef to have the perturbed ones at the end
* and set nr_nr_nonperturbed in ilist.
*/
-void gmx_sort_ilist_fe(struct t_idef* idef, const real* qA, const real* qB);
+void gmx_sort_ilist_fe(InteractionDefinitions* idef, const real* qA, const real* qB);
#endif
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return frame_.time;
}
-int TrajectoryFrame::pbc() const
+PbcType TrajectoryFrame::pbc() const
{
- return frame_.ePBC;
+ return frame_.pbcType;
}
ArrayRef<const RVec> TrajectoryFrame::x() const
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/real.h"
struct t_atoms;
+enum class PbcType : int;
typedef struct t_trxframe // NOLINT (clang-analyzer-optin.performance.Padding)
{
gmx_bool bBox;
matrix box; /* the 3 box vectors */
gmx_bool bPBC;
- int ePBC; /* the type of pbc */
+ PbcType pbcType; /* the type of pbc */
gmx_bool bIndex;
int* index; /* atom indices of contained coordinates */
} t_trxframe;
//! Time read from the trajectory file frame.
double time() const;
//! The PBC characteristics of the box.
- int pbc() const;
+ PbcType pbc() const;
//! Get a view of position coordinates of the frame (which could be empty).
ArrayRef<const RVec> x() const;
//! Get a view of velocity coordinates of the frame (which could be empty).
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2013,2014,2015,2018 by the GROMACS development team.
+# Copyright (c) 2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
const SelectionCollection& selections);
//! Checks whether the given AnalysisData has been initialized.
- bool isInitialized(const AnalysisData& data) const;
+ static bool isInitialized(const AnalysisData& data);
//! Keeps a data handle for each AnalysisData object.
HandleContainer handles_;
}
}
-bool TrajectoryAnalysisModuleData::Impl::isInitialized(const AnalysisData& data) const
+bool TrajectoryAnalysisModuleData::Impl::isInitialized(const AnalysisData& data)
{
for (int i = 0; i < data.dataSetCount(); ++i)
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Does not throw.
*/
- Selection parallelSelection(const Selection& selection);
+ static Selection parallelSelection(const Selection& selection);
/*! \brief
* Returns a set of selection that corresponds to the given selections.
*
*
* \see parallelSelection()
*/
- SelectionList parallelSelections(const SelectionList& selections);
+ static SelectionList parallelSelections(const SelectionList& selections);
protected:
/*! \brief
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
public:
//! Initializes the default values for the settings object.
Impl() :
- timeUnit(TimeUnit_Default),
+ timeUnit(TimeUnit::Default),
flags(0),
frflags(0),
bRmPBC(true),
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_trxframe& frame = common_.frame();
if (ppbc != nullptr)
{
- set_pbc(ppbc, topology.ePBC(), frame.box);
+ set_pbc(ppbc, topology.pbcType(), frame.box);
}
selections_.evaluate(&frame, ppbc);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/trajectory/trajectoryframe.h"
#include "gromacs/trajectoryanalysis/analysissettings.h"
#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/enumerationhelpers.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
*/
//! How to interpret the selections in -group1.
-enum Group1Type
+enum class Group1Type : int
{
- Group1Type_Angle,
- Group1Type_Dihedral,
- Group1Type_Vector,
- Group1Type_Plane
+ Angle,
+ Dihedral,
+ Vector,
+ Plane,
+ Count
};
//! How to interpret the selections in -group2.
-enum Group2Type
+enum class Group2Type : int
{
- Group2Type_None,
- Group2Type_Vector,
- Group2Type_Plane,
- Group2Type_TimeZero,
- Group2Type_Z,
- Group2Type_SphereNormal
+ None,
+ Vector,
+ Plane,
+ TimeZero,
+ Z,
+ SphereNormal,
+ Count
};
//! String values corresponding to Group1Type.
-const char* const cGroup1TypeEnum[] = { "angle", "dihedral", "vector", "plane" };
+const EnumerationArray<Group1Type, const char*> c_group1TypeEnumNames = { { "angle", "dihedral",
+ "vector", "plane" } };
//! String values corresponding to Group2Type.
-const char* const cGroup2TypeEnum[] = { "none", "vector", "plane", "t0", "z", "sphnorm" };
+const EnumerationArray<Group2Type, const char*> c_group2TypeEnumNames = {
+ { "none", "vector", "plane", "t0", "z", "sphnorm" }
+};
class Angle : public TrajectoryAnalysisModule
{
Angle::Angle() :
sel1info_(nullptr),
sel2info_(nullptr),
- g1type_(Group1Type_Angle),
- g2type_(Group2Type_None),
+ g1type_(Group1Type::Angle),
+ g2type_(Group2Type::None),
binWidth_(1.0),
natoms1_(0),
natoms2_(0)
.defaultBasename("anghist")
.description("Histogram of the angles"));
+ options->addOption(EnumOption<Group1Type>("g1")
+ .enumValue(c_group1TypeEnumNames)
+ .store(&g1type_)
+ .description("Type of analysis/first vector group"));
options->addOption(
- EnumOption<Group1Type>("g1").enumValue(cGroup1TypeEnum).store(&g1type_).description("Type of analysis/first vector group"));
- options->addOption(
- EnumOption<Group2Type>("g2").enumValue(cGroup2TypeEnum).store(&g2type_).description("Type of second vector group"));
+ EnumOption<Group2Type>("g2").enumValue(c_group2TypeEnumNames).store(&g2type_).description("Type of second vector group"));
options->addOption(
DoubleOption("binw").store(&binWidth_).description("Binwidth for -oh in degrees"));
void Angle::optionsFinished(TrajectoryAnalysisSettings* /* settings */)
{
- const bool bSingle = (g1type_ == Group1Type_Angle || g1type_ == Group1Type_Dihedral);
+ const bool bSingle = (g1type_ == Group1Type::Angle || g1type_ == Group1Type::Dihedral);
- if (bSingle && g2type_ != Group2Type_None)
+ if (bSingle && g2type_ != Group2Type::None)
{
GMX_THROW(
InconsistentInputError("Cannot use a second group (-g2) with "
InconsistentInputError("Cannot provide a second selection "
"(-group2) with -g1 angle or dihedral"));
}
- if (!bSingle && g2type_ == Group2Type_None)
+ if (!bSingle && g2type_ == Group2Type::None)
{
GMX_THROW(
InconsistentInputError("Should specify a second group (-g2) "
// Set up the number of positions per angle.
switch (g1type_)
{
- case Group1Type_Angle: natoms1_ = 3; break;
- case Group1Type_Dihedral: natoms1_ = 4; break;
- case Group1Type_Vector: natoms1_ = 2; break;
- case Group1Type_Plane: natoms1_ = 3; break;
+ case Group1Type::Angle: natoms1_ = 3; break;
+ case Group1Type::Dihedral: natoms1_ = 4; break;
+ case Group1Type::Vector: natoms1_ = 2; break;
+ case Group1Type::Plane: natoms1_ = 3; break;
default: GMX_THROW(InternalError("invalid -g1 value"));
}
switch (g2type_)
{
- case Group2Type_None: natoms2_ = 0; break;
- case Group2Type_Vector: natoms2_ = 2; break;
- case Group2Type_Plane: natoms2_ = 3; break;
- case Group2Type_TimeZero: natoms2_ = 0; break;
- case Group2Type_Z: natoms2_ = 0; break;
- case Group2Type_SphereNormal: natoms2_ = 1; break;
+ case Group2Type::None: natoms2_ = 0; break;
+ case Group2Type::Vector: natoms2_ = 2; break;
+ case Group2Type::Plane: natoms2_ = 3; break;
+ case Group2Type::TimeZero: // Intended to fall through
+ case Group2Type::Z: natoms2_ = 0; break;
+ case Group2Type::SphereNormal: natoms2_ = 1; break;
default: GMX_THROW(InternalError("invalid -g2 value"));
}
if (natoms2_ == 0 && sel2info_->isSet())
"divisible by %d",
static_cast<int>(g + 1), natoms2_)));
}
- if (g2type_ == Group2Type_SphereNormal && posCount2 != 1)
+ if (g2type_ == Group2Type::SphereNormal && posCount2 != 1)
{
GMX_THROW(InconsistentInputError(
"The second group should contain a single position with -g2 sphnorm"));
{
angles_.setColumnCount(i, angleCount_[i]);
}
- double histogramMin = (g1type_ == Group1Type_Dihedral ? -180.0 : 0);
+ double histogramMin = (g1type_ == Group1Type::Dihedral ? -180.0 : 0);
histogramModule_->init(histogramFromRange(histogramMin, 180.0).binWidth(binWidth_).includeAll());
- if (g2type_ == Group2Type_TimeZero)
+ if (g2type_ == Group2Type::TimeZero)
{
vt0_.resize(sel1_.size());
for (size_t g = 0; g < sel1_.size(); ++g)
void Angle::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryAnalysisModuleData* pdata)
{
AnalysisDataHandle dh = pdata->dataHandle(angles_);
- const SelectionList& sel1 = pdata->parallelSelections(sel1_);
- const SelectionList& sel2 = pdata->parallelSelections(sel2_);
+ const SelectionList& sel1 = TrajectoryAnalysisModuleData::parallelSelections(sel1_);
+ const SelectionList& sel2 = TrajectoryAnalysisModuleData::parallelSelections(sel2_);
checkSelections(sel1, sel2);
switch (g2type_)
{
- case Group2Type_Z: v2[ZZ] = 1.0; break;
- case Group2Type_SphereNormal: copy_rvec(sel2_[g].position(0).x(), c2); break;
+ case Group2Type::Z: v2[ZZ] = 1.0; break;
+ case Group2Type::SphereNormal: copy_rvec(sel2_[g].position(0).x(), c2); break;
default:
// do nothing
break;
iter1.getCurrentPositions(x);
switch (g1type_)
{
- case Group1Type_Angle:
+ case Group1Type::Angle:
if (pbc)
{
pbc_dx(pbc, x[0], x[1], v1);
}
angle = gmx_angle(v1, v2);
break;
- case Group1Type_Dihedral:
+ case Group1Type::Dihedral:
{
rvec dx[3];
if (pbc)
}
break;
}
- case Group1Type_Vector:
- case Group1Type_Plane:
+ case Group1Type::Vector:
+ case Group1Type::Plane:
calc_vec(natoms1_, x, pbc, v1, c1);
switch (g2type_)
{
- case Group2Type_Vector:
- case Group2Type_Plane:
+ case Group2Type::Vector:
+ case Group2Type::Plane:
iter2.getCurrentPositions(x);
calc_vec(natoms2_, x, pbc, v2, c2);
break;
- case Group2Type_TimeZero:
+ case Group2Type::TimeZero:
// FIXME: This is not parallelizable.
if (frnr == 0)
{
}
copy_rvec(vt0_[g][n], v2);
break;
- case Group2Type_Z: c1[XX] = c1[YY] = 0.0; break;
- case Group2Type_SphereNormal:
+ case Group2Type::Z: c1[XX] = c1[YY] = 0.0; break;
+ case Group2Type::SphereNormal:
if (pbc)
{
pbc_dx(pbc, c1, c2, v2);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/coordinateio/coordinatefile.h"
#include "gromacs/coordinateio/requirements.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/options/filenameoption.h"
#include "gromacs/options/ioptionscontainer.h"
#include "gromacs/selection/selectionoption.h"
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
AnalysisDataHandle distHandle = pdata->dataHandle(distances_);
AnalysisDataHandle xyzHandle = pdata->dataHandle(xyz_);
- const SelectionList& sel = pdata->parallelSelections(sel_);
+ const SelectionList& sel = TrajectoryAnalysisModuleData::parallelSelections(sel_);
checkSelections(sel);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/coordinateio/coordinatefile.h"
#include "gromacs/coordinateio/requirements.h"
+#include "gromacs/fileio/trxio.h"
#include "gromacs/options/filenameoption.h"
#include "gromacs/options/ioptionscontainer.h"
#include "gromacs/selection/selectionoption.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void FreeVolume::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryAnalysisModuleData* pdata)
{
AnalysisDataHandle dh = pdata->dataHandle(data_);
- const Selection& sel = pdata->parallelSelection(sel_);
+ const Selection& sel = TrajectoryAnalysisModuleData::parallelSelection(sel_);
gmx::UniformRealDistribution<real> dist;
GMX_RELEASE_ASSERT(nullptr != pbc, "You have no periodic boundary conditions");
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! \{
//! Enum value to store the selected value for `-type`.
-enum DistanceType
+enum class DistanceType : int
{
- eDistanceType_Min,
- eDistanceType_Max
+ Min,
+ Max,
+ Count
};
//! Enum value to store the selected value for `-refgrouping`/`-selgrouping`.
-enum GroupType
+enum class GroupType : int
{
- eGroupType_All,
- eGroupType_Residue,
- eGroupType_Molecule,
- eGroupType_None
+ All,
+ Residue,
+ Molecule,
+ None,
+ Count
};
//! Strings corresponding to DistanceType.
-const char* const c_distanceTypes[] = { "min", "max" };
+const EnumerationArray<DistanceType, const char*> c_distanceTypeNames = { { "min", "max" } };
//! Strings corresponding to GroupType.
-const char* const c_groupTypes[] = { "all", "res", "mol", "none" };
+const EnumerationArray<GroupType, const char*> c_groupTypeNames = { { "all", "res", "mol",
+ "none" } };
/*! \brief
* Implements `gmx pairdist` trajectory analysis module.
PairDistance::PairDistance() :
cutoff_(0.0),
- distanceType_(eDistanceType_Min),
- refGroupType_(eGroupType_All),
- selGroupType_(eGroupType_All),
+ distanceType_(DistanceType::Min),
+ refGroupType_(GroupType::All),
+ selGroupType_(GroupType::All),
refGroupCount_(0),
maxGroupCount_(0),
initialDist2_(0.0),
DoubleOption("cutoff").store(&cutoff_).description("Maximum distance to consider"));
options->addOption(EnumOption<DistanceType>("type")
.store(&distanceType_)
- .enumValue(c_distanceTypes)
+ .enumValue(c_distanceTypeNames)
.description("Type of distances to calculate"));
options->addOption(
EnumOption<GroupType>("refgrouping")
.store(&refGroupType_)
- .enumValue(c_groupTypes)
+ .enumValue(c_groupTypeNames)
.description("Grouping of -ref positions to compute the min/max over"));
options->addOption(
EnumOption<GroupType>("selgrouping")
.store(&selGroupType_)
- .enumValue(c_groupTypes)
+ .enumValue(c_groupTypeNames)
.description("Grouping of -sel positions to compute the min/max over"));
options->addOption(SelectionOption("ref").store(&refSel_).required().description(
}
//! Helper function to initialize the grouping for a selection.
-int initSelectionGroups(Selection* sel, const gmx_mtop_t* top, int type)
+int initSelectionGroups(Selection* sel, const gmx_mtop_t* top, GroupType type)
{
e_index_t indexType = INDEX_UNKNOWN;
switch (type)
{
- case eGroupType_All: indexType = INDEX_ALL; break;
- case eGroupType_Residue: indexType = INDEX_RES; break;
- case eGroupType_Molecule: indexType = INDEX_MOL; break;
- case eGroupType_None: indexType = INDEX_ATOM; break;
+ case GroupType::All: indexType = INDEX_ALL; break;
+ case GroupType::Residue: indexType = INDEX_RES; break;
+ case GroupType::Molecule: indexType = INDEX_MOL; break;
+ case GroupType::None: indexType = INDEX_ATOM; break;
+ case GroupType::Count: GMX_THROW(InternalError("Invalid GroupType"));
}
return sel->initOriginalIdsToGroup(top, indexType);
}
{
AnalysisDataPlotModulePointer plotm(new AnalysisDataPlotModule(settings.plotSettings()));
plotm->setFileName(fnDist_);
- if (distanceType_ == eDistanceType_Max)
+ if (distanceType_ == DistanceType::Max)
{
plotm->setTitle("Maximum distance");
}
{
initialDist2_ = cutoff_ * cutoff_;
}
- if (distanceType_ == eDistanceType_Max)
+ if (distanceType_ == DistanceType::Max)
{
initialDist2_ = 0.0;
}
void PairDistance::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* pbc, TrajectoryAnalysisModuleData* pdata)
{
AnalysisDataHandle dh = pdata->dataHandle(distances_);
- const Selection& refSel = pdata->parallelSelection(refSel_);
- const SelectionList& sel = pdata->parallelSelections(sel_);
+ const Selection& refSel = TrajectoryAnalysisModuleData::parallelSelection(refSel_);
+ const SelectionList& sel = TrajectoryAnalysisModuleData::parallelSelections(sel_);
PairDistanceModuleData& frameData = *static_cast<PairDistanceModuleData*>(pdata);
std::vector<real>& distArray = frameData.distArray_;
std::vector<int>& countArray = frameData.countArray_;
const int selIndex = selPos.mappedId();
const int index = selIndex * refGroupCount_ + refIndex;
const real r2 = pair.distance2();
- if (distanceType_ == eDistanceType_Min)
+ if (distanceType_ == DistanceType::Min)
{
if (distArray[index] > r2)
{
// update the distance if necessary and the count.
if (countArray[index] < totalCount)
{
- if (distanceType_ == eDistanceType_Max)
+ if (distanceType_ == DistanceType::Max)
{
distArray[index] = cutoff2_;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
//! Normalization for the computed distribution.
-enum Normalization
+enum class Normalization : int
{
- Normalization_Rdf,
- Normalization_NumberDensity,
- Normalization_None
+ Rdf,
+ NumberDensity,
+ None,
+ Count
};
//! String values corresponding to Normalization.
-const char* const c_NormalizationEnum[] = { "rdf", "number_density", "none" };
+const EnumerationArray<Normalization, const char*> c_normalizationNames = {
+ { "rdf", "number_density", "none" }
+};
//! Whether to compute RDF wrt. surface of the reference group.
-enum SurfaceType
+enum class SurfaceType : int
{
- SurfaceType_None,
- SurfaceType_Molecule,
- SurfaceType_Residue
+ None,
+ Molecule,
+ Residue,
+ Count
};
//! String values corresponding to SurfaceType.
-const char* const c_SurfaceEnum[] = { "no", "mol", "res" };
+const EnumerationArray<SurfaceType, const char*> c_surfaceTypeNames = { { "no", "mol", "res" } };
/*! \brief
* Implements `gmx rdf` trajectory analysis module.
};
Rdf::Rdf() :
- surface_(SurfaceType_None),
+ surface_(SurfaceType::None),
pairCounts_(new AnalysisDataSimpleHistogramModule()),
normAve_(new AnalysisDataAverageModule()),
localTop_(nullptr),
binwidth_(0.002),
cutoff_(0.0),
rmax_(0.0),
- normalization_(Normalization_Rdf),
+ normalization_(Normalization::Rdf),
bNormalizationSet_(false),
bXY_(false),
bExclusions_(false),
options->addOption(DoubleOption("bin").store(&binwidth_).description("Bin width (nm)"));
options->addOption(EnumOption<Normalization>("norm")
- .enumValue(c_NormalizationEnum)
+ .enumValue(c_normalizationNames)
.store(&normalization_)
.storeIsSet(&bNormalizationSet_)
.description("Normalization"));
DoubleOption("rmax").store(&rmax_).description("Largest distance (nm) to calculate"));
options->addOption(EnumOption<SurfaceType>("surf")
- .enumValue(c_SurfaceEnum)
+ .enumValue(c_surfaceTypeNames)
.store(&surface_)
.description("RDF with respect to the surface of the reference"));
void Rdf::optionsFinished(TrajectoryAnalysisSettings* settings)
{
- if (surface_ != SurfaceType_None)
+ if (surface_ != SurfaceType::None)
{
settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
- if (bNormalizationSet_ && normalization_ != Normalization_None)
+ if (bNormalizationSet_ && normalization_ != Normalization::None)
{
GMX_THROW(InconsistentInputError("-surf cannot be combined with -norm"));
}
- normalization_ = Normalization_None;
+ normalization_ = Normalization::None;
if (bExclusions_)
{
GMX_THROW(InconsistentInputError("-surf cannot be combined with -excl"));
normFactors_.setColumnCount(0, sel_.size() + 1);
- const bool bSurface = (surface_ != SurfaceType_None);
+ const bool bSurface = (surface_ != SurfaceType::None);
if (bSurface)
{
if (!refSel_.hasOnlyAtoms())
{
GMX_THROW(InconsistentInputError("-surf only works with -ref that consists of atoms"));
}
- const e_index_t type = (surface_ == SurfaceType_Molecule ? INDEX_MOL : INDEX_RES);
+ const e_index_t type = (surface_ == SurfaceType::Molecule ? INDEX_MOL : INDEX_RES);
surfaceGroupCount_ = refSel_.initOriginalIdsToGroup(top.mtop(), type);
}
}
}
localTop_ = top.expandedTopology();
- if (localTop_->excls.nr == 0)
+ if (localTop_->excls.empty())
{
GMX_THROW(InconsistentInputError(
"-excl is set, but the file provided to -s does not define exclusions"));
{
box[ZZ][ZZ] = 2 * std::max(box[XX][XX], box[YY][YY]);
}
- rmax_ = std::sqrt(0.99 * 0.99 * max_cutoff2(bXY_ ? epbcXY : epbcXYZ, box));
+ rmax_ = std::sqrt(0.99 * 0.99 * max_cutoff2(bXY_ ? PbcType::XY : PbcType::Xyz, box));
}
else
{
{
AnalysisDataHandle dh = pdata->dataHandle(pairDist_);
AnalysisDataHandle nh = pdata->dataHandle(normFactors_);
- const Selection& refSel = pdata->parallelSelection(refSel_);
- const SelectionList& sel = pdata->parallelSelections(sel_);
+ const Selection& refSel = TrajectoryAnalysisModuleData::parallelSelection(refSel_);
+ const SelectionList& sel = TrajectoryAnalysisModuleData::parallelSelections(sel_);
RdfModuleData& frameData = *static_cast<RdfModuleData*>(pdata);
const bool bSurface = !frameData.surfaceDist2_.empty();
// through the dataset registration mechanism.
AverageHistogramPointer finalRdf = pairCounts_->averager().resampleDoubleBinWidth(true);
- if (normalization_ != Normalization_None)
+ if (normalization_ != Normalization::None)
{
// Normalize by the volume of the bins (volume of sphere segments or
// length of circle segments).
}
finalRdf->scaleAllByVector(invBinVolume.data());
- if (normalization_ == Normalization_Rdf)
+ if (normalization_ == Normalization::Rdf)
{
// Normalize by particle density.
for (size_t g = 0; g < sel_.size(); ++g)
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2006, The GROMACS development team.
- * Copyright (c) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2008,2009,2010,2011,2012 by the GROMACS development team.
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void add_rec(t_conect c[], int i, int j, real d2)
{
if (c[i].aa == -1)
- {
+ { // NOLINT bugprone-branch-clone
c[i].aa = j;
c[i].d2a = d2;
}
else if (c[i].ab == -1)
- {
+ { // NOLINT bugprone-branch-clone
c[i].ab = j;
c[i].d2b = d2;
}
rvec x[],
t_atoms* atoms,
t_symtab* symtab,
- int ePBC,
+ PbcType pbcType,
const matrix box,
gmx_bool bIncludeSolute)
{
}
atoms->nr = i0 + ndots;
atoms->nres = r0 + 1;
- write_sto_conf(fn, title, atoms, xnew, nullptr, ePBC, const_cast<rvec*>(box));
+ write_sto_conf(fn, title, atoms, xnew, nullptr, pbcType, const_cast<rvec*>(box));
atoms->nres = r0;
atoms->nr = i0;
}
aaa.pdbinfo[ii0].occup = 0.0;
}
aaa.nr = ndots;
- write_sto_conf(fn, title, &aaa, xnew, nullptr, ePBC, const_cast<rvec*>(box));
+ write_sto_conf(fn, title, &aaa, xnew, nullptr, pbcType, const_cast<rvec*>(box));
do_conect(fn, ndots, xnew);
done_atom(&aaa);
}
}
please_cite(stderr, "Eisenhaber95");
- // if ((top.ePBC() != epbcXYZ) || (TRICLINIC(fr.box)))
+ // if ((top.pbcType() != PbcType::Xyz) || (TRICLINIC(fr.box)))
//{
// fprintf(stderr, "\n\nWARNING: non-rectangular boxes may give erroneous results or crashes.\n"
// "Analysis based on vacuum simulations (with the possibility of evaporation)\n"
AnalysisDataHandle aah = pdata->dataHandle(atomArea_);
AnalysisDataHandle rah = pdata->dataHandle(residueArea_);
AnalysisDataHandle vh = pdata->dataHandle(volume_);
- const Selection& surfaceSel = pdata->parallelSelection(surfaceSel_);
- const SelectionList& outputSel = pdata->parallelSelections(outputSel_);
+ const Selection& surfaceSel = TrajectoryAnalysisModuleData::parallelSelection(surfaceSel_);
+ const SelectionList& outputSel = TrajectoryAnalysisModuleData::parallelSelections(outputSel_);
SasaModuleData& frameData = *static_cast<SasaModuleData*>(pdata);
const bool bResAt = !frameData.res_a_.empty();
// one else uses the topology after initialization, it may just work
// even with future parallelization.
connolly_plot(fnConnolly_.c_str(), nsurfacedots, surfacedots, fr.x, atoms_.get(),
- &mtop_->symtab, fr.ePBC, fr.box, bIncludeSolute_);
+ &mtop_->symtab, fr.pbcType, fr.box, bIncludeSolute_);
}
ah.startFrame(frnr, fr.time);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
//! How to identify residues in output files.
-enum ResidueNumbering
+enum class ResidueNumbering : int
{
- ResidueNumbering_ByNumber,
- ResidueNumbering_ByIndex
+ ByNumber,
+ ByIndex,
+ Count
};
//! Which atoms to write out to PDB files.
-enum PdbAtomsSelection
+enum class PdbAtomsSelection : int
{
- PdbAtomsSelection_All,
- PdbAtomsSelection_MaxSelection,
- PdbAtomsSelection_Selected
+ All,
+ MaxSelection,
+ Selected,
+ Count
};
//! String values corresponding to ResidueNumbering.
-const char* const cResNumberEnum[] = { "number", "index" };
+const EnumerationArray<ResidueNumbering, const char*> c_residueNumberingTypeNames = { { "number",
+ "index" } };
//! String values corresponding to PdbAtomsSelection.
-const char* const cPDBAtomsEnum[] = { "all", "maxsel", "selected" };
+const EnumerationArray<PdbAtomsSelection, const char*> c_pdbAtomsTypeNames = { { "all", "maxsel",
+ "selected" } };
class Select : public TrajectoryAnalysisModule
{
bFracNorm_(false),
bResInd_(false),
bCumulativeLifetimes_(true),
- resNumberType_(ResidueNumbering_ByNumber),
- pdbAtoms_(PdbAtomsSelection_All),
+ resNumberType_(ResidueNumbering::ByNumber),
+ pdbAtoms_(PdbAtomsSelection::All),
top_(nullptr),
occupancyModule_(new AnalysisDataAverageModule()),
lifetimeModule_(new AnalysisDataLifetimeModule())
BooleanOption("cfnorm").store(&bFracNorm_).description("Normalize by covered fraction with -os"));
options->addOption(EnumOption<ResidueNumbering>("resnr")
.store(&resNumberType_)
- .enumValue(cResNumberEnum)
+ .enumValue(c_residueNumberingTypeNames)
.description("Residue number output type with -oi and -on"));
options->addOption(EnumOption<PdbAtomsSelection>("pdbatoms")
.store(&pdbAtoms_)
- .enumValue(cPDBAtomsEnum)
+ .enumValue(c_pdbAtomsTypeNames)
.description("Atoms to write with -ofpdb"));
options->addOption(BooleanOption("cumlt")
.store(&bCumulativeLifetimes_)
void Select::initAnalysis(const TrajectoryAnalysisSettings& settings, const TopologyInformation& top)
{
- bResInd_ = (resNumberType_ == ResidueNumbering_ByIndex);
+ bResInd_ = (resNumberType_ == ResidueNumbering::ByIndex);
for (SelectionList::iterator i = sel_.begin(); i != sel_.end(); ++i)
{
AnalysisDataHandle cdh = pdata->dataHandle(cdata_);
AnalysisDataHandle idh = pdata->dataHandle(idata_);
AnalysisDataHandle mdh = pdata->dataHandle(mdata_);
- const SelectionList& sel = pdata->parallelSelections(sel_);
+ const SelectionList& sel = TrajectoryAnalysisModuleData::parallelSelections(sel_);
sdh.startFrame(frnr, fr.time);
for (size_t g = 0; g < sel.size(); ++g)
switch (pdbAtoms_)
{
- case PdbAtomsSelection_All:
+ case PdbAtomsSelection::All:
{
t_trxstatus* status = open_trx(fnPDB_.c_str(), "w");
write_trxframe(status, &fr, nullptr);
close_trx(status);
break;
}
- case PdbAtomsSelection_MaxSelection:
+ case PdbAtomsSelection::MaxSelection:
{
std::set<int> atomIndicesSet;
for (size_t g = 0; g < sel_.size(); ++g)
close_trx(status);
break;
}
- case PdbAtomsSelection_Selected:
+ case PdbAtomsSelection::Selected:
{
std::vector<int> indices;
for (int i = 0; i < atoms->nr; ++i)
close_trx(status);
break;
}
- default:
+ case PdbAtomsSelection::Count:
GMX_RELEASE_ASSERT(false,
"Mismatch between -pdbatoms enum values and implementation");
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2007, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
void Trajectory::analyzeFrame(int frnr, const t_trxframe& fr, t_pbc* /* pbc */, TrajectoryAnalysisModuleData* pdata)
{
AnalysisDataHandle dh = pdata->dataHandle(xdata_);
- const SelectionList& sel = pdata->parallelSelections(sel_);
+ const SelectionList& sel = TrajectoryAnalysisModuleData::parallelSelections(sel_);
analyzeFrameImpl(frnr, fr, &dh, sel, [](const SelectionPosition& pos) { return pos.x(); });
if (fr.bV)
{
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
return;
}
- time_unit_t time_unit = static_cast<time_unit_t>(settings_.timeUnit() + 1); // NOLINT(bugprone-misplaced-widening-cast)
- output_env_init(&oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0);
+ output_env_init(&oenv_, getProgramContext(), settings_.timeUnit(), FALSE, XvgFormat::None, 0);
int frflags = settings_.frflags();
frflags |= TRX_NEED_X;
copy_mat(topInfo_.boxtop_, fr->box);
}
- set_trxframe_ePBC(fr, topInfo_.ePBC());
+ setTrxFramePbcType(fr, topInfo_.pbcType());
if (topInfo_.hasTopology() && settings_.hasRmPBC())
{
gpbc_ = gmx_rmpbc_init(topInfo_);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-gmx_add_unit_test(TrajectoryAnalysisUnitTests trajectoryanalysis-test
- moduletest.cpp
- clustsize.cpp
- cmdlinerunner.cpp
- angle.cpp
- convert_trj.cpp
- distance.cpp
- extract_cluster.cpp
- freevolume.cpp
- pairdist.cpp
- rdf.cpp
- sasa.cpp
- select.cpp
- surfacearea.cpp
- topologyinformation.cpp
- trajectory.cpp
- unionfind.cpp)
+gmx_add_gtest_executable(trajectoryanalysis-test
+ CPP_SOURCE_FILES
+ # Infrastructure
+ moduletest.cpp
+ # Tests
+ angle.cpp
+ clustsize.cpp
+ cmdlinerunner.cpp
+ convert_trj.cpp
+ distance.cpp
+ extract_cluster.cpp
+ freevolume.cpp
+ pairdist.cpp
+ rdf.cpp
+ sasa.cpp
+ select.cpp
+ surfacearea.cpp
+ topologyinformation.cpp
+ trajectory.cpp
+ unionfind.cpp
+ )
+gmx_register_gtest_test(TrajectoryAnalysisUnitTests trajectoryanalysis-test SLOW_TEST)
target_link_libraries(trajectoryanalysis-test PRIVATE analysisdata-test-shared)
add_executable(test_selection ${UNITTEST_TARGET_OPTIONS} test_selection.cpp)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
Atoms stored in the trajectory file (if not set, assume first N
atoms)
-xvg <enum> (xmgrace)
- Plot formatting: none, xmgrace, xmgr
+ Plot formatting: xmgrace, xmgr, none
-[no]rmpbc (yes)
Make molecules whole for each frame
-[no]pbc (yes)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
t_pbc pbc;
if (bPBC)
{
- set_pbc(&pbc, epbcXYZ, box_);
+ set_pbc(&pbc, PbcType::Xyz, box_);
}
- ASSERT_NO_THROW_GMX({
- gmx::SurfaceAreaCalculator calculator;
- calculator.setDotCount(ndots);
- calculator.setRadii(radius_);
- calculator.calculate(as_rvec_array(x_.data()), bPBC ? &pbc : nullptr, index_.size(),
- index_.data(), flags, &area_, &volume_, &atomArea_, &dots_, &dotCount_);
- });
+ gmx::SurfaceAreaCalculator calculator;
+ calculator.setDotCount(ndots);
+ calculator.setRadii(radius_);
+ calculator.calculate(as_rvec_array(x_.data()), bPBC ? &pbc : nullptr, index_.size(),
+ index_.data(), flags, &area_, &volume_, &atomArea_, &dots_, &dotCount_);
}
real resultArea() const { return area_; }
real resultVolume() const { return volume_; }
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/gmxpreprocess/grompp.h"
#include "gromacs/math/vectypes.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/topology/topology.h"
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/exceptions.h"
ASSERT_TRUE(atoms2);
EXPECT_NE(atoms1.get(), atoms2.get());
EXPECT_EQ(0, atoms1->nr);
- EXPECT_EQ(-1, topInfo.ePBC());
+ EXPECT_EQ(PbcType::Unset, topInfo.pbcType());
EXPECT_THROW(topInfo.x().size(), gmx::APIError);
EXPECT_THROW(topInfo.v().size(), gmx::APIError);
matrix box{ { -2 } };
topInfo.fillFromInputFile(TestFileManager::getInputFilePath("lysozyme.gro"));
EXPECT_FALSE(topInfo.hasFullTopology());
runCommonTests(topInfo, numAtoms);
- EXPECT_EQ(-1, topInfo.ePBC());
+ EXPECT_EQ(PbcType::Unset, topInfo.pbcType());
// Check the per-atom data
auto atoms = topInfo.copyAtoms();
EXPECT_FALSE(topInfo.hasFullTopology());
runCommonTests(topInfo, numAtoms);
// TODO why does this differ from .gro?
- EXPECT_EQ(0, topInfo.ePBC());
+ EXPECT_EQ(PbcType::Xyz, topInfo.pbcType());
// Check the per-atom data
auto atoms = topInfo.copyAtoms();
EXPECT_TRUE(topInfo.hasFullTopology());
runCommonTests(topInfo, numAtoms);
// TODO why does this differ from .gro?
- EXPECT_EQ(0, topInfo.ePBC());
+ EXPECT_EQ(PbcType::Xyz, topInfo.pbcType());
// Check the per-atom data
auto atoms = topInfo.copyAtoms();
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/fileio/confio.h"
#include "gromacs/math/vec.h"
+#include "gromacs/pbcutil/pbc.h"
#include "gromacs/pbcutil/rmpbc.h"
#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
expandedTopology_(nullptr),
atoms_(nullptr),
bTop_(false),
- ePBC_(-1)
+ pbcType_(PbcType::Unset)
{
}
// TODO Once there are fewer callers of the file-reading
// functionality, make them read directly into std::vector.
rvec *x, *v;
- readConfAndTopology(filename.c_str(), &bTop_, mtop_.get(), &ePBC_, &x, &v, boxtop_);
+ readConfAndTopology(filename.c_str(), &bTop_, mtop_.get(), &pbcType_, &x, &v, boxtop_);
xtop_.assign(x, x + mtop_->natoms);
vtop_.assign(v, v + mtop_->natoms);
sfree(x);
// Do lazy initialization
if (expandedTopology_ == nullptr && hasTopology())
{
- expandedTopology_ = std::make_unique<gmx_localtop_t>();
+ expandedTopology_ = std::make_unique<gmx_localtop_t>(mtop_->ffparams);
gmx_mtop_generate_local_top(*mtop_, expandedTopology_.get(), false);
}
{
GMX_RELEASE_ASSERT(topInfo.hasTopology(), "Cannot remove PBC without a topology");
- return gmx_rmpbc_init(&topInfo.expandedTopology()->idef, topInfo.ePBC(), topInfo.mtop()->natoms);
+ return gmx_rmpbc_init(topInfo.expandedTopology()->idef, topInfo.pbcType(), topInfo.mtop()->natoms);
}
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Forward declaration
typedef struct gmx_rmpbc* gmx_rmpbc_t;
+enum class PbcType : int;
namespace gmx
{
/*! \brief Copies the fully expanded atom data arrays, which
* might be valid but empty if no topology is available. */
AtomsDataPtr copyAtoms() const;
- //! Returns the ePBC field from the topology.
- int ePBC() const { return ePBC_; }
+ //! Returns the pbcType field from the topology.
+ PbcType pbcType() const { return pbcType_; }
/*! \brief
* Gets the configuration positions from the topology file.
*
std::vector<RVec> vtop_;
//! The box loaded from the topology file.
matrix boxtop_{};
- //! The ePBC field loaded from the topology file.
- int ePBC_;
+ //! The pbcType field loaded from the topology file.
+ PbcType pbcType_;
// TODO This type is probably movable if we need that.
GMX_DISALLOW_COPY_AND_ASSIGN(TopologyInformation);
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* The header path.h declares helpers for manipulating paths as strings and for
* managing directories and files.
- * The fate of this header depends on what is decided in Redmine issue #950.
+ * The fate of this header depends on what is decided in Issue #950.
*
* <H3>Logging</H3>
*
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
file(GLOB UTILITY_SOURCES *.cpp)
-if (GMX_GPU AND NOT GMX_USE_OPENCL)
+if (GMX_USE_CUDA)
gmx_add_libgromacs_sources(cuda_version_information.cu)
endif()
set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${UTILITY_SOURCES} PARENT_SCOPE)
-# TODO: (https://redmine.gromacs.org/issues/988) Find a new convention for defining public API.
+# TODO: (https://gitlab.com/gromacs/gromacs/-/issues/988) Find a new convention for defining public API.
install(FILES
basedefinitions.h
current_function.h
install(FILES
arrayref.h
baseversion.h
+ classhelpers.h
enumerationhelpers.h
+ exceptions.h
+ listoflists.h
programcontext.h
range.h
smalloc.h
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
ClassName& operator=(const ClassName&) = delete; \
ClassName(const ClassName&) = delete
#endif
+#ifdef DOXYGEN
+/*! \brief
+ * Macro to declare a class non-copyable, non-movable, non-copy-assignable and
+ * non-move-assignable.
+ *
+ * For consistency, should appear last in the class declaration.
+ *
+ * \ingroup module_utility
+ */
+# define GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(ClassName)
+#else
+# define GMX_DISALLOW_COPY_MOVE_AND_ASSIGN(ClassName) \
+ ClassName& operator=(const ClassName&) = delete; \
+ ClassName(const ClassName&) = delete; \
+ ClassName& operator=(ClassName&&) = delete; /* NOLINT(misc-macro-parentheses,bugprone-macro-parentheses) */ \
+ ClassName(ClassName&&) = delete /* NOLINT(misc-macro-parentheses,bugprone-macro-parentheses) */
+#endif
/*! \brief
* Macro to declare a class non-assignable.
*
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{ "Shoot them in the back now", "The Ramones" },
{ "Read me your scripture and I will twist it", "Red Hot Chili Peppers" },
{ "Good Music Saves your Soul", "Lemmy" },
- { "I believe in miracles cause I'm one", "The Ramones" },
- { "Gabba Gabba Hey!", "The Ramones" },
- { "Good Music Saves your Soul", "Lemmy" },
{ "Move about like a Scientist, lay down, get kissed", "Red Hot Chili Peppars" },
{ "California, R.I.P.", "Red Hot Chili Peppars" },
{ "Don't You Wish You Never Met Her, Dirty Blue Gene?", "Captain Beefheart" },
{ "Nobody Never Learnt No-Nothing from No History", "Gogol Bordello" },
{ "I'd be Safe and Warm if I was in L.A.", "The Mamas and the Papas" },
- { "It's Unacceptable That Choclate Makes You Fat", "MI 3" },
+ { "It's Unacceptable That Chocolate Makes You Fat", "MI 3" },
{ "My Brothers are Protons (Protons!), My Sisters are Neurons (Neurons)",
"Gogol Bordello" },
{ "Put Me Inside SSC, Let's Test Superstring Theory, Oh Yoi Yoi Accelerate the Protons",
"takes all the running YOU can do, to keep in the same place. If you want "
"to get somewhere else, you must run at least twice as fast as that!\"",
"Lewis Carroll" },
+ { "More than 10000000 total errors detected. I'm not reporting any more. "
+ "Final error counts will be inaccurate. Go fix your program!",
+ "Valgrind while memory debugging mdrun" },
+ { "If we are going to have SYCL, can we have a hammer as well?", "Joe Jordan" },
+ { "We can make it into a friend class. But I don't like having friends.", "Joe Jordan" },
+ { "A method is more important than a discovery, since the right method will lead to new "
+ "and even more important discoveries.",
+ "Lev Landau" },
+ { "Product of optimism and knowledge is a constant.", "Lev Landau" },
+ { "Why add prime numbers? Prime numbers are made to be multiplied.", "Lev Landau" },
+ { "How wonderful that we have met with a paradox. Now we have some hope of making "
+ "progress.",
+ "Niels Bohr" },
+ { "We must be clear that when it comes to atoms, language can be used only as in poetry. ",
+ "Niels Bohr" },
+ { "\"What are the biological implications of your research?\" - \"Well, I simulate "
+ "water.\" ",
+ "Petter Johansson" },
};
if (beCool())
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Native Windows uses backslash path separators (but accepts also slashes).
* Cygwin and most other systems use slash.
*
- * \todo Get rid of this (Redmine #950). It is not necessary for
+ * \todo Get rid of this (Issue #950). It is not necessary for
* constructing paths on the systems that it currently supports, and
* is not reliable in parsing input paths either, since Windows needs
* to accept both instead of only DIR_SEPARATOR. At the very least, we
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Usage examples:
*
- * enum class Foo
+ * enum class Foo : int
* {
- * Bar, Baz, Fooz,
+ * Bar,
+ * Baz,
+ * Fooz,
* Count
* };
*
- * EnumerationWrapper<Foo> iter;
- *
- * for (Foo c : iter)
+ * for (Foo c : EnumerationWrapper<Foo>{})
* {
* // 'c' is a constant from Foo
* }
*
+ *
* const EnumerationArray<Foo, std::string> fooStrings = { { "Bar", "Baz", "Fooz" } };
+ * std::cout << fooStrings[Foo::Baz];
+ * std::cout << fooStrings[Foo::Count]; // Triggers an assertion
*
* for (Foo c : keysOf(fooStrings))
* {
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* StandardInputStream
*/
-bool StandardInputStream::isInteractive() const
+// static
+bool StandardInputStream::isInteractive()
{
#ifdef HAVE_UNISTD_H
return isatty(fileno(stdin)) != 0;
return readLineImpl(stdin, line);
}
-// static
-StandardInputStream& StandardInputStream::instance()
-{
- static StandardInputStream stdinObject;
- return stdinObject;
-}
-
/********************************************************************
* TextInputFile
*/
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Does not throw.
*/
- bool isInteractive() const;
+ static bool isInteractive();
// From TextInputStream
bool readLine(std::string* line) override;
void close() override {}
-
- /*! \brief
- * Returns a stream for accessing `stdin`.
- *
- * Does not throw.
- */
- static StandardInputStream& instance();
};
/*! \libinternal \brief
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
writer_->writeLine(message);
}
- std::string formatValueForMissingMessage(const KeyValueTreeValue& value)
+ static std::string formatValueForMissingMessage(const KeyValueTreeValue& value)
{
if (value.isObject() || value.isArray())
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// warning is about as bad as any alternative.
KeyValueTreeTransformRuleBuilder::~KeyValueTreeTransformRuleBuilder() // NOLINT(bugprone-exception-escape)
{
- if (!std::uncaught_exception())
+ if (!std::uncaught_exceptions())
{
data_->createRule(impl_);
}
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2019, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \file
+ * \brief
+ * Declares gmx::ListOfLists
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \inpublicapi
+ * \ingroup module_utility
+ */
+#ifndef GMX_UTILITY_LISTOFLISTS_H
+#define GMX_UTILITY_LISTOFLISTS_H
+
+#include <vector>
+
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/exceptions.h"
+
+namespace gmx
+{
+
+/*! \brief A list of lists, optimized for performance
+ *
+ * This class holds a list of \p size() lists of elements of type \p T.
+ * To optimize performance, the only modification operation supporting
+ * is adding a new list at the end of the list of lists.
+ *
+ * This implementation stores all data internally in two std::vector objects
+ * and thereby avoids the overhead of managing \p size() separate objects
+ * in memory.
+ *
+ * Internal storage consists of one std::vector<int> listRanges_ of size number
+ * of lists plus one and a std::vector<T> elements_ with the elements of all
+ * lists concatenated. List i is stored in entries listRanges_[i] to
+ * listRanges_[i+1] in elements_.
+ *
+ * \note This class is currently limited to arithmetic types, mainly because
+ * this should only be used for performance critical applications.
+ * When performance is not critical, a std::vector of std::vector can be used.
+ *
+ * \tparam T value type
+ */
+
+template<typename T>
+class ListOfLists
+{
+ static_assert(std::is_arithmetic<T>::value, "This class is limited to arithmetic types");
+
+public:
+ //! Constructs an empty list of lists
+ ListOfLists() = default;
+
+ /*! \brief Constructs a list of list from raw data in internal layout
+ *
+ * Does basic consistency checks and throws when one of those fail.
+ *
+ * \param[in] listRanges Ranges of the lists concatenated (see above), is consumed
+ * \param[in] elements Elements for all lists concatenated, is consumed
+ */
+ ListOfLists(std::vector<int>&& listRanges, std::vector<T>&& elements) :
+ listRanges_(std::move(listRanges)),
+ elements_(std::move(elements))
+ {
+ if (listRanges_.empty() || listRanges_.at(0) != 0)
+ {
+ GMX_THROW(InconsistentInputError(
+ "listRanges does not have a first element with value 0"));
+ }
+ if (int(elements_.size()) != listRanges_.back())
+ {
+ GMX_THROW(InconsistentInputError(
+ "The size of elements does not match the last value in listRanges"));
+ }
+ }
+
+ //! Returns the number of lists
+ std::size_t size() const { return listRanges_.size() - 1; }
+
+ /*! \brief Returns the number of lists
+ *
+ * \note Use ssize for any expression involving arithmetic operations
+ * (including loop indices).
+ */
+ index ssize() const { return index(listRanges_.size()) - 1; }
+
+ //! Returns whether the list holds no lists
+ bool empty() const { return listRanges_.size() == 1; }
+
+ //! Returns the sum of the number of elements over all lists
+ int numElements() const { return listRanges_.back(); }
+
+ //! Appends a new list with elements \p values, pass {} to add an empty list
+ void pushBack(ArrayRef<const T> values)
+ {
+ elements_.insert(elements_.end(), values.begin(), values.end());
+ listRanges_.push_back(int(elements_.size()));
+ }
+
+ //! Appends a new list with \p numElements elements
+ void pushBackListOfSize(int numElements)
+ {
+ // With arithmetic types enforced, this assertion is always true
+ static_assert(std::is_default_constructible<T>::value,
+ "pushBackListOfSize should only be called with default constructable types");
+ elements_.resize(elements_.size() + numElements);
+ listRanges_.push_back(int(elements_.size()));
+ }
+
+ //! Returns an ArrayRef to the elements of the list with the given index
+ ArrayRef<const T> operator[](std::size_t listIndex) const
+ {
+ return ArrayRef<const T>(elements_.data() + listRanges_[listIndex],
+ elements_.data() + listRanges_[listIndex + 1]);
+ }
+
+ //! Returns the list of elements for the list with index \p listIndex, throws an \p out_of_range exception when out of range
+ ArrayRef<const T> at(std::size_t listIndex) const
+ {
+ return ArrayRef<const T>(elements_.data() + listRanges_.at(listIndex),
+ elements_.data() + listRanges_.at(listIndex + 1));
+ }
+
+ /*! \brief Returns a reference to the first list
+ *
+ * \returns a reference to the first list
+ */
+ ArrayRef<T> front()
+ {
+ GMX_ASSERT(size() > 0, "Must contain a list if front() is called");
+ auto beginPtr = elements_.data();
+ auto endPtr = beginPtr + listRanges_[1];
+ return { beginPtr, endPtr };
+ }
+ /*! \brief Returns a reference to the final list
+ *
+ * \returns a reference to the final list
+ */
+ ArrayRef<T> back()
+ {
+ GMX_ASSERT(size() > 0, "Must contain a list if bank() is called");
+ auto endIndex = *(listRanges_.end() - 1);
+ auto beginIndex = *(listRanges_.end() - 2);
+ return { elements_.data() + beginIndex, elements_.data() + endIndex };
+ }
+
+ //! Clears the list
+ void clear()
+ {
+ listRanges_.resize(1);
+ elements_.clear();
+ }
+
+ //! Appends a ListOfLists at the end and increments the appended elements by \p offset
+ void appendListOfLists(const ListOfLists& listOfLists, const T offset = 0)
+ {
+ listRanges_.insert(listRanges_.end(), listOfLists.listRanges_.begin() + 1,
+ listOfLists.listRanges_.end());
+ const int oldNumElements = elements_.size();
+ for (std::size_t i = listRanges_.size() - listOfLists.size(); i < listRanges_.size(); i++)
+ {
+ listRanges_[i] += oldNumElements;
+ }
+ elements_.insert(elements_.end(), listOfLists.elements_.begin(), listOfLists.elements_.end());
+
+ if (offset != 0)
+ {
+ for (std::size_t i = elements_.size() - listOfLists.elements_.size(); i < elements_.size(); i++)
+ {
+ elements_[i] += offset;
+ }
+ }
+ }
+
+ //! Returns concatenated ranges of the lists (see above for details)
+ ArrayRef<const int> listRangesView() const { return listRanges_; }
+
+ //! Returns the a view of the elements of all lists concatenated
+ ArrayRef<const T> elementsView() const { return elements_; }
+
+private:
+ //! The ranges of the lists, list i uses range \p listRanges_[i], \p listRanges_[i+1].
+ std::vector<int> listRanges_ = { 0 };
+ //! The elements in all lists concatenated
+ std::vector<T> elements_;
+};
+
+} // namespace gmx
+
+#endif
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares gmx::MdModuleNotification.
+ *
+ * \author Christian Blau <blau@kth.se>
+ * \inlibraryapi
+ * \ingroup module_utility
+ */
+
+#ifndef GMX_UTILITY_MDMODULENOTIFICATION_IMPL_H
+#define GMX_UTILITY_MDMODULENOTIFICATION_IMPL_H
+
+#include <functional>
+#include <vector>
+
+namespace gmx
+{
+
+/*! \libinternal \brief
+ * Subscribe and trigger notification functions.
+ *
+ * Extends MdModuleNotificationBase with new notification function and routine
+ * to subscribe new listeners.
+ *
+ * To create a class of this type that provides callbacks, e.g., for events
+ * EventA, and EventB use registerMdModuleNotification<EventA, EventB>::type.
+ *
+ * \tparam CallParameter of the function to be notified
+ * \tparam MdModuleNotificationBase class to be extended with a notification
+ * with CallParameter
+ *
+ * \note All added subscribers are required to out-live the MdModuleNotification
+ *
+ */
+template<class CallParameter, class MdModuleNotificationBase>
+class MdModuleNotification : public MdModuleNotificationBase
+{
+public:
+ //! Make base class notification trigger available to this class
+ using MdModuleNotificationBase::notify;
+ //! Make base class subscription available to this class
+ using MdModuleNotificationBase::subscribe;
+
+ /*! \brief Trigger the subscribed notifications.
+ * \param[in] callParameter of the function to be called back
+ */
+ void notify(CallParameter callParameter) const
+ {
+ for (auto& callBack : callBackFunctions_)
+ {
+ callBack(callParameter);
+ }
+ }
+
+ /*! \brief
+ * Add callback function to be called when notification is triggered.
+ *
+ * Notifications are distinguished by their call signature.
+ *
+ * \param[in] callBackFunction to be called from this class
+ */
+ void subscribe(std::function<void(CallParameter)> callBackFunction)
+ {
+ callBackFunctions_.emplace_back(callBackFunction);
+ }
+
+private:
+ std::vector<std::function<void(CallParameter)>> callBackFunctions_;
+};
+
+/*! \internal
+ * \brief Aide to avoid nested MdModuleNotification definition.
+ *
+ * Instead of
+ * MdModuleNotification<CallParameterA, MdModuleNotification<CallParameterB, etc ... >>
+ * this allows to write
+ * registerMdModuleNotification<CallParameterA, CallParameterB, ...>::type
+ *
+ * \tparam CallParameter all the event types to be registered
+ */
+template<class... CallParameter>
+struct registerMdModuleNotification;
+
+/*! \internal \brief Template specialization to end parameter unpacking recursion.
+ */
+template<>
+struct registerMdModuleNotification<>
+{
+ /*! \internal
+ * \brief Do nothing but be base class of MdModuleNotification.
+ *
+ * Required so that using MdModuleNotificationBase::notify and
+ * MdModuleNotificationBase::subscribe are valid in derived class.
+ */
+ class NoCallParameter
+ {
+ public:
+ //! Do nothing but provide MdModuleNotification::notify to derived class
+ void notify() {}
+ //! Do nothing but provide MdModuleNotification::subscribe to derived class
+ void subscribe() {}
+ };
+ /*! \brief Defines a type if no notifications are managed.
+ *
+ * This ensures that code works with MdModuleCallParameterManagement that
+ * does not manage any notifications.
+ */
+ using type = NoCallParameter;
+};
+
+/*! \libinternal
+ * \brief Template specialization to assemble MdModuleNotification.
+ *
+ * Assembly of MdModuleNotification is performed by recursively taking off the
+ * front of the CallParameter parameter pack and constructing the nested type
+ * definition of MdModuleNotification base classes.
+ *
+ * \tparam CurrentCallParameter front of the template parameter pack
+ * \tparam CallParameter rest of the event types
+ */
+template<class CurrentCallParameter, class... CallParameter>
+struct registerMdModuleNotification<CurrentCallParameter, CallParameter...>
+{
+ // private:
+ //! The next type with rest of the arguments with the front parameter removed.
+ using next_type = typename registerMdModuleNotification<CallParameter...>::type;
+ //! The type of the MdModuleNotification
+ using type = MdModuleNotification<CurrentCallParameter, next_type>;
+};
+
+} // namespace gmx
+
+#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
/*! \libinternal \file
* \brief
- * Declares gmx::MdModuleNotification.
+ * Declares gmx::MdModulesNotifier.
*
* \author Christian Blau <blau@kth.se>
* \inlibraryapi
* \ingroup module_utility
*/
-#ifndef GMX_MDRUNUTILITY_MDMODULENOTIFICATION_H
-#define GMX_MDRUNUTILITY_MDMODULENOTIFICATION_H
+#ifndef GMX_UTILITY_MDMODULENOTIFICATION_H
+#define GMX_UTILITY_MDMODULENOTIFICATION_H
-#include <functional>
#include <string>
#include <vector>
+#include "gromacs/utility/mdmodulenotification-impl.h"
+
struct t_commrec;
+enum class PbcType : int;
namespace gmx
{
-/*! \libinternal \brief
- * Subscribe and trigger notification functions.
- *
- * Extends MdModuleNotificationBase with new notification function and routine
- * to subscribe new listeners.
- *
- * To create a class of this type that provides callbacks, e.g., for events
- * EventA, and EventB use registerMdModuleNotification<EventA, EventB>::type.
- *
- * \tparam CallParameter of the function to be notified
- * \tparam MdModuleNotificationBase class to be extended with a notification
- * with CallParameter
- *
- \msc
- wordwraparcs=true,
- hscale="2";
-
- runner [label="runner:\nMdrunner"],
- CallParameter [label = "eventA:\nCallParameter"],
- MOD [label = "mdModules_:\nMdModules"],
- ModuleA [label="moduleA"],
- ModuleB [label="moduleB"],
- MdModuleNotification [label="notifier_:\nMdModuleNotification"];
-
- MOD box MdModuleNotification [label = "mdModules_ owns notifier_ and moduleA/B"];
- MOD =>> ModuleA [label="instantiates(notifier_)"];
- ModuleA =>> MdModuleNotification [label="subscribe(otherfunc)"];
- ModuleA =>> MOD;
- MOD =>> ModuleB [label="instantiates(notifier_)"];
- ModuleB =>> MdModuleNotification [label="subscribe(func)"];
- ModuleB =>> MOD;
- runner =>> CallParameter [label="instantiate"];
- CallParameter =>> runner ;
- runner =>> MOD [label="notify(eventA)"];
- MOD =>> MdModuleNotification [label="notify(eventA)"];
- MdModuleNotification =>> ModuleA [label="notify(eventA)"];
- ModuleA -> ModuleA [label="func(eventA)"];
- MdModuleNotification =>> ModuleB [label="notify(eventA)"];
- ModuleB -> ModuleB [label="otherfunc(eventA)"];
-
- \endmsc
- *
- * \note All added subscribers are required to out-live the MdModuleNotification
- *
- */
-template<class CallParameter, class MdModuleNotificationBase>
-class MdModuleNotification : public MdModuleNotificationBase
-{
-public:
- //! Make base class notification trigger available to this class
- using MdModuleNotificationBase::notify;
- //! Make base class subscription available to this class
- using MdModuleNotificationBase::subscribe;
-
- /*! \brief Trigger the subscribed notifications.
- * \param[in] callParameter of the function to be called back
- */
- void notify(CallParameter callParameter) const
- {
- for (auto& callBack : callBackFunctions_)
- {
- callBack(callParameter);
- }
- }
-
- /*! \brief
- * Add callback function to be called when notification is triggered.
- *
- * Notifications are distinguished by their call signature.
- *
- * \param[in] callBackFunction to be called from this class
- */
- void subscribe(std::function<void(CallParameter)> callBackFunction)
- {
- callBackFunctions_.emplace_back(callBackFunction);
- }
-
-private:
- std::vector<std::function<void(CallParameter)>> callBackFunctions_;
-};
-
-/*! \internal
- * \brief Aide to avoid nested MdModuleNotification definition.
- *
- * Instead of
- * MdModuleNotification<CallParameterA, MdModuleNotification<CallParameterB, etc ... >>
- * this allows to write
- * registerMdModuleNotification<CallParameterA, CallParameterB, ...>::type
- *
- * \tparam CallParameter all the event types to be registered
- */
-template<class... CallParameter>
-struct registerMdModuleNotification;
-
-/*! \internal \brief Template specialization to end parameter unpacking recursion.
- */
-template<>
-struct registerMdModuleNotification<>
-{
- /*! \internal
- * \brief Do nothing but be base class of MdModuleNotification.
- *
- * Required so that using MdModuleNotificationBase::notify and
- * MdModuleNotificationBase::subscribe are valid in derived class.
- */
- class NoCallParameter
- {
- public:
- //! Do nothing but provide MdModuleNotification::notify to derived class
- void notify() {}
- //! Do nothing but provide MdModuleNotification::subscribe to derived class
- void subscribe() {}
- };
- /*! \brief Defines a type if no notifications are managed.
- *
- * This ensures that code works with MdModuleCallParameterManagement that
- * does not manage any notifications.
- */
- using type = NoCallParameter;
-};
-
-/*! \libinternal
- * \brief Template specialization to assemble MdModuleNotification.
- *
- * Assembly of MdModuleNotification is performed by recursively taking off the
- * front of the CallParameter parameter pack and constructing the nested type
- * definition of MdModuleNotification base classes.
- *
- * \tparam CurrentCallParameter front of the template parameter pack
- * \tparam CallParameter rest of the event types
- */
-template<class CurrentCallParameter, class... CallParameter>
-struct registerMdModuleNotification<CurrentCallParameter, CallParameter...>
-{
- // private:
- //! The next type with rest of the arguments with the front parameter removed.
- using next_type = typename registerMdModuleNotification<CallParameter...>::type;
- //! The type of the MdModuleNotification
- using type = MdModuleNotification<CurrentCallParameter, next_type>;
-};
-
class KeyValueTreeObject;
class KeyValueTreeObjectBuilder;
class LocalAtomSetManager;
struct MdModulesCheckpointReadingDataOnMaster;
struct MdModulesCheckpointReadingBroadcast;
struct MdModulesWriteCheckpointData;
-struct PeriodicBoundaryConditionType
-{
- int pbcType;
-};
+/*! \libinternal \brief Check if module outputs energy to a specific field.
+ *
+ * Ensures that energy is output for this module.
+ */
struct MdModulesEnergyOutputToDensityFittingRequestChecker
{
+ //! Trigger output to density fitting energy field
bool energyOutputToDensityFitting_ = false;
};
std::vector<std::string> errorMessages_;
};
+/*! \libinternal \brief Provides the simulation time step in ps.
+ */
struct SimulationTimeStep
{
//! Time step (ps)
const double delta_t;
};
+/*! \libinternal
+ * \brief Collection of callbacks to MDModules at differnt run-times.
+ *
+ * MDModules use members of this struct to sign up for callback functionality.
+ *
+ * The members of the struct represent callbacks at these run-times:
+ *
+ * When pre-processing the simulation data
+ * When reading and writing check-pointing data
+ * When setting up simulation after reading in the tpr file
+ *
+ \msc
+ wordwraparcs=true,
+ hscale="2";
+
+ runner [label="runner:\nMdrunner"],
+ CallParameter [label = "eventA:\nCallParameter"],
+ MOD [label = "mdModules_:\nMdModules"],
+ ModuleA [label="moduleA"],
+ ModuleB [label="moduleB"],
+ MdModuleNotification [label="notifier_:\nMdModuleNotification"];
+
+ MOD box MdModuleNotification [label = "mdModules_ owns notifier_ and moduleA/B"];
+ MOD =>> ModuleA [label="instantiates(notifier_)"];
+ ModuleA =>> MdModuleNotification [label="subscribe(otherfunc)"];
+ ModuleA =>> MOD;
+ MOD =>> ModuleB [label="instantiates(notifier_)"];
+ ModuleB =>> MdModuleNotification [label="subscribe(func)"];
+ ModuleB =>> MOD;
+ runner =>> CallParameter [label="instantiate"];
+ CallParameter =>> runner ;
+ runner =>> MOD [label="notify(eventA)"];
+ MOD =>> MdModuleNotification [label="notify(eventA)"];
+ MdModuleNotification =>> ModuleA [label="notify(eventA)"];
+ ModuleA -> ModuleA [label="func(eventA)"];
+ MdModuleNotification =>> ModuleB [label="notify(eventA)"];
+ ModuleB -> ModuleB [label="otherfunc(eventA)"];
+
+ \endmsc
+ *
+ * The template arguments to the members of this struct directly reflect
+ * the callback function signature. Arguments passed as pointers are always
+ * meant to be modified, but never meant to be stored (in line with the policy
+ * everywhere else).
+ */
struct MdModulesNotifier
{
- //! Register callback function types for MdModule
- registerMdModuleNotification<const t_commrec&,
- EnergyCalculationFrequencyErrors*,
- IndexGroupsAndNames,
- KeyValueTreeObjectBuilder,
- const KeyValueTreeObject&,
+ /*! \brief Pre-processing callback functions.
+ *
+ * EnergyCalculationFrequencyErrors* allows modules to check if they match
+ * their required calculation frequency
+ * and add their error message if needed
+ * to the collected error messages
+ * IndexGroupsAndNames provides modules with atom indices and their names
+ * KeyValueTreeObjectBuilder enables writing of module internal data to
+ * .tpr files.
+ */
+ registerMdModuleNotification<EnergyCalculationFrequencyErrors*, IndexGroupsAndNames, KeyValueTreeObjectBuilder>::type preProcessingNotifications_;
+
+ /*! \brief Checkpointing callback functions.
+ *
+ * MdModulesCheckpointReadingDataOnMaster provides modules with their
+ * checkpointed data on the master
+ * node and checkpoint file version
+ * MdModulesCheckpointReadingBroadcast provides modules with a communicator
+ * and the checkpoint file version to
+ * distribute their data
+ * MdModulesWriteCheckpointData provides the modules with a key-value-tree
+ * builder to store their checkpoint data and
+ * the checkpoint file version
+ */
+ registerMdModuleNotification<MdModulesCheckpointReadingDataOnMaster,
+ MdModulesCheckpointReadingBroadcast,
+ MdModulesWriteCheckpointData>::type checkpointingNotifications_;
+
+ /*! \brief Callbacks during simulation setup.
+ *
+ * const KeyValueTreeObject& provides modules with the internal data they
+ * wrote to .tpr files
+ * LocalAtomSetManager* enables modules to add atom indices to local atom sets
+ * to be managed
+ * MdModulesEnergyOutputToDensityFittingRequestChecker* enables modules to
+ * report if they want to write their energy output
+ * to the density fitting field in the energy files
+ * const PbcType& provides modules with the periodic boundary condition type
+ * that is used during the simulation
+ * const SimulationTimeStep& provides modules with the simulation time-step
+ * that allows them to interconvert between step
+ * time information
+ * const t_commrec& provides a communicator to the modules during simulation
+ * setup
+ */
+ registerMdModuleNotification<const KeyValueTreeObject&,
LocalAtomSetManager*,
MdModulesEnergyOutputToDensityFittingRequestChecker*,
- MdModulesCheckpointReadingDataOnMaster,
- MdModulesCheckpointReadingBroadcast,
- MdModulesWriteCheckpointData,
- PeriodicBoundaryConditionType,
- const SimulationTimeStep&>::type notifier_;
+ const PbcType&,
+ const SimulationTimeStep&,
+ const t_commrec&>::type simulationSetupNotifications_;
};
} // namespace gmx
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include <algorithm>
#include <string>
+#include <string_view>
#include <utility>
#include <sys/stat.h>
*
* \returns A view of the parent-path components, or empty if no
* directory separator exists. */
-compat::string_view getParentPathView(const std::string& input)
+std::string_view getParentPathView(const std::string& input)
{
- auto inputView = compat::to_string_view(input);
+ auto inputView = std::string_view(input);
size_t pos = inputView.find_last_of(cDirSeparators);
if (pos == std::string::npos)
{
- return compat::string_view();
+ return std::string_view();
}
return inputView.substr(0, pos);
}
* last directory separator (if one exists).
*
* \returns A view of the filename component. */
-compat::string_view getFilenameView(const compat::string_view input)
+std::string_view getFilenameView(const std::string_view input)
{
size_t pos = input.find_last_of(cDirSeparators);
if (pos == std::string::npos)
* filename component, ie. omitting any leading directories.
*
* \returns The view of the filename stem, or empty if none exists. */
-compat::string_view getStemView(const std::string& input)
+std::string_view getStemView(const std::string& input)
{
auto filenameView = getFilenameView(input);
size_t extensionSeparatorPosition = filenameView.find_last_of('.');
* filename component, ie. omitting any leading directories.
*
* \returns The view of the file extension, or empty if none exists. */
-compat::string_view getExtensionView(const compat::string_view input)
+std::string_view getExtensionView(const std::string_view input)
{
auto filenameView = getFilenameView(input);
size_t extensionSeparatorPosition = filenameView.find_last_of('.');
- if (extensionSeparatorPosition == compat::string_view::npos)
+ if (extensionSeparatorPosition == std::string_view::npos)
{
// No separator was found
- return compat::string_view();
+ return std::string_view();
}
return filenameView.substr(extensionSeparatorPosition);
}
std::string Path::getParentPath(const std::string& input)
{
- return compat::to_string(getParentPathView(input));
+ return std::string(getParentPathView(input));
}
std::string Path::getFilename(const std::string& input)
{
- return to_string(getFilenameView(input));
+ return std::string(getFilenameView(input));
}
bool Path::hasExtension(const std::string& input)
return getFilenameView(input).find('.') != std::string::npos;
}
-bool Path::extensionMatches(const compat::string_view input, const compat::string_view extension)
+bool Path::extensionMatches(const std::string_view input, const std::string_view extension)
{
auto extensionWithSeparator = getExtensionView(input);
return (!extensionWithSeparator.empty() && extensionWithSeparator.substr(1) == extension);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#define GMX_UTILITY_PATH_H
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
-#include "gromacs/compat/string_view.h"
-
namespace gmx
{
/*! \brief Returns whether the extension present in \c input
* matches \c extension (which does not include the separator
* character). */
- static bool extensionMatches(compat::string_view input, compat::string_view extension);
+ static bool extensionMatches(std::string_view input, std::string_view extension);
/*! \brief Returns a copy of the input without any trailing
* extension found in the filename component. */
static std::string stripExtension(const std::string& input);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_UTILITY_RANGE_H
#define GMX_UTILITY_RANGE_H
+#include <type_traits>
+
#include "gromacs/utility/gmxassert.h"
namespace gmx
//! Reference
operator T&() { return value_; }
//! Pointer
- int operator*() const { return value_; }
+ T operator*() const { return value_; }
//! Inequality comparison
bool operator!=(const iterator other) { return value_ != other.value_; }
//! Increment operator
return *this;
}
//! Increment operator
- iterator operator++(T gmx_unused dummy)
+ iterator operator++(int gmx_unused dummy)
{
iterator tmp(*this);
++value_;
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
static inline void gmx_snew_impl(const char* name, const char* file, int line, T*& ptr, size_t nelem)
{
static_assert(std::is_pod<T>::value, "snew() called on C++ type");
+ // NOLINTNEXTLINE bugprone-sizeof-expression
ptr = static_cast<T*>(save_calloc(name, file, line, nelem, sizeof(T)));
}
/** C++ helper for srenew(). */
static inline void gmx_srenew_impl(const char* name, const char* file, int line, T*& ptr, size_t nelem)
{
static_assert(std::is_pod<T>::value, "srenew() called on C++ type");
+ // NOLINTNEXTLINE bugprone-sizeof-expression
ptr = static_cast<T*>(save_realloc(name, file, line, ptr, nelem, sizeof(T)));
}
/** C++ helper for smalloc(). */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2013,2014,2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(UtilityUnitTests utility-test
- alignedallocator.cpp
- arrayref.cpp
- bitmask32.cpp bitmask64.cpp bitmask128.cpp
- cstringutil.cpp
- defaultinitializationallocator.cpp
- enumerationhelpers.cpp
- fixedcapacityvector.cpp
- inmemoryserializer.cpp
- keyvaluetreeserializer.cpp
- keyvaluetreetransform.cpp
- logger.cpp
- mutex.cpp
- path.cpp
- physicalnodecommunicator.cpp
- stringutil.cpp
- textreader.cpp
- textwriter.cpp
- typetraits.cpp
- )
+ CPP_SOURCE_FILES
+ alignedallocator.cpp
+ arrayref.cpp
+ bitmask32.cpp bitmask64.cpp bitmask128.cpp
+ cstringutil.cpp
+ defaultinitializationallocator.cpp
+ enumerationhelpers.cpp
+ fixedcapacityvector.cpp
+ inmemoryserializer.cpp
+ keyvaluetreeserializer.cpp
+ keyvaluetreetransform.cpp
+ listoflists.cpp
+ logger.cpp
+ mdmodulenotification-impl.cpp
+ mutex.cpp
+ path.cpp
+ physicalnodecommunicator.cpp
+ range.cpp
+ stringutil.cpp
+ textreader.cpp
+ textwriter.cpp
+ typetraits.cpp
+ )
gmx_add_mpi_unit_test(UtilityMpiUnitTests utility-mpi-test 4
- physicalnodecommunicator_mpi.cpp
- )
+ CPP_SOURCE_FILES
+ physicalnodecommunicator_mpi.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
real realValue_;
};
- void serialize(ISerializer* serializer, SerializerValues* values)
+ static void serialize(ISerializer* serializer, SerializerValues* values)
{
EXPECT_FALSE(serializer->reading());
doValues(serializer, values);
}
- SerializerValues deserialize(ISerializer* serializer)
+ static SerializerValues deserialize(ISerializer* serializer)
{
EXPECT_TRUE(serializer->reading());
SerializerValues result;
return result;
}
- void checkSerializerValuesforEquality(const SerializerValues& lhs, const SerializerValues& rhs)
+ static void checkSerializerValuesforEquality(const SerializerValues& lhs, const SerializerValues& rhs)
{
EXPECT_EQ(lhs.boolValue_, rhs.boolValue_);
EXPECT_EQ(lhs.unsignedCharValue_, rhs.unsignedCharValue_);
}
private:
- void doValues(ISerializer* serializer, SerializerValues* values)
+ static void doValues(ISerializer* serializer, SerializerValues* values)
{
serializer->doBool(&values->boolValue_);
serializer->doUChar(&values->unsignedCharValue_);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
gmx::KeyValueTreeBuilder builder_;
private:
- std::vector<char> serializeTree(const gmx::KeyValueTreeObject& tree)
+ static std::vector<char> serializeTree(const gmx::KeyValueTreeObject& tree)
{
gmx::InMemorySerializer serializer;
gmx::serializeKeyValueTree(tree, &serializer);
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for the ListOfLists class.
+ *
+ * \author berk Hess <hess@kth.se>
+ * \ingroup module_utility
+ */
+#include "gmxpre.h"
+
+#include "gromacs/utility/listoflists.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "testutils/testasserts.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+using ::testing::Eq;
+using ::testing::Pointwise;
+
+//! Compares all element between two lists of lists
+template<typename T>
+void compareLists(const ListOfLists<T>& list, const std::vector<std::vector<T>>& v)
+{
+ ASSERT_EQ(list.size(), v.size());
+ for (std::size_t i = 0; i < list.size(); i++)
+ {
+ ASSERT_EQ(list[i].size(), v[i].size());
+ EXPECT_THAT(list[i], Pointwise(Eq(), v[i]));
+ }
+}
+
+TEST(ListOfLists, EmptyListOfListsWorks)
+{
+ ListOfLists<char> list;
+
+ EXPECT_EQ(list.size(), 0);
+ EXPECT_EQ(list.empty(), true);
+ EXPECT_EQ(list.numElements(), 0);
+}
+
+//! Checks whether append works and stores the data correctly
+template<typename T>
+void checkAppend(const std::vector<std::vector<T>> inputLists)
+{
+ ListOfLists<T> list;
+
+ for (const auto& inputList : inputLists)
+ {
+ list.pushBack(inputList);
+ }
+ EXPECT_EQ(list.size(), 2);
+ compareLists(list, inputLists);
+}
+
+TEST(ListOfLists, AppendWorks)
+{
+ const std::vector<std::vector<char>> v = { { 5, 3 }, { char(-1), 7, 4 } };
+
+ checkAppend(v);
+}
+
+TEST(ListOfLists, EmptyListWorks)
+{
+ ListOfLists<char> list;
+
+ std::vector<char> v = { 5, 3 };
+ list.pushBack(v);
+ list.pushBack({});
+ EXPECT_EQ(list.size(), 2);
+ auto a = list[1];
+ EXPECT_EQ(a.empty(), true);
+}
+
+TEST(ListOfLists, AppendAccessWorks)
+{
+ const std::vector<std::vector<char>> v = { { 5, 3 }, { char(-1), 4 } };
+
+ ListOfLists<char> list;
+ list.pushBack(v[0]);
+ list.pushBackListOfSize(v[1].size());
+ std::copy(v[1].begin(), v[1].end(), list.back().begin());
+ compareLists(list, v);
+}
+
+TEST(ListOfLists, ClearWorks)
+{
+ ListOfLists<char> list;
+
+ std::vector<char> v = { 5, 3 };
+ list.pushBack(v);
+ list.pushBack({});
+ list.clear();
+ EXPECT_EQ(list.empty(), true);
+ EXPECT_EQ(list.numElements(), 0);
+}
+
+TEST(ListOfLists, OutOfRangeAccessThrows)
+{
+ ListOfLists<char> list;
+
+ std::vector<char> v = { 5, 3 };
+ EXPECT_THROW(list.at(1), std::out_of_range);
+}
+
+TEST(ListOfLists, FrontAndBackWork)
+{
+ ListOfLists<char> list1;
+ std::vector<char> v1{ { 3, 4 } };
+ list1.pushBack(v1);
+ EXPECT_THAT(list1.front(), Pointwise(Eq(), v1));
+ EXPECT_THAT(list1.back(), Pointwise(Eq(), v1));
+
+ std::vector<char> v2{ { 12, 63, 1 } };
+ list1.pushBack(v2);
+ EXPECT_THAT(list1.front(), Pointwise(Eq(), v1));
+ EXPECT_THAT(list1.back(), Pointwise(Eq(), v2));
+
+ list1.pushBack({});
+ EXPECT_THAT(list1.front(), Pointwise(Eq(), v1));
+ EXPECT_THAT(list1.back(), Pointwise(Eq(), std::vector<char>{}));
+
+ std::vector<char> v3{ { 99, 0, char(-1) } };
+ list1.pushBack(v3);
+ EXPECT_THAT(list1.front(), Pointwise(Eq(), v1));
+ EXPECT_THAT(list1.back(), Pointwise(Eq(), v3));
+
+ ListOfLists<char> list2;
+ list2.pushBack(v2);
+ EXPECT_THAT(list2.front(), Pointwise(Eq(), v2));
+ EXPECT_THAT(list2.back(), Pointwise(Eq(), v2));
+
+ list2.appendListOfLists(list1);
+ EXPECT_THAT(list2.front(), Pointwise(Eq(), v2));
+ EXPECT_THAT(list2.back(), Pointwise(Eq(), v3));
+ EXPECT_EQ(list2.back().size(), v3.size());
+
+ list2.pushBackListOfSize(1);
+ EXPECT_EQ(list2.back().size(), 1);
+}
+
+TEST(ListOfLists, ExtractsAndRestores)
+{
+ const std::vector<std::vector<char>> v({ { 5, 3 }, {}, { char(-1), 4 } });
+
+ ListOfLists<char> list1;
+ for (const auto& vlist : v)
+ {
+ list1.pushBack(vlist);
+ }
+
+ auto listRanges = list1.listRangesView();
+ auto elements = list1.elementsView();
+ std::vector<int> listRangesVector;
+ listRangesVector.insert(listRangesVector.begin(), listRanges.begin(), listRanges.end());
+ std::vector<char> elementsVector;
+ elementsVector.insert(elementsVector.begin(), elements.begin(), elements.end());
+ ListOfLists<char> list2(std::move(listRangesVector), std::move(elementsVector));
+ compareLists(list2, v);
+}
+
+TEST(ListOfLists, AppendsListOfListsWithOffset)
+{
+ std::vector<std::vector<char>> v = { { 5, 3 }, { 2, char(-1) }, { 4 } };
+
+ ListOfLists<char> list1;
+ ListOfLists<char> list2;
+
+ list1.pushBack(v[0]);
+ list2.pushBack(v[1]);
+ list2.pushBack(v[2]);
+ const char offset = 2;
+ list1.appendListOfLists(list2, offset);
+ for (std::size_t i = 1; i < v.size(); i++)
+ {
+ for (auto& elem : v[i])
+ {
+ elem += offset;
+ }
+ }
+ compareLists(list1, v);
+}
+
+} // namespace
+
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Tests MdModuleNotification
*
* \author Christian Blau <blau@kth.se>
- * \ingroup module_mdrun_integration_tests
+ * \ingroup module_utility
*/
#include "gmxpre.h"
-#include <gmock/gmock.h>
+#include "gromacs/utility/mdmodulenotification-impl.h"
-#include "gromacs/utility/mdmodulenotification.h"
+#include <gmock/gmock.h>
namespace gmx
{
class EventACallee final
{
public:
- void callback(EventA /*a*/) { notifiedEventA_ = true; };
+ void callback(EventA /*a*/) { notifiedEventA_ = true; }
bool notifiedEventA() { return notifiedEventA_; }
class EventBCallee final
{
public:
- void callback(EventB* /* bPointer */) { notifiedEventB_ = true; };
+ void callback(EventB* /* bPointer */) { notifiedEventB_ = true; }
bool notifiedEventB() { return notifiedEventB_; }
class EventAandBCallee final
{
public:
- void notify(EventB* /* bPointer */) { notifiedEventB_ = true; };
+ void notify(EventB* /* bPointer */) { notifiedEventB_ = true; }
- void callback(EventA /* a */) { notifiedEventA_ = true; };
+ void callback(EventA /* a */) { notifiedEventA_ = true; }
bool notifiedEventB() { return notifiedEventB_; }
bool notifiedEventA() { return notifiedEventA_; }
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "config.h"
#include <future>
+
#include <gtest/gtest.h>
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for the Range class.
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_utility
+ */
+#include "gmxpre.h"
+
+#include "gromacs/utility/range.h"
+
+#include <limits>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "testutils/testasserts.h"
+
+namespace gmx
+{
+
+namespace
+{
+
+TEST(Range, EmptyRangeWorks)
+{
+ Range<int> range;
+
+ EXPECT_EQ(range.empty(), true);
+ EXPECT_EQ(range.size(), 0);
+}
+
+TEST(Range, NonEmptyRangeWorks)
+{
+ const Range<char> range(3, 5);
+
+ EXPECT_EQ(range.empty(), false);
+ EXPECT_EQ(range.size(), 2);
+}
+
+TEST(Range, BeginEnd)
+{
+ const Range<long> range(-2, 9);
+
+ EXPECT_EQ(range.begin(), -2);
+ EXPECT_EQ(*range.begin(), -2);
+ EXPECT_EQ(range.end(), 9);
+ EXPECT_EQ(*range.end(), 9);
+}
+
+TEST(Range, IsInRangeWorks)
+{
+ const Range<size_t> range(5, 8);
+
+ EXPECT_EQ(range.isInRange(4), false);
+ EXPECT_EQ(range.isInRange(5), true);
+ EXPECT_EQ(range.isInRange(6), true);
+ EXPECT_EQ(range.isInRange(7), true);
+ EXPECT_EQ(range.isInRange(8), false);
+}
+
+TEST(Range, IteratorWorks)
+{
+ const Range<index> range(-1, 3);
+
+ int minValue = std::numeric_limits<int>::max();
+ int maxValue = std::numeric_limits<int>::min();
+ for (int i : range)
+ {
+ minValue = std::min(minValue, i);
+ maxValue = std::max(maxValue, i);
+ }
+ EXPECT_EQ(minValue, -1);
+ EXPECT_EQ(maxValue, 2);
+}
+
+} // namespace
+
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2010,2011,2012,2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+# Copyright (c) 2015,2016,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
gmx_target_compile_options(mdrun_objlib)
target_compile_definitions(mdrun_objlib PRIVATE HAVE_CONFIG_H)
target_include_directories(mdrun_objlib SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
+# Should be possible to remove this when resolving #3290
+target_include_directories(mdrun_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
if(GMX_FAHCORE)
# The lack of a real source file here alongside the object library
add_library(view_objlib OBJECT ${VIEW_SOURCES})
gmx_target_compile_options(view_objlib)
target_compile_definitions(view_objlib PRIVATE HAVE_CONFIG_H)
+ target_include_directories(view_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
+ add_library(gmx_objlib OBJECT ${GMX_MAIN_SOURCES})
+ target_include_directories(gmx_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
add_executable(gmx
- ${GMX_MAIN_SOURCES}
+ $<TARGET_OBJECTS:gmx_objlib>
$<TARGET_OBJECTS:mdrun_objlib>
$<TARGET_OBJECTS:view_objlib>)
gmx_target_compile_options(gmx)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
settings->setHelpText(desc);
- const char* const cNbnxmSimdStrings[] = { "auto", "no", "4xm", "2xmm" };
- const char* const cCombRuleStrings[] = { "geometric", "lb", "none" };
- const char* const cCoulombTypeStrings[] = { "ewald", "reaction-field" };
+ static const EnumerationArray<Nbnxm::BenchMarkKernels, const char*> c_nbnxmSimdStrings = {
+ { "auto", "no", "4xm", "2xmm" }
+ };
+ static const EnumerationArray<Nbnxm::BenchMarkCombRule, const char*> c_combRuleStrings = {
+ { "geometric", "lb", "none" }
+ };
+ static const EnumerationArray<Nbnxm::BenchMarkCoulomb, const char*> c_coulombTypeStrings = {
+ { "ewald", "reaction-field" }
+ };
options->addOption(
IntegerOption("size").store(&sizeFactor_).description("The system size is 3000 atoms times this value"));
IntegerOption("nt").store(&benchmarkOptions_.numThreads).description("The number of OpenMP threads to use"));
options->addOption(EnumOption<Nbnxm::BenchMarkKernels>("simd")
.store(&benchmarkOptions_.nbnxmSimd)
- .enumValue(cNbnxmSimdStrings)
+ .enumValue(c_nbnxmSimdStrings)
.description("SIMD type, auto runs all supported SIMD setups or no "
"SIMD when SIMD is not supported"));
options->addOption(EnumOption<Nbnxm::BenchMarkCoulomb>("coulomb")
.store(&benchmarkOptions_.coulombType)
- .enumValue(cCoulombTypeStrings)
+ .enumValue(c_coulombTypeStrings)
.description("The functional form for the Coulomb interactions"));
options->addOption(
BooleanOption("table")
.description("Use lookup table for Ewald correction instead of analytical"));
options->addOption(EnumOption<Nbnxm::BenchMarkCombRule>("combrule")
.store(&benchmarkOptions_.ljCombinationRule)
- .enumValue(cCombRuleStrings)
+ .enumValue(c_combRuleStrings)
.description("The LJ combination rule"));
options->addOption(BooleanOption("halflj")
.store(&benchmarkOptions_.useHalfLJOptimization)
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2013,2014,2015,2016,2017 The GROMACS development team.
+# Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
energyreader.cpp
energycomparison.cpp
moduletest.cpp
- mdmodulenotification.cpp
terminationhelper.cpp
trajectorycomparison.cpp
trajectoryreader.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
)
+target_include_directories(mdrun_test_infrastructure SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
set(testname "MdrunTests")
set(exename "mdrun-test")
-gmx_add_gtest_executable(
- ${exename}
- # files with code for tests
- compressed_x_output.cpp
- densityfittingmodule.cpp
- exactcontinuation.cpp
- grompp.cpp
- helpwriting.cpp
- initialconstraints.cpp
- interactiveMD.cpp
- outputfiles.cpp
- orires.cpp
- pmetest.cpp
- simulator.cpp
- swapcoords.cpp
- tabulated_bonded_interactions.cpp
- termination.cpp
- trajectory_writing.cpp
- mimic.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
+gmx_add_gtest_executable(${exename}
+ CPP_SOURCE_FILES
+ compressed_x_output.cpp
+ densityfittingmodule.cpp
+ exactcontinuation.cpp
+ ewaldsurfaceterm.cpp
+ grompp.cpp
+ helpwriting.cpp
+ initialconstraints.cpp
+ interactiveMD.cpp
+ orires.cpp
+ outputfiles.cpp
+ pmetest.cpp
+ simulator.cpp
+ swapcoords.cpp
+ tabulated_bonded_interactions.cpp
+ termination.cpp
+ trajectory_writing.cpp
+ mimic.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
)
target_link_libraries(${exename} PRIVATE mdrun_test_infrastructure)
-gmx_register_gtest_test(${testname} ${exename} OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(${testname} ${exename} OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
# To avoid running into test timeouts, some end-to-end tests of mdrun
# functionality are split off. This can be rearranged in future as we
set(testname "MdrunNonIntegratorTests")
set(exename "mdrun-non-integrator-test")
-gmx_add_gtest_executable(
- ${exename}
- # files with code for tests
- minimize.cpp
- nonbonded_bench.cpp
- normalmodes.cpp
- rerun.cpp
- simple_mdrun.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(${exename}
+ CPP_SOURCE_FILES
+ # files with code for tests
+ minimize.cpp
+ nonbonded_bench.cpp
+ normalmodes.cpp
+ rerun.cpp
+ simple_mdrun.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
target_link_libraries(${exename} PRIVATE mdrun_test_infrastructure)
-gmx_register_gtest_test(${testname} ${exename} OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(${testname} ${exename} OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
# TPI does not support OpenMP, so we need a separate test binary
set(testname "MdrunTpiTests")
set(exename "mdrun-tpi-test")
-gmx_add_gtest_executable(
- ${exename}
- # files with code for tests
- tpitest.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(${exename}
+ CPP_SOURCE_FILES
+ # files with code for tests
+ tpitest.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
target_link_libraries(${exename} PRIVATE mdrun_test_infrastructure)
-gmx_register_gtest_test(${testname} ${exename} INTEGRATION_TEST)
+gmx_register_gtest_test(${testname} ${exename} INTEGRATION_TEST IGNORE_LEAKS)
# Tests that only make sense to run with multiple ranks and/or real
# MPI are implemented here.
set(testname "MdrunMpiTests")
set(exename "mdrun-mpi-test")
-gmx_add_gtest_executable(
- ${exename} MPI
- # files with code for tests
- domain_decomposition.cpp
- minimize.cpp
- mimic.cpp
- multisim.cpp
- multisimtest.cpp
- pmetest.cpp
- replicaexchange.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(${exename} MPI
+ CPP_SOURCE_FILES
+ # files with code for tests
+ domain_decomposition.cpp
+ minimize.cpp
+ mimic.cpp
+ multisim.cpp
+ multisimtest.cpp
+ pmetest.cpp
+ replicaexchange.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
target_link_libraries(${exename} PRIVATE mdrun_test_infrastructure)
-gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST)
+gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 2 OPENMP_THREADS 2 INTEGRATION_TEST IGNORE_LEAKS)
# Slow-running tests that target testing multiple-rank coordination behaviors
set(exename "mdrun-mpi-coordination-test")
-gmx_add_gtest_executable(
- ${exename} MPI
- # files with code for tests
- periodicactions.cpp
- # pseudo-library for code for mdrun
- $<TARGET_OBJECTS:mdrun_objlib>
- )
+gmx_add_gtest_executable(${exename} MPI
+ CPP_SOURCE_FILES
+ # files with code for tests
+ periodicactions.cpp
+ # pseudo-library for code for mdrun
+ $<TARGET_OBJECTS:mdrun_objlib>
+ )
target_link_libraries(${exename} PRIVATE mdrun_test_infrastructure)
# These tests are extremely slow without optimization or OpenMP, so only run them for
# with OpenMP enabled.
if (CMAKE_BUILD_TYPE MATCHES "Rel" AND GMX_OPENMP)
set(testname "MdrunMpiCoordinationTestsOneRank")
- gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 1 SLOW_TEST)
+ gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 1 SLOW_TEST IGNORE_LEAKS)
set(testname "MdrunMpiCoordinationTestsTwoRanks")
- gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 2 SLOW_TEST)
+ gmx_register_gtest_test(${testname} ${exename} MPI_RANKS 2 SLOW_TEST IGNORE_LEAKS)
endif()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
namespace test
{
-const EnergyTermsToCompare EnergyComparison::s_defaultEnergyTermsToCompare = {
- { interaction_function[F_EPOT].longname, relativeToleranceAsUlp(10.0, 50) },
- { interaction_function[F_EKIN].longname, relativeToleranceAsUlp(10.0, 50) },
- // The pressure is very strongly affected by summation errors,
- // so we need a large tolerance.
- // The value of 15000 is calibrated for running a small water box for 16 steps.
- // For a single frame for a water box a value of 150 could work.
- { interaction_function[F_PRES].longname, relativeToleranceAsUlp(10.0, 15000) },
+EnergyTermsToCompare EnergyComparison::defaultEnergyTermsToCompare()
+{
+ return {
+ { interaction_function[F_EPOT].longname, relativeToleranceAsUlp(10.0, 50) },
+ { interaction_function[F_EKIN].longname, relativeToleranceAsUlp(10.0, 50) },
+ // The pressure is very strongly affected by summation errors,
+ // so we need a large tolerance.
+ // The value of 15000 is calibrated for running a small water box for 16 steps.
+ // For a single frame for a water box a value of 150 could work.
+ { interaction_function[F_PRES].longname, relativeToleranceAsUlp(10.0, 15000) },
+ };
};
EnergyComparison::EnergyComparison(const EnergyTermsToCompare& energyTermsToCompare) :
const EnergyFrame& frame = energyReader->frame();
const std::string frameName = frame.frameName() + " in frame " + toString(frameNumber);
+ SCOPED_TRACE("Comparing frame " + frameName);
for (const auto& energyTermToCompare : energyTermsToCompare)
{
const std::string& energyName = energyTermToCompare.first;
const real energyValue = frame.at(energyName);
- SCOPED_TRACE("Comparing " + energyName + " in " + frameName);
+ SCOPED_TRACE("Comparing energy " + energyName);
checkers[energyName].checkReal(energyValue, frameName.c_str());
}
++frameNumber;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
public:
//! Defaults for energy comparisons
- static const EnergyTermsToCompare s_defaultEnergyTermsToCompare;
+ static EnergyTermsToCompare defaultEnergyTermsToCompare();
//! Constructor
EnergyComparison(const EnergyTermsToCompare& energyTermsToCompare);
/*! \brief Return the names of energies that will be compared
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+
+/*! \internal \file
+ * \brief
+ * Test for Ewald 3DC and epsilon-surface terms.
+ *
+ * \author Berk Hess <hess@kth.se>
+ * \ingroup module_mdrun_integration_tests
+ */
+#include "gmxpre.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/topology/idef.h"
+#include "gromacs/topology/ifunc.h"
+#include "gromacs/trajectory/trajectoryframe.h"
+#include "gromacs/utility/basenetwork.h"
+#include "gromacs/utility/filestream.h"
+#include "gromacs/utility/strconvert.h"
+#include "gromacs/utility/stringutil.h"
+
+#include "testutils/mpitest.h"
+#include "testutils/refdata.h"
+#include "testutils/simulationdatabase.h"
+#include "testutils/testasserts.h"
+
+#include "energycomparison.h"
+#include "moduletest.h"
+#include "trajectoryreader.h"
+
+namespace gmx
+{
+namespace test
+{
+namespace
+{
+
+//! Helper type
+using MdpField = MdpFieldValues::value_type;
+
+/*! \brief Test fixture base for simple mdrun systems
+ *
+ * This test ensures mdrun can run a simulation, reaching reproducible
+ * energies and forces.
+ * The starting coordinates are set up such that both molecules are
+ * broken over PBC and the PBC treatment is tested.
+ */
+class EwaldSurfaceTermTest : public MdrunTestFixture, public ::testing::WithParamInterface<std::string>
+{
+};
+
+TEST_P(EwaldSurfaceTermTest, WithinTolerances)
+{
+ auto simulationName = GetParam();
+ SCOPED_TRACE(formatString("Comparing simple mdrun for '%s'", simulationName.c_str()));
+
+ int numRanksAvailable = getNumberOfTestMpiRanks();
+ /* For epsilon-surface we need whole molecules.
+ * Without constraints we can make molecules whole on a sinlge rank.
+ * With constraints molecules are whole with update groups with DD.
+ *
+ * TODO: Remove the rank=1 check when DD also runs single rank.
+ */
+ if ((simulationName == "epsilon-surface" && numRanksAvailable > 1)
+ || (simulationName == "epsilon-surface-constraint" && numRanksAvailable == 1))
+ {
+ fprintf(stdout,
+ "Test system '%s' cannot run with %d ranks.\n"
+ "The supported numbers are %s 1.\n",
+ simulationName.c_str(), numRanksAvailable, numRanksAvailable == 1 ? ">" : "=");
+ return;
+ }
+
+ std::string theMdpFile =
+ "coulombtype = PME\n"
+ "nstcalcenergy = 1\n"
+ "nstenergy = 4\n"
+ "nstfout = 4\n"
+ "rcoulomb = 1.5\n"
+ "rvdw = 1.5\n"
+ "pme-order = 4\n"
+ "fourier-spacing = 0.2\n"
+ "dt = 0.0025\n"
+ "nsteps = 20\n";
+
+ if (simulationName == "3DC")
+ {
+ theMdpFile +=
+ "ewald-geometry = 3DC\n"
+ "pbc = xy\n"
+ "nwall = 2\n"
+ "wall-type = 12-6\n"
+ "wall-atomtype = C C\n"
+ "wall-ewald-zfac = 2\n";
+ }
+ else
+ {
+ theMdpFile += "epsilon-surface = 1\n";
+ if (simulationName == "epsilon-surface-constraint")
+ {
+ theMdpFile += "constraints = all-bonds";
+ }
+ }
+
+ // Prepare the .tpr file
+ {
+ CommandLine caller;
+ runner_.useTopGroAndNdxFromDatabase("dipoles");
+ runner_.useStringAsMdpFile(theMdpFile);
+ EXPECT_EQ(0, runner_.callGrompp(caller));
+ }
+ // Do mdrun
+ {
+ CommandLine mdrunCaller;
+ ASSERT_EQ(0, runner_.callMdrun(mdrunCaller));
+ EnergyTermsToCompare energyTermsToCompare{
+ { { interaction_function[F_EPOT].longname, absoluteTolerance(1e-3) },
+ { interaction_function[F_ETOT].longname, absoluteTolerance(1e-3) } }
+ };
+ TestReferenceData refData;
+ auto checker = refData.rootChecker().checkCompound("Simulation", simulationName);
+ checkEnergiesAgainstReferenceData(runner_.edrFileName_, energyTermsToCompare, &checker);
+ // Now check the forces
+ TrajectoryFrameReader reader(runner_.fullPrecisionTrajectoryFileName_);
+ checker.setDefaultTolerance(relativeToleranceAsFloatingPoint(1, 1e-3));
+ do
+ {
+ auto frame = reader.frame();
+ auto force = frame.f();
+ int atom = 0;
+ for (auto& f : force)
+ {
+ std::string forceName = frame.frameName() + " F[" + toString(atom) + "]";
+
+ checker.checkVector(f, forceName.c_str());
+ atom++;
+ }
+ } while (reader.readNextFrame());
+ }
+}
+
+//! Containers of systems to test.
+//! \{
+std::vector<std::string> surfaceTerm = { "3DC", "epsilon-surface-constraint", "epsilon-surface" };
+//! \}
+
+INSTANTIATE_TEST_CASE_P(EwaldSurfaceTerm, EwaldSurfaceTermTest, ::testing::ValuesIn(surfaceTerm));
+
+} // namespace
+} // namespace test
+} // namespace gmx
caller.addOption("-maxwarn", maxWarningsTolerated);
runner->useTopGroAndNdxFromDatabase(simulationName);
auto firstPartMdpFieldValues = mdpFieldValues;
- firstPartMdpFieldValues["nsteps"] = "8";
+ firstPartMdpFieldValues["nsteps"] = std::to_string(std::stoi(mdpFieldValues.at("nsteps")) / 2);
runner->useStringAsMdpFile(prepareMdpFileContents(firstPartMdpFieldValues));
runner->tprFileName_ = firstPartRunTprFileName;
EXPECT_EQ(0, runner->callGrompp(caller));
// The exact lambda state choice is unimportant, so long as there
// is one when using an FEP input.
mdpFieldValues["other"] += formatString("\ninit-lambda-state = %d", 3);
+ mdpFieldValues["nsteps"] = "16";
// Forces on GPUs are generally not reproducible enough for a tight
// tolerance. Similarly, the propagation of sd and bd are not as
// as the others, either in continuations or reruns.
ulpToleranceInMixed = 128;
}
- EnergyTermsToCompare energyTermsToCompare{ {
- { interaction_function[F_EPOT].longname,
- relativeToleranceAsPrecisionDependentUlp(10.0, ulpToleranceInMixed, ulpToleranceInDouble) },
- } };
+ EnergyTermsToCompare energyTermsToCompare{
+ { { interaction_function[F_EPOT].longname,
+ relativeToleranceAsPrecisionDependentUlp(10.0, ulpToleranceInMixed, ulpToleranceInDouble) },
+ { interaction_function[F_EKIN].longname,
+ relativeToleranceAsPrecisionDependentUlp(10.0, ulpToleranceInMixed, ulpToleranceInDouble) } }
+ };
+
+ if (temperatureCoupling != "no" || pressureCoupling != "no")
+ {
+ energyTermsToCompare.insert({ interaction_function[F_ECONSERVED].longname,
+ relativeToleranceAsPrecisionDependentUlp(
+ 10.0, ulpToleranceInMixed, ulpToleranceInDouble) });
+ }
+
+ if (pressureCoupling == "parrinello-rahman")
+ {
+ energyTermsToCompare.insert(
+ { "Box-Vel-XX", relativeToleranceAsPrecisionDependentUlp(1e-12, ulpToleranceInMixed,
+ ulpToleranceInDouble) });
+ energyTermsToCompare.insert(
+ { "Box-Vel-YY", relativeToleranceAsPrecisionDependentUlp(1e-12, ulpToleranceInMixed,
+ ulpToleranceInDouble) });
+ energyTermsToCompare.insert(
+ { "Box-Vel-ZZ", relativeToleranceAsPrecisionDependentUlp(1e-12, ulpToleranceInMixed,
+ ulpToleranceInDouble) });
+ }
int numWarningsToTolerate = 1;
runTest(&fileManager_, &runner_, simulationName, numWarningsToTolerate, mdpFieldValues,
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// things that way, this function should be renamed. For now,
// we use the Verlet scheme and hard-code a tolerance.
// TODO There is possible outstanding unexplained behaviour of mdp
-// input parsing e.g. Redmine 2074, so this particular set of mdp
+// input parsing e.g. Issue #2074, so this particular set of mdp
// contents is also tested with GetIrTest in gmxpreprocess-test.
void SimulationRunner::useEmptyMdpFile()
{
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
//! Names for the output files from the reference mdrun call
ReferenceFileNames referenceFileNames_ = { fileManager_.getTemporaryFilePath("reference.edr") };
//! Functor for energy comparison
- EnergyComparison energyComparison_{ EnergyComparison::s_defaultEnergyTermsToCompare };
+ EnergyComparison energyComparison_{ EnergyComparison::defaultEnergyTermsToCompare() };
//! Names of energies compared by energyComparison_
std::vector<std::string> namesOfEnergiesToMatch_ = energyComparison_.getEnergyNames();
};
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
for (const auto& mode : runModes)
{
+ SCOPED_TRACE("mdrun " + joinStrings(mode.second, " "));
auto modeTargetsGpus = (mode.first.find("Gpu") != std::string::npos);
if (modeTargetsGpus && !s_hasCompatibleGpus)
{
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Simulation Name="3DC">
+ <Energy Name="Total Energy">
+ <Real Name="Time 0.000000 Step 0 in frame 0">35.954109</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">35.93243</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">35.888763</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">35.851433</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">35.843254</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">35.868946</Real>
+ </Energy>
+ <Energy Name="Potential">
+ <Real Name="Time 0.000000 Step 0 in frame 0">35.838486</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">31.51033</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">22.831844</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">15.060135</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">12.742168</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">16.857098</Real>
+ </Energy>
+ <Vector Name="Time 0.000000 Step 0 F[0]">
+ <Real Name="X">0.63591957</Real>
+ <Real Name="Y">519.72107</Real>
+ <Real Name="Z">387.92822</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[1]">
+ <Real Name="X">-0.77027768</Real>
+ <Real Name="Y">-519.39612</Real>
+ <Real Name="Z">-377.65155</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[2]">
+ <Real Name="X">18.781555</Real>
+ <Real Name="Y">-2.0529842</Real>
+ <Real Name="Z">14.781036</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[3]">
+ <Real Name="X">-18.647247</Real>
+ <Real Name="Y">1.7278194</Real>
+ <Real Name="Z">-234.13368</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[0]">
+ <Real Name="X">0.62046039</Real>
+ <Real Name="Y">466.01166</Real>
+ <Real Name="Z">349.07852</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[1]">
+ <Real Name="X">-0.75117296</Real>
+ <Real Name="Y">-465.69577</Real>
+ <Real Name="Z">-339.0498</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[2]">
+ <Real Name="X">11.485992</Real>
+ <Real Name="Y">-2.0129957</Real>
+ <Real Name="Z">7.3729095</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[3]">
+ <Real Name="X">-11.355316</Real>
+ <Real Name="Y">1.6968718</Real>
+ <Real Name="Z">-222.63599</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[0]">
+ <Real Name="X">0.59271532</Real>
+ <Real Name="Y">334.89679</Real>
+ <Real Name="Z">254.41725</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[1]">
+ <Real Name="X">-0.71474606</Real>
+ <Real Name="Y">-334.60272</Real>
+ <Real Name="Z">-244.95985</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[2]">
+ <Real Name="X">-6.2411346</Real>
+ <Real Name="Y">-1.9218638</Real>
+ <Real Name="Z">-10.294846</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[3]">
+ <Real Name="X">6.3630676</Real>
+ <Real Name="Y">1.6275122</Real>
+ <Real Name="Z">-195.02248</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[0]">
+ <Real Name="X">0.58192861</Real>
+ <Real Name="Y">147.74336</Real>
+ <Real Name="Z">119.82979</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[1]">
+ <Real Name="X">-0.69187623</Real>
+ <Real Name="Y">-147.47998</Real>
+ <Real Name="Z">-111.1104</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[2]">
+ <Real Name="X">-31.277664</Real>
+ <Real Name="Y">-1.8096745</Real>
+ <Real Name="Z">-34.310486</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[3]">
+ <Real Name="X">31.387344</Real>
+ <Real Name="Y">1.5458357</Real>
+ <Real Name="Z">-156.77382</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[0]">
+ <Real Name="X">0.62886125</Real>
+ <Real Name="Y">-64.947739</Real>
+ <Real Name="Z">-32.052841</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[1]">
+ <Real Name="X">-0.72547024</Real>
+ <Real Name="Y">65.176849</Real>
+ <Real Name="Z">40.033974</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[2]">
+ <Real Name="X">-59.076599</Real>
+ <Real Name="Y">-1.7106733</Real>
+ <Real Name="Z">-59.353546</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[3]">
+ <Real Name="X">59.172882</Real>
+ <Real Name="Y">1.4807854</Real>
+ <Real Name="Z">-115.10541</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[0]">
+ <Real Name="X">0.78214669</Real>
+ <Real Name="Y">-268.51788</Real>
+ <Real Name="Z">-175.65146</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[1]">
+ <Real Name="X">-0.86627579</Real>
+ <Real Name="Y">268.71423</Real>
+ <Real Name="Z">183.01443</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[2]">
+ <Real Name="X">-84.336151</Real>
+ <Real Name="Y">-1.6569676</Real>
+ <Real Name="Z">-79.859665</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[3]">
+ <Real Name="X">84.419815</Real>
+ <Real Name="Y">1.4594903</Real>
+ <Real Name="Z">-77.279404</Real>
+ </Vector>
+ </Simulation>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Simulation Name="epsilon-surface-constraint">
+ <Energy Name="Total Energy">
+ <Real Name="Time 0.000000 Step 0 in frame 0">-0.34057474</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">-0.34058204</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">-0.34044197</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">-0.34037</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">-0.34102595</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">-0.34038031</Real>
+ </Energy>
+ <Energy Name="Potential">
+ <Real Name="Time 0.000000 Step 0 in frame 0">-0.34057617</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">-0.34064102</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">-0.34065056</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">-0.34082031</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">-0.34181023</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">-0.34159088</Real>
+ </Energy>
+ <Vector Name="Time 0.000000 Step 0 F[0]">
+ <Real Name="X">1.6149496</Real>
+ <Real Name="Y">-0.086868286</Real>
+ <Real Name="Z">-1.0419159</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[1]">
+ <Real Name="X">-1.8542147</Real>
+ <Real Name="Y">-0.25299072</Real>
+ <Real Name="Z">0.80174255</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[2]">
+ <Real Name="X">-0.064361572</Real>
+ <Real Name="Y">-0.8647213</Real>
+ <Real Name="Z">-1.2425385</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[3]">
+ <Real Name="X">0.30360413</Real>
+ <Real Name="Y">1.2046714</Real>
+ <Real Name="Z">1.4829559</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[0]">
+ <Real Name="X">1.6154348</Real>
+ <Real Name="Y">-0.087356567</Real>
+ <Real Name="Z">-1.0413895</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[1]">
+ <Real Name="X">-1.8548124</Real>
+ <Real Name="Y">-0.25245667</Real>
+ <Real Name="Z">0.80117035</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[2]">
+ <Real Name="X">-0.064651489</Real>
+ <Real Name="Y">-0.864492</Real>
+ <Real Name="Z">-1.2429199</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[3]">
+ <Real Name="X">0.30400085</Real>
+ <Real Name="Y">1.2044551</Real>
+ <Real Name="Z">1.4832764</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[0]">
+ <Real Name="X">1.6154604</Real>
+ <Real Name="Y">-0.087097168</Real>
+ <Real Name="Z">-1.0424576</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[1]">
+ <Real Name="X">-1.8550944</Real>
+ <Real Name="Y">-0.25256348</Real>
+ <Real Name="Z">0.80217743</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[2]">
+ <Real Name="X">-0.064407349</Real>
+ <Real Name="Y">-0.86516654</Real>
+ <Real Name="Z">-1.2433014</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[3]">
+ <Real Name="X">0.3039093</Real>
+ <Real Name="Y">1.2051598</Real>
+ <Real Name="Z">1.4837341</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[0]">
+ <Real Name="X">1.6158544</Real>
+ <Real Name="Y">-0.087295532</Real>
+ <Real Name="Z">-1.0429993</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[1]">
+ <Real Name="X">-1.8559394</Real>
+ <Real Name="Y">-0.25222778</Real>
+ <Real Name="Z">0.80271912</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[2]">
+ <Real Name="X">-0.065734863</Real>
+ <Real Name="Y">-0.86546493</Real>
+ <Real Name="Z">-1.2434998</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[3]">
+ <Real Name="X">0.30551147</Real>
+ <Real Name="Y">1.2055182</Real>
+ <Real Name="Z">1.4839935</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[0]">
+ <Real Name="X">1.6170367</Real>
+ <Real Name="Y">-0.08883667</Real>
+ <Real Name="Z">-1.0432281</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[1]">
+ <Real Name="X">-1.8577462</Real>
+ <Real Name="Y">-0.25038147</Real>
+ <Real Name="Z">0.80291748</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[2]">
+ <Real Name="X">-0.067520142</Real>
+ <Real Name="Y">-0.86665791</Real>
+ <Real Name="Z">-1.2446899</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[3]">
+ <Real Name="X">0.30763245</Real>
+ <Real Name="Y">1.2067299</Real>
+ <Real Name="Z">1.4853821</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[0]">
+ <Real Name="X">1.6183333</Real>
+ <Real Name="Y">-0.088378906</Real>
+ <Real Name="Z">-1.0447006</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[1]">
+ <Real Name="X">-1.859828</Real>
+ <Real Name="Y">-0.25050354</Real>
+ <Real Name="Z">0.80425262</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[2]">
+ <Real Name="X">-0.068191528</Real>
+ <Real Name="Y">-0.86807513</Real>
+ <Real Name="Z">-1.2454529</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[3]">
+ <Real Name="X">0.3087616</Real>
+ <Real Name="Y">1.2082047</Real>
+ <Real Name="Z">1.4863129</Real>
+ </Vector>
+ </Simulation>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <Simulation Name="epsilon-surface">
+ <Energy Name="Total Energy">
+ <Real Name="Time 0.000000 Step 0 in frame 0">20.32147</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">20.300804</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">20.259245</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">20.223288</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">20.215561</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">20.240704</Real>
+ </Energy>
+ <Energy Name="Potential">
+ <Real Name="Time 0.000000 Step 0 in frame 0">20.214478</Real>
+ <Real Name="Time 0.010000 Step 4 in frame 1">16.217239</Real>
+ <Real Name="Time 0.020000 Step 8 in frame 2">8.2757568</Real>
+ <Real Name="Time 0.030000 Step 12 in frame 3">1.3982239</Real>
+ <Real Name="Time 0.040000 Step 16 in frame 4">-0.07736969</Real>
+ <Real Name="Time 0.050000 Step 20 in frame 5">4.7798805</Real>
+ </Energy>
+ <Vector Name="Time 0.000000 Step 0 F[0]">
+ <Real Name="X">1.6004291</Real>
+ <Real Name="Y">522.04138</Real>
+ <Real Name="Z">370.92786</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[1]">
+ <Real Name="X">-1.900637</Real>
+ <Real Name="Y">-522.46527</Real>
+ <Real Name="Z">-371.22949</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[2]">
+ <Real Name="X">20.091843</Real>
+ <Real Name="Y">-1.0637188</Real>
+ <Real Name="Z">18.672668</Real>
+ </Vector>
+ <Vector Name="Time 0.000000 Step 0 F[3]">
+ <Real Name="X">-19.791595</Real>
+ <Real Name="Y">1.4878402</Real>
+ <Real Name="Z">-18.371048</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[0]">
+ <Real Name="X">1.5716085</Real>
+ <Real Name="Y">468.56262</Real>
+ <Real Name="Z">332.87283</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[1]">
+ <Real Name="X">-1.8655734</Real>
+ <Real Name="Y">-468.97778</Real>
+ <Real Name="Z">-333.16809</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[2]">
+ <Real Name="X">18.114136</Real>
+ <Real Name="Y">-1.0417742</Real>
+ <Real Name="Z">16.720505</Real>
+ </Vector>
+ <Vector Name="Time 0.010000 Step 4 F[3]">
+ <Real Name="X">-17.82019</Real>
+ <Real Name="Y">1.4571649</Real>
+ <Real Name="Z">-16.425293</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[0]">
+ <Real Name="X">1.5227978</Real>
+ <Real Name="Y">338.07782</Real>
+ <Real Name="Z">239.98503</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[1]">
+ <Real Name="X">-1.801703</Real>
+ <Real Name="Y">-338.47165</Real>
+ <Real Name="Z">-240.26477</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[2]">
+ <Real Name="X">13.286667</Real>
+ <Real Name="Y">-0.99115908</Real>
+ <Real Name="Z">11.956177</Real>
+ </Vector>
+ <Vector Name="Time 0.020000 Step 8 F[3]">
+ <Real Name="X">-13.007904</Real>
+ <Real Name="Y">1.3853663</Real>
+ <Real Name="Z">-11.676315</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[0]">
+ <Real Name="X">1.5251596</Real>
+ <Real Name="Y">152.05093</Real>
+ <Real Name="Z">107.45719</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[1]">
+ <Real Name="X">-1.7829351</Real>
+ <Real Name="Y">-152.41469</Real>
+ <Real Name="Z">-107.71528</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[2]">
+ <Real Name="X">6.4033661</Real>
+ <Real Name="Y">-0.92074591</Real>
+ <Real Name="Z">5.1584015</Real>
+ </Vector>
+ <Vector Name="Time 0.030000 Step 12 F[3]">
+ <Real Name="X">-6.1460266</Real>
+ <Real Name="Y">1.2851006</Real>
+ <Real Name="Z">-4.9001007</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[0]">
+ <Real Name="X">1.6834296</Real>
+ <Real Name="Y">-58.880402</Real>
+ <Real Name="Z">-43.009636</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[1]">
+ <Real Name="X">-1.9177186</Real>
+ <Real Name="Y">58.550491</Real>
+ <Real Name="Z">42.775757</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[2]">
+ <Real Name="X">-1.4052582</Real>
+ <Real Name="Y">-0.84537828</Real>
+ <Real Name="Z">-2.5614777</Real>
+ </Vector>
+ <Vector Name="Time 0.040000 Step 16 F[3]">
+ <Real Name="X">1.6388092</Real>
+ <Real Name="Y">1.1762809</Real>
+ <Real Name="Z">2.7957458</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[0]">
+ <Real Name="X">2.1072018</Real>
+ <Real Name="Y">-259.95499</Real>
+ <Real Name="Z">-186.73514</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[1]">
+ <Real Name="X">-2.3196166</Real>
+ <Real Name="Y">259.6571</Real>
+ <Real Name="Z">186.52396</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[2]">
+ <Real Name="X">-8.8654175</Real>
+ <Real Name="Y">-0.77974892</Real>
+ <Real Name="Z">-9.9438782</Real>
+ </Vector>
+ <Vector Name="Time 0.050000 Step 20 F[3]">
+ <Real Name="X">9.0768127</Real>
+ <Real Name="Y">1.0791473</Real>
+ <Real Name="Z">10.155777</Real>
+ </Vector>
+ </Simulation>
+</ReferenceData>
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* needed/useful.
*
* We should also not compare pressure, because with constraints the
- * non-search steps need a much larger tolerance, and per Redmine 1868
+ * non-search steps need a much larger tolerance, and per Issue #1868
* we should stop computing pressure in reruns anyway.
*
* Similarly, per 1868, in the present implementation the kinetic
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
fourthPart.append("mdrun");
fourthPart.addOption("-cpi", runner_.cptFileName_);
fourthPart.addOption("-cpo", runner_.cptFileName_);
- // TODO this is necessary, but ought not be. Is this the issue in Redmine #2804?
+ // TODO this is necessary, but ought not be. Is this the issue in Issue #2804?
fourthPart.append("-noappend");
runner_.edrFileName_ = fileManager_.getTemporaryFilePath(".part0004.edr");
runner_.logFileName_ = fileManager_.getTemporaryFilePath(".part0004.log");
fifthPart.append("mdrun");
fifthPart.addOption("-cpi", runner_.cptFileName_);
fifthPart.addOption("-cpo", runner_.cptFileName_);
- // TODO this is necessary, but ought not be. Is this the issue in Redmine #2804?
+ // TODO this is necessary, but ought not be. Is this the issue in Issue #2804?
fifthPart.append("-noappend");
runner_.edrFileName_ = fileManager_.getTemporaryFilePath(".part0005.edr");
runner_.logFileName_ = fileManager_.getTemporaryFilePath(".part0005.log");
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
snew(man->bHydro, sh.natoms);
snew(bB, sh.natoms);
read_tpx_top(status, nullptr, man->box, &man->natom, nullptr, nullptr, &man->top);
- man->gpbc = gmx_rmpbc_init(&man->top.idef, -1, man->natom);
+ man->gpbc = gmx_rmpbc_init(&man->top.idef, PbcType::Unset, man->natom);
man->natom = read_first_x(man->oenv, &man->status, trajectory, &(man->time), &(man->x), man->box);
man->trajfile = gmx_strdup(trajectory);
put_atoms_in_triclinic_unitcell(ecenterDEF, man->box, atomsArrayRef);
break;
case esbTrunc:
- put_atoms_in_compact_unitcell(man->molw->ePBC, ecenterDEF, man->box, atomsArrayRef);
+ put_atoms_in_compact_unitcell(man->molw->pbcType, ecenterDEF, man->box, atomsArrayRef);
break;
case esbRect:
case esbNone:
int height,
unsigned long fg,
unsigned long bg,
- int ePBC,
+ PbcType pbcType,
matrix box,
gmx_output_env_t* oenv)
{
/* The order of creating windows is important for the stacking order */
/* Mol Window */
- man->molw = init_mw(x11, man->wd.self, 0, 0, 1, 1, WHITE, BLUE, ePBC, box);
+ man->molw = init_mw(x11, man->wd.self, 0, 0, 1, 1, WHITE, BLUE, pbcType, box);
/* Title Window */
InitWin(&(man->title), 0, 0, 1, 1, 0, nullptr);
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "xutil.h"
struct gmx_output_env_t;
+enum class PbcType : int;
/* Some window sizes */
#define EWIDTH 200
t_windata wd; /* Mol window structure */
bool bShowHydrogen; /* Show Hydrogens? */
int bond_type; /* Show one of the above bondtypes */
- int ePBC; /* PBC type */
+ PbcType pbcType; /* PBC type */
int boxtype; /* Rectangular, Tric, TruncOct (display)*/
int realbox; /* Property of the real box */
} t_molwin;
int height,
unsigned long fg,
unsigned long bg,
- int ePBC,
+ PbcType pbcType,
matrix box,
gmx_output_env_t* oenv);
/* Initiate the display manager */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2013, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return false;
}
-static void set_def(t_molwin* mw, int ePBC, matrix box)
+static void set_def(t_molwin* mw, PbcType pbcType, matrix box)
{
mw->bShowHydrogen = true;
mw->bond_type = eBFat;
- mw->ePBC = ePBC;
+ mw->pbcType = pbcType;
mw->boxtype = esbRect;
mw->realbox = TRICLINIC(box) ? esbTri : esbRect;
}
int height,
unsigned long fg,
unsigned long bg,
- int ePBC,
+ PbcType pbcType,
matrix box)
{
t_molwin* mw;
snew(mw, 1);
- set_def(mw, ePBC, box);
+ set_def(mw, pbcType, box);
InitWin(&mw->wd, x, y, width, height, 1, "Mol Window");
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
int height,
unsigned long fg,
unsigned long bg,
- int ePBC,
+ PbcType pbcType,
matrix box);
/* Create the molecule window using the x,y etc. */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
case IDEXPORT: ShowDlg(gmx->dlgs[edExport]); break;
case IDDOEXPORT:
write_sto_conf(gmx->confout, *gmx->man->top.name, &(gmx->man->top.atoms), gmx->man->x,
- nullptr, gmx->man->molw->ePBC, gmx->man->box);
+ nullptr, gmx->man->molw->pbcType, gmx->man->box);
break;
case IDQUIT: show_mb(gmx, emQuit); break;
case IDTERM: done_gmx(x11, gmx); return true;
int w0, h0;
int natom, natom_trx;
t_topology top;
- int ePBC;
+ PbcType pbcType;
matrix box;
t_trxframe fr;
t_trxstatus* status;
snew(gmx, 1);
snew(gmx->wd, 1);
- ePBC = read_tpx_top(ftp2fn(efTPR, nfile, fnm), nullptr, box, &natom, nullptr, nullptr, &top);
+ pbcType = read_tpx_top(ftp2fn(efTPR, nfile, fnm), nullptr, box, &natom, nullptr, nullptr, &top);
read_first_frame(oenv, &status, ftp2fn(efTRX, nfile, fnm), &fr, TRX_DONT_SKIP);
close_trx(status);
/* The order of creating windows is important here! */
/* Manager */
- gmx->man = init_man(x11, gmx->wd->self, 0, 0, 1, 1, WHITE, BLACK, ePBC, box, oenv);
+ gmx->man = init_man(x11, gmx->wd->self, 0, 0, 1, 1, WHITE, BLACK, pbcType, box, oenv);
gmx->logo = init_logo(x11, gmx->wd->self, false);
/* Now put all windows in the proper place */
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013,2014,2015, The GROMACS development team.
+# Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
# Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+# Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
include(CMakeParseArguments)
+include(gmxClangCudaUtils)
function (gmx_add_unit_test_library NAME)
if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
target_compile_definitions(${NAME} PRIVATE HAVE_CONFIG_H)
target_include_directories(${NAME} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
target_link_libraries(${NAME} PRIVATE testutils gmock)
- # clang-3.6 warns about a number of issues that are not reported by more modern compilers
- # and we know they are not real issues. So we only check that it can compile without error
- # but ignore all warnings.
- if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^3\.6")
- target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-w>)
+ if(GMX_CLANG_TIDY)
+ set_target_properties(${NAME} PROPERTIES CXX_CLANG_TIDY
+ "${CLANG_TIDY_EXE};-warnings-as-errors=*;-header-filter=.*")
+ endif()
+ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
+ target_compile_options(${NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS} -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-as-null-pointer-constant -Wno-missing-variable-declarations>)
endif()
endif()
endfunction ()
+# This function creates a GoogleTest test executable for a module. It
+# hides all the complexity of how to treat different source files
+# under different configuration conditions. It should be extended
+# if we ever support another GPU compilation approach.
+#
+# It can be called with extra options and arguments:
+# MPI
+# To trigger the ctest runner to run this test with multiple ranks
+# HARDWARE_DETECTION
+# To trigger the test executable setup code to run hardware detection
+# CPP_SOURCE_FILES file1.cpp file2.cpp ...
+# All the normal C++ .cpp source files
+# GPU_CPP_SOURCE_FILES file1.cpp file2.cpp ...
+# All the C++ .cpp source files that are always needed, but must be
+# compiled in the way that suits GMX_GPU.
+# CUDA_CU_SOURCE_FILES file1.cu file2.cu ...
+# All the normal CUDA .cu source files
+# CUDA_CPP_SOURCE_FILES file1.cpp file2.cpp ...
+# All the other .cpp source files to be compiled as CUDA
+# OPENCL_CPP_SOURCE_FILES file1.cpp file2.cpp ...
+# All the other C++ .cpp source files needed only with OpenCL
+# NON_GPU_CPP_SOURCE_FILES file1.cpp file2.cpp ...
+# All the other C++ .cpp source files needed only with neither OpenCL nor CUDA
function (gmx_add_gtest_executable EXENAME)
if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
set(_options MPI HARDWARE_DETECTION)
- cmake_parse_arguments(ARG "${_options}" "" "" ${ARGN})
- set(_source_files ${ARG_UNPARSED_ARGUMENTS})
+ set(_multi_value_keywords
+ CPP_SOURCE_FILES
+ CUDA_CU_SOURCE_FILES
+ GPU_CPP_SOURCE_FILES
+ CUDA_CPP_SOURCE_FILES
+ OPENCL_CPP_SOURCE_FILES
+ NON_GPU_CPP_SOURCE_FILES
+ )
+ cmake_parse_arguments(ARG "${_options}" "" "${_multi_value_keywords}" ${ARGN})
file(RELATIVE_PATH _input_files_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set(_temporary_files_path "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary")
TEST_USES_HARDWARE_DETECTION=true)
endif()
- add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
- ${_source_files} ${TESTUTILS_DIR}/unittest_main.cpp)
+ if (GMX_USE_CUDA AND NOT GMX_CLANG_CUDA)
+ # Work around FindCUDA that prevents using target_link_libraries()
+ # with keywords otherwise...
+ set(CUDA_LIBRARIES PRIVATE ${CUDA_LIBRARIES})
+ cuda_add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
+ ${ARG_CPP_SOURCE_FILES}
+ ${ARG_CUDA_CU_SOURCE_FILES}
+ ${ARG_CUDA_CPP_SOURCE_FILES}
+ ${ARG_GPU_CPP_SOURCE_FILES}
+ ${TESTUTILS_DIR}/unittest_main.cpp)
+ else()
+ add_executable(${EXENAME} ${UNITTEST_TARGET_OPTIONS}
+ ${ARG_CPP_SOURCE_FILES}
+ ${TESTUTILS_DIR}/unittest_main.cpp)
+ endif()
+
+ if (GMX_USE_CUDA)
+ if (GMX_CLANG_CUDA)
+ target_sources(${EXENAME} PRIVATE
+ ${ARG_CUDA_CU_SOURCE_FILES}
+ ${ARG_CUDA_CPP_SOURCE_FILES}
+ ${ARG_GPU_CPP_SOURCE_FILES})
+ set_source_files_properties(${ARG_CUDA_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+ gmx_compile_cuda_file_with_clang(${ARG_CUDA_CU_SOURCE_FILES})
+ if(ARG_CUDA_CPP_SOURCE_FILES OR ARG_CUDA_CU_SOURCE_FILES OR ARG_GPU_CPP_SOURCE_FILES)
+ target_link_libraries(${EXENAME} PRIVATE ${GMX_EXTRA_LIBRARIES})
+ endif()
+ endif()
+ elseif (GMX_USE_OPENCL)
+ target_sources(${EXENAME} PRIVATE ${ARG_OPENCL_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES})
+ if(ARG_OPENCL_CPP_SOURCE_FILES OR ARG_GPU_CPP_SOURCE_FILES)
+ target_link_libraries(${EXENAME} PRIVATE ${OpenCL_LIBRARIES})
+ endif()
+ else()
+ target_sources(${EXENAME} PRIVATE ${ARG_NON_GPU_CPP_SOURCE_FILES} ${ARG_GPU_CPP_SOURCE_FILES})
+ endif()
+
gmx_target_compile_options(${EXENAME})
target_compile_definitions(${EXENAME} PRIVATE HAVE_CONFIG_H ${EXTRA_COMPILE_DEFINITIONS})
target_include_directories(${EXENAME} SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
set_target_properties(${EXENAME} PROPERTIES CXX_CLANG_TIDY
"${CLANG_TIDY_EXE};-warnings-as-errors=*;-header-filter=.*")
endif()
- if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^6\.0")
+ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7")
target_compile_options(${EXENAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Weverything ${IGNORED_CLANG_ALL_WARNINGS} -Wno-gnu-zero-variadic-macro-arguments -Wno-zero-as-null-pointer-constant -Wno-missing-variable-declarations>)
endif()
# clang-3.6 warns about a number of issues that are not reported by more modern compilers
# INTEGRATION_TEST requires the use of the IntegrationTest label in CTest
# SLOW_TEST requires the use of the SlowTest label in CTest, and
# increase the length of the ctest timeout.
+# IGNORE_LEAKS Skip some memory safety checks.
#
# TODO When a test case needs it, generalize the MPI_RANKS mechanism so
# that ctest can run the test binary over a range of numbers of MPI
# ranks.
function (gmx_register_gtest_test NAME EXENAME)
if (GMX_BUILD_UNITTESTS AND BUILD_TESTING)
- set(_options INTEGRATION_TEST SLOW_TEST)
+ set(_options INTEGRATION_TEST SLOW_TEST IGNORE_LEAKS)
set(_one_value_args MPI_RANKS OPENMP_THREADS)
cmake_parse_arguments(ARG "${_options}" "${_one_value_args}" "" ${ARGN})
set(_xml_path ${CMAKE_BINARY_DIR}/Testing/Temporary/${NAME}.xml)
else()
set(_timeout 120)
endif()
- gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
elseif (ARG_SLOW_TEST)
list(APPEND _labels SlowTest)
set(_timeout 480)
- gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
else()
list(APPEND _labels UnitTest)
gmx_get_test_prefix_cmd(_prefix_cmd)
endif()
+ if (ARG_IGNORE_LEAKS)
+ gmx_get_test_prefix_cmd(_prefix_cmd IGNORE_LEAKS)
+ endif ()
set(_cmd ${_prefix_cmd} $<TARGET_FILE:${EXENAME}>)
if (ARG_OPENMP_THREADS)
if (GMX_OPENMP)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*/
TestReferenceDataImplPointer g_referenceData;
//! Global reference data mode set with setReferenceDataMode().
-ReferenceDataMode g_referenceDataMode = erefdataCompare;
+ReferenceDataMode g_referenceDataMode = ReferenceDataMode::Compare;
//! Returns the global reference data mode.
ReferenceDataMode getReferenceDataMode()
void initReferenceData(IOptionsContainer* options)
{
- // Needs to correspond to the enum order in refdata.h.
- const char* const refDataEnum[] = { "check", "create", "update-changed", "update-all" };
+ static const gmx::EnumerationArray<ReferenceDataMode, const char*> s_refDataNames = {
+ { "check", "create", "update-changed", "update-all" }
+ };
options->addOption(EnumOption<ReferenceDataMode>("ref-data")
- .enumValue(refDataEnum)
+ .enumValue(s_refDataNames)
.store(&g_referenceDataMode)
.description("Operation mode for tests that use reference data"));
::testing::UnitTest::GetInstance()->listeners().Append(new ReferenceDataTestEventListener);
switch (mode)
{
- case erefdataCompare:
+ case ReferenceDataMode::Compare:
if (File::exists(fullFilename_, File::throwOnError))
{
compareRootEntry_ = readReferenceDataFile(fullFilename_);
}
break;
- case erefdataCreateMissing:
+ case ReferenceDataMode::CreateMissing:
if (File::exists(fullFilename_, File::throwOnError))
{
compareRootEntry_ = readReferenceDataFile(fullFilename_);
outputRootEntry_ = ReferenceDataEntry::createRoot();
}
break;
- case erefdataUpdateChanged:
+ case ReferenceDataMode::UpdateChanged:
if (File::exists(fullFilename_, File::throwOnError))
{
compareRootEntry_ = readReferenceDataFile(fullFilename_);
outputRootEntry_ = ReferenceDataEntry::createRoot();
updateMismatchingEntries_ = true;
break;
- case erefdataUpdateAll:
+ case ReferenceDataMode::UpdateAll:
compareRootEntry_ = ReferenceDataEntry::createRoot();
outputRootEntry_ = ReferenceDataEntry::createRoot();
break;
+ case ReferenceDataMode::Count: GMX_THROW(InternalError("Invalid reference data mode"));
}
}
std::string appendPath(const char* id) const;
//! Creates an entry with given parameters and fills it with \p checker.
- ReferenceDataEntry::EntryPointer createEntry(const char* type,
- const char* id,
- const IReferenceDataEntryChecker& checker) const
+ static ReferenceDataEntry::EntryPointer createEntry(const char* type,
+ const char* id,
+ const IReferenceDataEntryChecker& checker)
{
ReferenceDataEntry::EntryPointer entry(new ReferenceDataEntry(type, id));
checker.fillEntry(entry.get());
return entry;
}
//! Checks an entry for correct type and using \p checker.
- ::testing::AssertionResult checkEntry(const ReferenceDataEntry& entry,
- const std::string& fullId,
- const char* type,
- const IReferenceDataEntryChecker& checker) const
+ static ::testing::AssertionResult checkEntry(const ReferenceDataEntry& entry,
+ const std::string& fullId,
+ const char* type,
+ const IReferenceDataEntryChecker& checker)
{
if (entry.type() != type)
{
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2011-2018, The GROMACS development team.
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* \ingroup module_testutils
*/
-enum ReferenceDataMode
+enum class ReferenceDataMode : int
{
/*! \brief
* Compare to existing reference data.
* If reference data does not exist, or if the test results differ from
* those in the reference data, the test fails.
*/
- erefdataCompare,
+ Compare,
/*! \brief
* Create missing reference data.
*
* If reference data does not exist for a test, that test behaves as if
- * ::erefdataUpdateAll had been specified. Tests for which reference data
- * exists, behave like with ::erefdataCompare.
+ * ReferenceDataMode::UpdateAll had been specified. Tests for which reference data
+ * exists, behave like with ReferenceDataMode::Compare.
*/
- erefdataCreateMissing,
+ CreateMissing,
/*! \brief
* Update reference data that does not pass comparison.
*
* Tests utilizing reference data should always pass in this mode unless
* there is an I/O error.
*/
- erefdataUpdateChanged,
+ UpdateChanged,
/*! \brief
* Update reference data, overwriting old data.
*
* Tests utilizing reference data should always pass in this mode unless
* there is an I/O error.
*/
- erefdataUpdateAll
+ UpdateAll,
+ //! Marks the end of the enum
+ Count
};
/*! \libinternal \brief
* Initializes reference data handling.
*
* Adds command-line options to \p options to set the reference data mode.
- * By default, ::erefdataCompare is used, but ``--ref-data create`` or
+ * By default, ReferenceDataMode::Compare is used, but ``--ref-data create`` or
* ``--ref-data update`` can be used to change it.
*
* This function is automatically called by initTestUtils().
* \code
int functionToTest(int param);
+ namespace gmx
+ {
+ namespace test
+ {
TEST(MyTest, SimpleTest)
{
- gmx::test::TestReferenceData data;
+ TestReferenceData data;
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(functionToTest(3), "ValueWith3");
checker.checkInteger(functionToTest(5), "ValueWith5");
- gmx::test::TestReferenceChecker compound(
+ TestReferenceChecker compound(
checker.checkCompound("CustomCompound", "Item"));
compound.checkInteger(function2ToTest(3), "ValueWith3");
compound.checkInteger(function2ToTest(5), "ValueWith5");
checker.checkInteger(functionToTest(4), "ValueWith4");
}
+ } // namespace test
+ } // namespace gmx
* \endcode
*
* If rootChecker() is never called, no comparison is done (i.e., missing
--- /dev/null
+Two simple dipoles
+ 4
+ 1DIP C 1 1.000 -0.140 1.000 0.0000 0.0000 0.0000
+ 1DIP C 2 1.000 0.140 1.200 0.0000 0.0000 0.0000
+ 2DIP C 3 3.900 2.000 3.000 0.0000 0.0000 0.0000
+ 2DIP C 4 4.100 2.000 3.200 0.0000 0.0000 0.0000
+ 4.00000 4.00000 4.00000
--- /dev/null
+[ System ]
+ 1 2 3 4
--- /dev/null
+; Simple dipoles
+
+[ defaults ]
+; nbfunc comb-rule
+ 1 1
+
+[ atomtypes ]
+; name at.num mass charge ptype sigma epsilon
+ C 6 12.01 0.0 A 0.3 1.0
+
+[ molecule_type ]
+Dipole 1
+
+[ atoms ]
+; nr type resnr residue atom cgnr charge
+ 1 C 1 DIP C 1 -1
+ 2 C 1 DIP C 2 1
+
+[ bonds ]
+1 2 1 0.28 10000
+
+[ system ]
+; Name
+Dipoles
+
+[ molecules ]
+; Compound #mols
+Dipole 2
; original reference: [M. W. Mahoney and W. L. Jorgensen, J. Chem. Phys. 112 , 2000]
;
; Note that there are various issues with tip5p and the different forcefields.
-; Discussion is here: http://redmine.gromacs.org/issues/1348
+; Discussion is here: https://gitlab.com/gromacs/gromacs/-/issues/1348
[ moleculetype ]
; molname nrexcl
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#ifndef GMX_TESTUTILS_TESTASSERTS_H
#define GMX_TESTUTILS_TESTASSERTS_H
+#include "config.h"
+
#include <string>
#include <gtest/gtest.h>
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2017 by the GROMACS development team.
+ * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2018 by the GROMACS development team.
+ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2011,2012,2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2011,2012,2014,2015,2016,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
# the research papers on the package. Check out http://www.gromacs.org.
gmx_add_unit_test(TestUtilsUnitTests testutils-test
- interactivetest.cpp
- refdata_tests.cpp
- testasserts_tests.cpp
- xvgtest_tests.cpp)
+ CPP_SOURCE_FILES
+ interactivetest.cpp
+ refdata_tests.cpp
+ testasserts_tests.cpp
+ xvgtest_tests.cpp
+ )
gmx_add_mpi_unit_test(TestUtilsMpiUnitTests testutils-mpi-test 2
- mpitest.cpp)
+ CPP_SOURCE_FILES
+ mpitest.cpp
+ )
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/refdata.h"
+namespace gmx
+{
+namespace test
+{
namespace
{
class InteractiveSession
{
public:
- explicit InteractiveSession(gmx::test::ReferenceDataMode mode) :
+ explicit InteractiveSession(ReferenceDataMode mode) :
data_(mode),
helper_(data_.rootChecker()),
nextInputLine_(0)
// The latter is the output string.
typedef std::pair<EventType, const char*> Event;
- gmx::test::TestReferenceData data_;
- gmx::test::InteractiveTestHelper helper_;
- std::vector<const char*> inputLines_;
- size_t nextInputLine_;
- std::vector<Event> events_;
+ TestReferenceData data_;
+ InteractiveTestHelper helper_;
+ std::vector<const char*> inputLines_;
+ size_t nextInputLine_;
+ std::vector<Event> events_;
};
TEST(InteractiveTestHelperTest, ChecksSimpleSession)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n");
session.addOutput("> ");
session.addInput("input");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n");
session.addOutput("> ");
session.addInput("input");
TEST(InteractiveTestHelperTest, ChecksSessionWithoutLastNewline)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n");
session.addOutput("> ");
session.addInput("input");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n");
session.addOutput("> ");
session.addInput("input");
TEST(InteractiveTestHelperTest, ChecksSessionWithMissingOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n> ");
session.addInput("input");
session.addInput("input2");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addInput("input2");
TEST(InteractiveTestHelperTest, ChecksSessionWithEquivalentOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n");
session.addOutput("> ");
session.addInput("input");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Second line\n");
TEST(InteractiveTestHelperTest, DetectsIncorrectOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Second line\n> ");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Incorrect line\n> ");
TEST(InteractiveTestHelperTest, DetectsMissingOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Second line\n> ");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addInput("input2");
TEST(InteractiveTestHelperTest, DetectsMissingFinalOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Second line\n> ");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Second line\n> ");
TEST(InteractiveTestHelperTest, DetectsExtraOutput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addOutput("First line\n> ");
session.addInput("input");
session.addInput("input2");
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addOutput("First line\n> ");
session.addInput("input");
session.addOutput("Extra output\n> ");
TEST(InteractiveTestHelperTest, DetectsMissingInput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addInput("input");
session.addInput("input2");
session.addReadInput();
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addInputLine("input");
session.addInputLine("input2");
session.addReadInput();
TEST(InteractiveTestHelperTest, DetectsExtraInput)
{
{
- InteractiveSession session(gmx::test::erefdataUpdateAll);
+ InteractiveSession session(ReferenceDataMode::UpdateAll);
session.addInput("input");
session.addInput("input2");
session.addReadInput();
session.run();
}
{
- InteractiveSession session(gmx::test::erefdataCompare);
+ InteractiveSession session(ReferenceDataMode::Compare);
session.addInputLine("input");
session.addInputLine("input2");
session.addReadInput();
}
} // namespace
+} // namespace test
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2011,2012,2013,2014,2015,2016,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015 by the GROMACS development team.
+ * Copyright (c) 2016,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/testasserts.h"
#include "testutils/testexceptions.h"
+
+namespace gmx
+{
+namespace test
+{
namespace
{
-using gmx::test::TestReferenceChecker;
-using gmx::test::TestReferenceData;
-
TEST(ReferenceDataTest, HandlesSimpleData)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkBoolean(true, "bool");
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkBoolean(true, "bool");
checker.checkInteger(1, "int");
const double doubleValue = 4.0 / 3.0;
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkDouble(doubleValue, "double");
checker.checkReal(doubleValue, "real");
checker.checkFloat(floatValue, "float");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkDouble(doubleValue, "double");
checker.checkReal(floatValue, "real");
TEST(ReferenceDataTest, HandlesPresenceChecks)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
EXPECT_TRUE(checker.checkPresent(true, "present"));
checker.checkInteger(1, "present");
EXPECT_FALSE(checker.checkPresent(false, "absent"));
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
// Assigned to avoid warnings about potentially uninitialized value.
bool bRet = true;
TEST(ReferenceDataTest, HandlesStringBlockData)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkTextBlock("Line1\nLine2\n", "block");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkTextBlock("Line1\nLine2\n", "block");
checker.checkString("Line1\nLine2\n", "block");
double vecd[3] = { -2.3, 1.43, 2.5 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkVector(veci, "ivec");
checker.checkVector(vecf, "fvec");
checker.checkVector(vecd, "dvec");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkVector(veci, "ivec");
checker.checkVector(vecf, "fvec");
const int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkSequenceArray(5, seq, "seq");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkSequenceArray(5, seq, "seq");
}
const dvec seq[] = { { -3, 4, 5 }, { -2.3, 5, 0 } };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkSequence(std::begin(seq), std::end(seq), "seq", checkCustomVector);
}
int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkDouble(0.5, "real");
checker.checkSequenceArray(5, seq, "seq");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkInteger(2, "int"), "");
EXPECT_NONFATAL_FAILURE(checker.checkDouble(0.3, "real"), "");
TEST(ReferenceDataTest, HandlesIncorrectDataType)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkCompound("Compound", "compound");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkString("1", "int"), "");
EXPECT_NONFATAL_FAILURE(checker.checkCompound("OtherCompound", "compound"), "");
const int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkSequenceArray(5, seq, "seq");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkInteger(1, "missing"), "");
EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "missing"), "");
const int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkSequenceArray(5, seq, "seq");
checker.checkUnusedEntries();
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
EXPECT_NONFATAL_FAILURE(checker.checkUnusedEntries(), "");
const int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkSequenceArray(5, seq, "seq");
checker.checkUnusedEntries();
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(3, seq, "seq"), "");
TEST(ReferenceDataTest, HandlesUncheckedDataInCompound)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
compound.checkInteger(1, "int1");
checker.checkUnusedEntries();
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
TestReferenceChecker compound(checker.checkCompound("Compound", "Compound"));
compound.checkInteger(1, "int1");
{
using gmx::Any;
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkAny(Any::create<bool>(true), "bool");
checker.checkAny(Any::create<int>(1), "int");
checker.checkAny(Any::create<std::string>("foo"), "str");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkAny(Any::create<bool>(true), "bool");
checker.checkAny(Any::create<int>(1), "int");
{
gmx::KeyValueTreeObject tree = buildKeyValueTree(true);
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkKeyValueTreeObject(tree, "tree");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkKeyValueTreeObject(tree, "tree");
}
TEST(ReferenceDataTest, HandlesKeyValueTreeExtraKey)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree"),
"");
TEST(ReferenceDataTest, HandlesKeyValueTreeMissingKey)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkKeyValueTreeObject(buildKeyValueTree(true), "tree");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkKeyValueTreeObject(buildKeyValueTree(false), "tree"),
"");
{
using gmx::Any;
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkAny(Any::create<bool>(true), "bool");
checker.checkAny(Any::create<int>(1), "int");
checker.checkAny(Any::create<std::string>("foo"), "str");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(false), "bool"), "");
EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(2), "int"), "");
{
using gmx::Any;
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkAny(Any::create<bool>(true), "bool");
checker.checkAny(Any::create<int>(1), "int");
checker.checkAny(Any::create<double>(3.5), "real");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<int>(1), "bool"), "");
EXPECT_NONFATAL_FAILURE(checker.checkAny(Any::create<bool>(true), "int"), "");
EXPECT_NONFATAL_FAILURE(
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkDouble(0.5, "real");
TEST(ReferenceDataTest, HandlesSpecialCharactersInStrings)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
// Note that '\r' is not handled correctly in string or
// stringblock (see the TODO in createElementContents), so
checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("\"<'>\n&\\/;", "string");
checker.checkTextBlock("\"<'>\n&\\/;", "stringblock");
const char* strings[] = { " test", "test ", " test ", "the test",
"\ntest", "\n\ntest", "test\n", "test\n\n" };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
for (const auto& s : strings)
{
}
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
for (const auto& s : strings)
{
TEST(ReferenceDataTest, HandlesEmptyStrings)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("", "Empty");
// GROMACS cannot use an empty line in a reference data String
// until https://github.com/leethomason/tinyxml2/issues/432 is
// resolved.
- EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
+ EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), TestException);
checker.checkTextBlock("", "EmptyBlock");
checker.checkTextBlock("\n", "EmptyLineBlock");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("", "Empty");
- EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), gmx::test::TestException);
+ EXPECT_THROW_GMX(checker.checkString("\n", "EmptyLine"), TestException);
checker.checkTextBlock("", "EmptyBlock");
checker.checkTextBlock("\n", "EmptyLineBlock");
}
don't actually depend on this behaviour, but it might be nice
to have / know about.) */
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkTextBlock(" ]]> ", "stringblock");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkTextBlock(" ]]> ", "stringblock");
}
int seq[5] = { -1, 3, 5, 2, 4 };
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkSequenceArray(5, seq, "seq");
checker.checkSequenceArray(5, seq, "seq2");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
seq[0] = 2;
EXPECT_NONFATAL_FAILURE(checker.checkSequenceArray(5, seq, "seq"), "seq/[0]");
TEST(ReferenceDataTest, HandlesMultipleChecksAgainstSameData)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("Test", "string");
EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
EXPECT_NONFATAL_FAILURE(checker.checkTextBlock("TestString2", "stringblock"), "");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("Test", "string");
EXPECT_NONFATAL_FAILURE(checker.checkString("Test2", "string"), "");
TEST(ReferenceDataTest, HandlesMultipleNullIds)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("Test", nullptr);
checker.checkString("Test2", nullptr);
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("Test", nullptr);
checker.checkString("Test2", nullptr);
TEST(ReferenceDataTest, HandlesMultipleComparisonsAgainstNullIds)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int1");
checker.checkString("Test", nullptr);
checker.checkString("Test2", nullptr);
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int1");
checker.checkString("Test", nullptr);
TEST(ReferenceDataTest, HandlesReadingValues)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkUChar('A', "char");
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
EXPECT_EQ('A', checker.readUChar("char"));
EXPECT_EQ(1, checker.readInteger("int"));
TEST(ReferenceDataTest, HandlesUpdateChangedWithoutChanges)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
compound.checkInteger(2, "int");
}
{
- TestReferenceData data(gmx::test::erefdataUpdateChanged);
+ TestReferenceData data(ReferenceDataMode::UpdateChanged);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
compound.checkInteger(2, "int");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
TEST(ReferenceDataTest, HandlesUpdateChangedWithValueChanges)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataUpdateChanged);
+ TestReferenceData data(ReferenceDataMode::UpdateChanged);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(2, "int");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(2, "int");
checker.checkString("Test", "string");
TEST(ReferenceDataTest, HandlesUpdateChangedWithTypeChanges)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "foo");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataUpdateChanged);
+ TestReferenceData data(ReferenceDataMode::UpdateChanged);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("foo", "foo");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkString("foo", "foo");
checker.checkString("Test", "string");
TEST(ReferenceDataTest, HandlesUpdateChangedWithCompoundChanges)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "1");
TestReferenceChecker compound(checker.checkCompound("Compound", "2"));
compound.checkInteger(2, "int");
}
{
- TestReferenceData data(gmx::test::erefdataUpdateChanged);
+ TestReferenceData data(ReferenceDataMode::UpdateChanged);
TestReferenceChecker checker(data.rootChecker());
TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
compound.checkInteger(2, "int");
checker.checkString("Test", "2");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
TestReferenceChecker compound(checker.checkCompound("Compound", "1"));
compound.checkInteger(2, "int");
TEST(ReferenceDataTest, HandlesUpdateChangedWithRemovedEntries)
{
{
- TestReferenceData data(gmx::test::erefdataUpdateAll);
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(1, "int");
checker.checkString("Test", "string");
}
{
- TestReferenceData data(gmx::test::erefdataUpdateChanged);
+ TestReferenceData data(ReferenceDataMode::UpdateChanged);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(2, "int");
}
{
- TestReferenceData data(gmx::test::erefdataCompare);
+ TestReferenceData data(ReferenceDataMode::Compare);
TestReferenceChecker checker(data.rootChecker());
checker.checkInteger(2, "int");
}
}
} // namespace
+} // namespace test
+} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "testutils/refdata.h"
#include "testutils/testasserts.h"
+namespace gmx
+{
+namespace test
+{
namespace
{
-using gmx::test::checkXvgFile;
-using gmx::test::XvgMatchSettings;
-
//! Input testing data - an inline xvg file.
const char* const input[] = { "0 2905.86 -410.199", "0.2 6656.67 -430.437",
"0.4 5262.44 -409.399", "0.6 5994.69 -405.763",
{
{
// Create new data
- gmx::test::TestReferenceData data(gmx::test::erefdataUpdateAll);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
+ TestReferenceChecker checker(data.rootChecker());
// Convert char array to a stream and add it to the checker
gmx::StringInputStream sis(input);
checkXvgFile(&sis, &checker, XvgMatchSettings());
}
{
// Now read it back
- gmx::test::TestReferenceData data(gmx::test::erefdataCompare);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceData data(ReferenceDataMode::Compare);
+ TestReferenceChecker checker(data.rootChecker());
// Convert char array to a stream and add it to the checker
gmx::StringInputStream sis(input);
checkXvgFile(&sis, &checker, XvgMatchSettings());
{
{
// Create new data
- gmx::test::TestReferenceData data(gmx::test::erefdataUpdateAll);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
+ TestReferenceChecker checker(data.rootChecker());
// Convert char array to a stream and add it to the checker
gmx::StringInputStream sis(input);
checkXvgFile(&sis, &checker, XvgMatchSettings());
const char* const input[] = { "0 2905.86 -410.199", "0.2 6656.67 -430.437",
"0.4 5262.44 -409.399" };
// Now check with missing data
- gmx::test::TestReferenceData data(gmx::test::erefdataCompare);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
- gmx::StringInputStream sis(input);
+ TestReferenceData data(ReferenceDataMode::Compare);
+ TestReferenceChecker checker(data.rootChecker());
+ gmx::StringInputStream sis(input);
EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()),
"not used in test");
}
{
{
// Create new data
- gmx::test::TestReferenceData data(gmx::test::erefdataUpdateAll);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
+ TestReferenceChecker checker(data.rootChecker());
// Convert char array to a stream and add it to the checker
gmx::StringInputStream sis(input);
checkXvgFile(&sis, &checker, XvgMatchSettings());
"0.8 5941.37 -408.337", "1 5869.87 -411.124",
"1.2 5889.87 -413.124" };
// Now check with missing data
- gmx::test::TestReferenceData data(gmx::test::erefdataCompare);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
- gmx::StringInputStream sis(input);
+ TestReferenceData data(ReferenceDataMode::Compare);
+ TestReferenceChecker checker(data.rootChecker());
+ gmx::StringInputStream sis(input);
EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()), "Row6");
}
}
{
{
// Create new data
- gmx::test::TestReferenceData data(gmx::test::erefdataUpdateAll);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
+ TestReferenceData data(ReferenceDataMode::UpdateAll);
+ TestReferenceChecker checker(data.rootChecker());
// Convert char array to a stream and add it to the checker
gmx::StringInputStream sis(input);
checkXvgFile(&sis, &checker, XvgMatchSettings());
"0.4 5262.44 -409.399", "0.6 5994.69 -405.763",
"0.8 5941.37 -408.337", "1 5869.87 -421.124" };
// Now check with incorrect data
- gmx::test::TestReferenceData data(gmx::test::erefdataCompare);
- gmx::test::TestReferenceChecker checker(data.rootChecker());
- gmx::StringInputStream sis(input);
+ TestReferenceData data(ReferenceDataMode::Compare);
+ TestReferenceChecker checker(data.rootChecker());
+ gmx::StringInputStream sis(input);
EXPECT_NONFATAL_FAILURE(checkXvgFile(&sis, &checker, XvgMatchSettings()), "-411");
}
}
} // namespace
+} // namespace test
+} // namespace gmx
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+# Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
if(REGRESSIONTEST_DOWNLOAD)
if (NOT SOURCE_IS_SOURCE_DISTRIBUTION)
- set(REGRESSIONTEST_URL http://gerrit.gromacs.org/snapshot/${REGRESSIONTEST_BRANCH})
+ set(REGRESSIONTEST_URL https://gitlab.com/gromacs/gromacs-regressiontests/-/archive/${REGRESSIONTEST_BRANCH}/gromacs-regressiontests-${REGRESSIONTEST_BRANCH}.tar.gz)
# REGRESSIONTEST_PATH for dev trees is set later based on the dirname found in the tar
else()
- set(REGRESSIONTEST_URL http://gerrit.gromacs.org/download/regressiontests-${REGRESSIONTEST_VERSION}.tar.gz)
+ set(REGRESSIONTEST_URL http://ftp.gromacs.org/regressiontests/regressiontests-${REGRESSIONTEST_VERSION}.tar.gz)
set(REGRESSIONTEST_PATH
"${CMAKE_CURRENT_BINARY_DIR}/regressiontests-${REGRESSIONTEST_VERSION}"
CACHE PATH "Path to auto-downloaded regressiontests" FORCE)
# End copied from regression tests.
#
- if (NOT PYTHONINTERP_FOUND)
+ if (NOT Python3_Interpreter_FOUND)
message(FATAL_ERROR
"Python not found. Physical validation requires python. \
- Install python, set PYTHON_EXECUTABLE to a valid python location, \
+ Install python, set Python3_ROOT_DIR or PYTHON_EXECUTABLE to a valid location, \
or set GMX_PHYSICAL_VALIDATION=OFF to disable the physical validation tests.")
endif()
#
probably neither especially elegant nor especially safe. Use of this
module in any remotely critical application is strongly discouraged.
"""
+import errno
import os
import sys
import subprocess
@includepath.setter
def includepath(self, path):
- try: # py2/3 compatibility
- basestring
- except NameError:
- basestring = str
- if isinstance(path, basestring):
+ if isinstance(path, str):
path = [path]
self._includepath = path
if exe is None:
exe = self._exe
try:
- devnull = open(os.devnull)
- exe_out = subprocess.check_output([exe, '--version'], stderr=devnull)
+ exe_out = subprocess.run([exe, '--version'],
+ stdout=subprocess.PIPE,
+ universal_newlines=True).stdout
except OSError as e:
- if e.errno == os.errno.ENOENT:
+ if hasattr(errno, 'ENOENT') and e.errno == errno.ENOENT:
# file not found error.
if not quiet:
print('ERROR: gmx executable not found')
else:
raise e
# check that output is as expected
- return re.search(br':-\) GROMACS - gmx.* \(-:', exe_out)
+ return re.search(r':-\) GROMACS - gmx.* \(-:', exe_out)
def _run(self, cmd, args, cwd=None, stdin=None, stdout=None, stderr=None, mpicmd=None):
if self.exe is None: