Merge commit d30f2cb6 from release-2020 into master
authorPaul Bauer <paul.bauer.q@gmail.com>
Tue, 7 Jan 2020 10:01:22 +0000 (11:01 +0100)
committerPaul Bauer <paul.bauer.q@gmail.com>
Tue, 7 Jan 2020 10:16:32 +0000 (11:16 +0100)
Merging the release-2020 branch in stages to allow update to TPR format
to be cherry-picked in.

Change-Id: I36c0861d0cb6f17a3f4ff739fa868867844f2944

199 files changed:
CMakeLists.txt
admin/builds/post-submit-matrix.txt
admin/ci-templates/.regressiontest-template.yml
admin/clang-format.sh
admin/copyright.py
cmake/TestARMv7.cpp [deleted file]
cmake/TestARMv7CycleCounters.cpp [deleted file]
cmake/gmxCPackUtilities.cmake
cmake/gmxDetectTargetArchitecture.cmake
cmake/gmxManageCycleCounters.cmake [deleted file]
cmake/gmxVersionInfo.cmake
docs/CMakeLists.txt
docs/conf.py
docs/dev-manual/build-system.rst
docs/dev-manual/jenkins.rst
docs/dev-manual/overview.rst
docs/dev-manual/style.rst
docs/dev-manual/tools.rst
docs/index.rst
docs/install-guide/index.rst
docs/reference-manual/file-formats.rst
docs/reference-manual/index.rst
docs/reference-manual/preface.rst
docs/release-notes/2021/major/bugs-fixed.rst [new file with mode: 0644]
docs/release-notes/2021/major/deprecated-functionality.rst [new file with mode: 0644]
docs/release-notes/2021/major/features.rst [new file with mode: 0644]
docs/release-notes/2021/major/highlights.rst [new file with mode: 0644]
docs/release-notes/2021/major/miscellaneous.rst [new file with mode: 0644]
docs/release-notes/2021/major/performance.rst [new file with mode: 0644]
docs/release-notes/2021/major/portability.rst [new file with mode: 0644]
docs/release-notes/2021/major/removed-functionality.rst [new file with mode: 0644]
docs/release-notes/2021/major/tools.rst [new file with mode: 0644]
docs/release-notes/index.rst
docs/user-guide/environment-variables.rst
docs/user-guide/faq.rst
docs/user-guide/force-fields.rst
docs/user-guide/index.rst
docs/user-guide/mdp-options.rst
docs/user-guide/mdrun-performance.rst
docs/user-guide/run-time-errors.rst
python_packaging/documentation/conf.py
python_packaging/requirements-test.txt
python_packaging/sample_restraint/tests/conftest.py
python_packaging/sample_restraint/tests/test_binding.py
python_packaging/scripts/run_flake8 [new file with mode: 0755]
python_packaging/src/gmxapi/_logging.py
python_packaging/src/gmxapi/commandline.py
python_packaging/src/gmxapi/datamodel.py
python_packaging/src/gmxapi/export_tprfile.cpp
python_packaging/src/gmxapi/operation.py
python_packaging/src/gmxapi/testsupport.py
python_packaging/src/gmxapi/version.py
python_packaging/src/setup.py
python_packaging/src/test/conftest.py
python_packaging/src/test/test_mdrun.py
python_packaging/test/conftest.py
src/CMakeLists.txt
src/api/CMakeLists.txt
src/api/cpp/CMakeLists.txt
src/config.h.cmakein
src/gromacs/applied_forces/densityfittingforceprovider.cpp
src/gromacs/domdec/box.cpp
src/gromacs/domdec/cellsizes.cpp
src/gromacs/domdec/distribute.cpp
src/gromacs/domdec/domdec.cpp
src/gromacs/domdec/domdec.h
src/gromacs/domdec/domdec_constraints.cpp
src/gromacs/domdec/domdec_internal.h
src/gromacs/domdec/domdec_specatomcomm.cpp
src/gromacs/domdec/domdec_struct.h
src/gromacs/domdec/domdec_topology.cpp
src/gromacs/domdec/dump.cpp
src/gromacs/domdec/partition.cpp
src/gromacs/domdec/redistribute.cpp
src/gromacs/domdec/utility.h
src/gromacs/ewald/pme_coordinate_receiver_gpu.h
src/gromacs/ewald/pme_coordinate_receiver_gpu_impl.cpp
src/gromacs/ewald/pme_coordinate_receiver_gpu_impl.cu
src/gromacs/ewald/pme_coordinate_receiver_gpu_impl.h
src/gromacs/ewald/pme_load_balancing.cpp
src/gromacs/ewald/pme_load_balancing.h
src/gromacs/ewald/pme_only.cpp
src/gromacs/ewald/tests/pmetestcommon.cpp
src/gromacs/fileio/pdbio.cpp
src/gromacs/fileio/tpxio.cpp
src/gromacs/gmxana/anadih.cpp
src/gromacs/gmxana/angle_correction.cpp
src/gromacs/gmxana/angle_correction.h
src/gromacs/gmxana/cmat.cpp
src/gromacs/gmxana/gmx_angle.cpp
src/gromacs/gmxlib/nonbonded/nb_free_energy.cpp
src/gromacs/gmxpreprocess/gpp_nextnb.cpp
src/gromacs/gmxpreprocess/gpp_nextnb.h
src/gromacs/gmxpreprocess/grompp.cpp
src/gromacs/gmxpreprocess/grompp_impl.h
src/gromacs/gmxpreprocess/readir.cpp
src/gromacs/gmxpreprocess/topio.cpp
src/gromacs/gmxpreprocess/toppush.cpp
src/gromacs/listed_forces/gpubonded_impl.cu
src/gromacs/listed_forces/listed_forces.cpp
src/gromacs/listed_forces/manage_threading.cpp
src/gromacs/mdlib/constr.cpp
src/gromacs/mdlib/constr.h
src/gromacs/mdlib/constraintrange.cpp
src/gromacs/mdlib/dispersioncorrection.cpp
src/gromacs/mdlib/energyoutput.cpp
src/gromacs/mdlib/energyoutput.h
src/gromacs/mdlib/force.cpp
src/gromacs/mdlib/forcerec.cpp
src/gromacs/mdlib/forcerec.h
src/gromacs/mdlib/leapfrog_cuda.cu
src/gromacs/mdlib/leapfrog_cuda.cuh
src/gromacs/mdlib/lincs.cpp
src/gromacs/mdlib/lincs.h
src/gromacs/mdlib/lincs_cuda.cu
src/gromacs/mdlib/lincs_cuda.cuh
src/gromacs/mdlib/mdoutf.cpp
src/gromacs/mdlib/nsgrid.cpp
src/gromacs/mdlib/perf_est.cpp
src/gromacs/mdlib/qm_gaussian.cpp
src/gromacs/mdlib/qm_gaussian.h
src/gromacs/mdlib/qm_orca.cpp
src/gromacs/mdlib/qm_orca.h
src/gromacs/mdlib/qmmm.cpp
src/gromacs/mdlib/qmmm.h
src/gromacs/mdlib/settle_cuda.cu
src/gromacs/mdlib/settle_cuda.cuh
src/gromacs/mdlib/sim_util.cpp
src/gromacs/mdlib/tests/constrtestrunners.cpp
src/gromacs/mdlib/tests/constrtestrunners.cu
src/gromacs/mdlib/tests/energyoutput.cpp
src/gromacs/mdlib/tests/settletestdata.cpp
src/gromacs/mdlib/tests/settletestrunners.cu
src/gromacs/mdlib/trajectory_writing.cpp
src/gromacs/mdlib/update_constrain_cuda_impl.cu
src/gromacs/mdlib/updategroups.cpp
src/gromacs/mdlib/vsite.cpp
src/gromacs/mdlib/wall.cpp
src/gromacs/mdrun/md.cpp
src/gromacs/mdrun/mimic.cpp
src/gromacs/mdrun/minimize.cpp
src/gromacs/mdrun/rerun.cpp
src/gromacs/mdrun/runner.cpp
src/gromacs/mdrun/tpi.cpp
src/gromacs/mdtypes/commrec.h
src/gromacs/mdtypes/forcerec.h
src/gromacs/mdtypes/state_propagator_data_gpu.h
src/gromacs/mdtypes/state_propagator_data_gpu_impl.cpp
src/gromacs/mdtypes/state_propagator_data_gpu_impl.h
src/gromacs/mdtypes/state_propagator_data_gpu_impl_gpu.cpp
src/gromacs/modularsimulator/computeglobalselement.cpp
src/gromacs/modularsimulator/energyelement.cpp
src/gromacs/modularsimulator/modularsimulator.cpp
src/gromacs/modularsimulator/modularsimulatorinterfaces.h
src/gromacs/modularsimulator/pmeloadbalancehelper.cpp
src/gromacs/modularsimulator/statepropagatordata.cpp
src/gromacs/modularsimulator/statepropagatordata.h
src/gromacs/nbnxm/atomdata.cpp
src/gromacs/nbnxm/atomdata.h
src/gromacs/nbnxm/benchmark/bench_setup.cpp
src/gromacs/nbnxm/benchmark/bench_system.cpp
src/gromacs/nbnxm/benchmark/bench_system.h
src/gromacs/nbnxm/cuda/nbnxm_buffer_ops_kernels.cuh
src/gromacs/nbnxm/cuda/nbnxm_cuda.cu
src/gromacs/nbnxm/nbnxm.h
src/gromacs/nbnxm/nbnxm_setup.cpp
src/gromacs/nbnxm/pairlist.cpp
src/gromacs/nbnxm/pairlistset.h
src/gromacs/nbnxm/pairlistsets.h
src/gromacs/pulling/pull.cpp
src/gromacs/pulling/pull.h
src/gromacs/selection/nbsearch.cpp
src/gromacs/selection/nbsearch.h
src/gromacs/selection/tests/nbsearch.cpp
src/gromacs/taskassignment/decidegpuusage.cpp
src/gromacs/taskassignment/decidegpuusage.h
src/gromacs/timing/cyclecounter.h
src/gromacs/timing/wallcycle.cpp
src/gromacs/timing/wallcycle.h
src/gromacs/tools/convert_tpr.cpp
src/gromacs/topology/block.cpp
src/gromacs/topology/block.h
src/gromacs/topology/exclusionblocks.cpp
src/gromacs/topology/exclusionblocks.h
src/gromacs/topology/idef.cpp
src/gromacs/topology/idef.h
src/gromacs/topology/mtop_util.cpp
src/gromacs/topology/tests/exclusionblocks.cpp
src/gromacs/topology/topology.cpp
src/gromacs/topology/topology.h
src/gromacs/topology/topsort.cpp
src/gromacs/trajectoryanalysis/modules/rdf.cpp
src/gromacs/utility/CMakeLists.txt
src/gromacs/utility/listoflists.h [new file with mode: 0644]
src/gromacs/utility/tests/CMakeLists.txt
src/gromacs/utility/tests/listoflists.cpp [new file with mode: 0644]
src/programs/mdrun/tests/CMakeLists.txt
src/programs/mdrun/tests/outputfiles.cpp
tests/CMakeLists.txt

index 1fae6e805c0b52890d1c3ae5cf70d5603a612928..5f3fc736c902352af0d0b94810f2e63d1f8fe046 100644 (file)
@@ -690,9 +690,6 @@ endif()
 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)
index afa2fda97c06f3075dde03834af7109eeabc051c..afb7ee946d2dddc5e7219351d387a0b84886eed7 100644 (file)
@@ -9,10 +9,6 @@
 # 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
index e3289afe8f38f833a7d705bb95ff017023d714a1..7acb6688a2b3ed4587866a1a15c2721e33b0259a 100644 (file)
@@ -15,9 +15,9 @@
   except:
     variables:
       - $GROMACS_RELEASE
-# Always clone the default version for this branch, release-2020 in this case
+# Always clone the default version for this branch, master in this case
   script:
-    - export REGTESTBRANCH=release-2020
+    - export REGTESTBRANCH=master
     - if [ ! -z $CI_MERGE_REQUEST_TARGET_BRANCH_NAME ] ; then
         if [[ ! -d regressiontests ]] ; then
           mkdir regressiontests ;
@@ -63,7 +63,7 @@
     - 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
index ae8f61dfbde939d1e6441f8c0f9bdfd3d190ed4e..e4ab728c0ee440dd51dcc0df853680f05024f5ba 100755 (executable)
@@ -98,7 +98,7 @@ then
     if [ -z "$CLANG_FORMAT" ]
     then
         echo "Please set the path to clang-format using the git hook"
-        echo "git config hooks.clang_formatpath /path/to/clang-format"
+        echo "git config hooks.clangformatpath /path/to/clang-format"
         echo "or by setting an environment variable, e.g."
         echo "CLANG_FORMAT=/path/to/clang-format"
         echo "See docs/dev-manual/code-formatting.rst for how to get clang-format."
index 8d57385a116f1c0e7e0bc64459d11dc08241762b..7b817430ef7f328b64bc163a5c747e1905dce0cb 100755 (executable)
@@ -2,7 +2,7 @@
 #
 # 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,2019,2020, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
diff --git a/cmake/TestARMv7.cpp b/cmake/TestARMv7.cpp
deleted file mode 100644 (file)
index 2b6a3ae..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-int main()
-{
-#ifdef __ARM_ARCH_7A__
-    return 0;
-#else
-#error This compiler is not targetting 32-bit ARMv7
-#endif
-}
diff --git a/cmake/TestARMv7CycleCounters.cpp b/cmake/TestARMv7CycleCounters.cpp
deleted file mode 100644 (file)
index 81b9251..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-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
-}
index 3a788950fa6bc0c79072980a4851e81be2c72b01..11e1bac0bb89353f66341e3f8c691005e5572935 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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,2019,2020, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
index 12cc0fa97094031f2e0ff0647cbaef3ff52e5355..8b44c7dcb07039b8b54be03ce6460e992c32b79a 100644 (file)
@@ -48,10 +48,6 @@ function(gmx_detect_target_architecture)
         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")
diff --git a/cmake/gmxManageCycleCounters.cmake b/cmake/gmxManageCycleCounters.cmake
deleted file mode 100644 (file)
index df3f0c7..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# 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()
-
index 6c7925b0e85bfe76849c3eabd6c505de44374f65..42f59adeab0737fe75f04e4aebe7bfbfb52148d0 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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,2019,2020, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
@@ -58,6 +58,7 @@
 #         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_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
 # as after the final release is out.
-set(GMX_VERSION_SUFFIX "-rc1")
+set(GMX_VERSION_SUFFIX "")
 
 # Conventionally with libtool, any ABI change must change the major
 # version number, the minor version number should change if it's just
@@ -212,7 +213,7 @@ set(GMX_VERSION_SUFFIX "-rc1")
 # 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)
 
@@ -254,7 +255,7 @@ if (NOT SOURCE_IS_SOURCE_DISTRIBUTION AND
 endif()
 
 set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
-set(REGRESSIONTEST_BRANCH "refs/heads/release-2020")
+set(REGRESSIONTEST_BRANCH "refs/heads/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
index 32636d3dd1e1aa1305379bd4adf267b86d2abc2f..99310f3417a84c977c67c63110ea08217d74de8c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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,2019,2020, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
@@ -361,6 +361,15 @@ if (SPHINX_FOUND)
         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/major/highlights.rst
         release-notes/2020/major/features.rst
         release-notes/2020/major/performance.rst
@@ -598,6 +607,10 @@ if (SPHINX_FOUND)
 
     # 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 "-D todo_include_todos=1")
+    endif()
     add_custom_target(webpage-sphinx
         DEPENDS sphinx-programs
         DEPENDS sphinx-input
@@ -610,6 +623,7 @@ if (SPHINX_FOUND)
             -q -b html
             -w sphinx-html.log
             -d "${SPHINX_CACHE_DIR}"
+            ${SPHINX_CONFIG_OVERRIDES}
             "${SPHINX_INPUT_DIR}"
             "${HTML_OUTPUT_DIR}"
         WORKING_DIRECTORY
index 929a34c0512087ddb528c3d35b455348b771ca86..1dd0bb1b2e8f87fa6c64bcbbabc9b42d7f0d37c6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index f7a3f0ab400ef653e9bc95913007e260046d4d58..a98c9e9f84298b72f2c7155d6200c3565e6981b7 100644 (file)
@@ -111,10 +111,14 @@ This section provides a (currently incomplete) list of cache variables that
 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
@@ -170,7 +174,7 @@ Variables affecting compilation/linking
    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
 
@@ -354,7 +358,7 @@ Variables affecting the ``all`` target
   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
   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 -DCMAKE_EXPORT_COMPILE_COMMANDS=on``.
   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=...``.
@@ -388,7 +392,7 @@ Variables affecting special targets
    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
@@ -442,7 +446,9 @@ Variables affecting special targets
 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.
 
index 09ac69d3833faaad63048ad2c89baed88fece952..8ff99a0923d536445ad46e3327055638bf0680e0 100644 (file)
@@ -15,7 +15,7 @@ Separate page documents how to interact with the Jenkins UI for these builds:
 :doc:`releng/jenkins-howto` has information on how to do common things with
 Jenkins builds.
 
-.. TODO: Add a link to a wiki page about general Jenkins documentation, once
+.. todo:: Add a link to a wiki page about general Jenkins documentation, once
    there is more of that.
 
 Pre-submit verification
index 4a63fd4cf0242953855e2fccf522e0167cc46086..e9bf4c8baa7d5a67cd370c51718ec9191ca3953a 100644 (file)
@@ -274,7 +274,7 @@ Doxygen documentation
   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.
index 6ef21feadb473f0511d2c432037eceab93a2ce3c..761a455524c3d5f00f19229d6f795f798426001c 100644 (file)
@@ -35,4 +35,4 @@ this page.
 :doc:`commitstyle`
   Guidelines for formatting git commits when sending in proposed fixes for code review.
 
-.. TODO: Add more guidelines
+.. todo:: Add more guidelines
index 9dce91439cabebf59f68bab07cbaf4eab6daedac..9ce35b7ce585133440be9ada39341a3b09b34076 100644 (file)
@@ -15,11 +15,15 @@ Several tools have their own individual pages and are listed below.
    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
@@ -58,7 +62,7 @@ Redmine
 Build system
 ------------
 
-.. TODO: details, ASAN, others?
+.. todo:: details, ASAN, others?
 
 CMake
   Main tool used in the build system.
index 65bd93cfbabaca3995d16cd67ad7c01b73d99c60..002cbe52cf9e560b8a7aadc3538ac6609ee13b11 100644 (file)
@@ -2,7 +2,9 @@
 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
index c0e7238c99b5e059bb5068b2c4a1f6871cf810d9..2eed400912b7b3685bfd0e489effd83a9b53c25c 100644 (file)
@@ -99,7 +99,7 @@ Platform
 |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
 ^^^^^^^^
@@ -301,7 +301,7 @@ should also add ``--enable-avx2`` also. On Intel processors supporting
 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
@@ -669,7 +669,7 @@ manual.
 
 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
@@ -1301,7 +1301,6 @@ For details, you can
 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.
index 5567d3a7e45828950bedc61b6c43e27f16dab7fd..28ecdc9347c324306c6c2ae97c6cb8bc62239ac4 100644 (file)
@@ -1,7 +1,7 @@
 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
 ^^^^^^^^^^^^^^^^^^^^^^^
index 44ac3bbf1c583576c11176af31593b5011b7af9b..6ef673093a782b74f98ea619d3b3d34ec5211c88 100644 (file)
@@ -6,7 +6,7 @@ Reference Manual
 
 .. 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'
 
index 66dd6b5982eb44ebc99d3a59ed5acbd16b50ebca..b583b4df968472d953edc298c1a701b271d31fa6 100644 (file)
@@ -49,7 +49,7 @@ minor release number as your |Gromacs| installation.
 Citation information
 --------------------
 
-.. TODO needs link to ref list
+.. todo:: needs link to ref list
 
 |GMX_MANUAL_DOI_STRING|
 
diff --git a/docs/release-notes/2021/major/bugs-fixed.rst b/docs/release-notes/2021/major/bugs-fixed.rst
new file mode 100644 (file)
index 0000000..1db0c1e
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/deprecated-functionality.rst b/docs/release-notes/2021/major/deprecated-functionality.rst
new file mode 100644 (file)
index 0000000..bf68600
--- /dev/null
@@ -0,0 +1,14 @@
+.. _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 redmine, without the
+   a space between the colon and number!
+
+Changes anticipated to |Gromacs| 2021 functionality
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Functionality deprecated in |Gromacs| 2021
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/docs/release-notes/2021/major/features.rst b/docs/release-notes/2021/major/features.rst
new file mode 100644 (file)
index 0000000..4fab02b
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/highlights.rst b/docs/release-notes/2021/major/highlights.rst
new file mode 100644 (file)
index 0000000..3bcb16d
--- /dev/null
@@ -0,0 +1,22 @@
+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 redmine, without the
+   a space between the colon and number!
diff --git a/docs/release-notes/2021/major/miscellaneous.rst b/docs/release-notes/2021/major/miscellaneous.rst
new file mode 100644 (file)
index 0000000..96513fa
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/performance.rst b/docs/release-notes/2021/major/performance.rst
new file mode 100644 (file)
index 0000000..0a72678
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/portability.rst b/docs/release-notes/2021/major/portability.rst
new file mode 100644 (file)
index 0000000..48bba8a
--- /dev/null
@@ -0,0 +1,9 @@
+Portability
+^^^^^^^^^^^
+
+.. 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
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/removed-functionality.rst b/docs/release-notes/2021/major/removed-functionality.rst
new file mode 100644 (file)
index 0000000..e6a6459
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
diff --git a/docs/release-notes/2021/major/tools.rst b/docs/release-notes/2021/major/tools.rst
new file mode 100644 (file)
index 0000000..3451957
--- /dev/null
@@ -0,0 +1,9 @@
+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 redmine, without the
+   a space between the colon and number!
+
index 16cb7ea8ac75c86ddba6de2e545b61ec5b65f3e8..ee390badc02d75946af0be1ea6b1008f569bdd35 100644 (file)
@@ -8,18 +8,40 @@ releases of |Gromacs|. Major releases contain changes to the
 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 2018 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.
 
+|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
 ---------------------
 
index 3d078d7da7a2064b802222b931144bbf278f75f1..d0fd44c7e9031ad1b9e8ef73cb7210c0a4cfe379 100644 (file)
@@ -4,7 +4,7 @@
 .. 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
+.. todo:: still undocumented GMX_QM_GAUSSIAN_NCPUS
 
 Environment Variables
 =====================
index 352681430aa077e109c5801e1d6e27280f004bb9..2c45196c27e0495bc95bb988acaa547a86e5bf4b 100644 (file)
@@ -111,7 +111,9 @@ Questions regarding simulation methodology
 
     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?
 
@@ -132,16 +134,24 @@ Questions regarding simulation methodology
     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?
 
@@ -176,9 +186,13 @@ Parameterization and Force Fields
 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?
index 334fd1f1b92bec894170d60dfec61764ff039ac7..d01f83f2f9ced31532170041a16b0e1569af9ad9 100644 (file)
@@ -105,7 +105,7 @@ for 43a1, 43a2, 45a3, 53a5, 53a6 and 54a7. The GROMOS force fields are
 * 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_
index f70b08ad1d1d3d1c36aa824416865af2fd6d903d..34c6749ee1ff775ab36a2f341f06d941e2154d76 100644 (file)
@@ -20,7 +20,9 @@ For background on algorithms and implementations, see the
 
 |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::
index f44286dbfb1fcdc9e1acf0a544d71cbd4708faf9..2691832a8bec69bb1e0ffd612a91123ee4a58f7e 100644 (file)
@@ -2,8 +2,9 @@
    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)
 ============================================
index 2a3d510c648db311dd99962cc6e9eeacb521f18b..47c75f6c5804efb265c393c740666eee5e4fb154 100644 (file)
@@ -1003,9 +1003,11 @@ An additional set of subcounters can offer more fine-grained inspection of perfo
 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:
 
@@ -1062,7 +1064,7 @@ compatibility (please see the :ref:`section below <gmx-pme-gpu-limitations>`).
 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.
@@ -1074,7 +1076,7 @@ this problem and thus reduce the calculation time.
 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
@@ -1110,7 +1112,7 @@ Known limitations
 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
@@ -1199,9 +1201,9 @@ Performance considerations for GPU tasks
 #) 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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1252,7 +1254,7 @@ Note that assigning fewer resources to :ref:`gmx mdrun` CPU computation
 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
 -----------------------------------
@@ -1272,7 +1274,8 @@ required as the open source nouveau driver (available in Mesa) does not
 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>`.
 
index b47083a4a72028f27c671ad9dca98358492392f8..440e566daff7f943c25e638179834fbf031d7cab 100644 (file)
@@ -85,8 +85,14 @@ the options for obtaining the force field parameters are:
 * 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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 860b6c58af7c5198b2bdaa10f2dc7296a8914317..3fdaf484bb4d3d0e4564a21189f366b95f41db18 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index 4ec29f6f94074c764f985554a05227ac2e2d8b9d..e6d64d7738d64ae1b3ab8d3a9fc7c2cecd5c4499 100644 (file)
@@ -1,6 +1,7 @@
 # Python package requirements for complete build, installation, and testing of
 # gmxapi functionality.
 cmake>=3.9.6
+flake8>=3.7.7
 networkx>=2.0
 pip>=10.1
 setuptools>=28.0.0
index db5da48a4397a0a124740d355ac25bce60a3c17e..6de576d1cabe687ca1e980f7efd2ad3d6d6dd243 100644 (file)
@@ -44,6 +44,7 @@ from contextlib import contextmanager
 
 import pytest
 
+pytest_plugins = ('gmxapi.testsupport',)
 
 def pytest_addoption(parser):
     """Add a command-line user option for the pytest invocation."""
index 135e6ec6b1e965370598a94a24745978c44d59c0..b9d0f14092c466158b6dadf55c8c6cdd66c4ab90 100644 (file)
@@ -14,7 +14,6 @@ from gmxapi.simulation.context import Context
 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
@@ -73,7 +72,7 @@ def test_ensemble_potential_nompi(spc_water_box):
         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
diff --git a/python_packaging/scripts/run_flake8 b/python_packaging/scripts/run_flake8
new file mode 100755 (executable)
index 0000000..3e5ec34
--- /dev/null
@@ -0,0 +1,19 @@
+#!/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
index 890f225d22153b2f3e672a9a62b78222674691aa..2304e5a4b060c55bee7b49c50c4c1f4074da19b5 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index b881e67b7fb321a3323de20821b9df0bf156f068..378de8c6d6a85adb5e350a015c7f7e43469a09cb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
@@ -31,6 +31,7 @@
 #
 # To help us fund GROMACS development, we humbly ask that you cite
 # the research papers on the package. Check out http://www.gromacs.org.
+
 """
 Provide command line operation.
 """
index ee308f90b89bbcd0faf1a137e82197563d466577..c9af75092cfd2dacaa09260044e23431f866d4c0 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index 6be962bfaaf4ff97ab571b72fd1c2e0dd0de4612..85387acd875ecfb853313fde4d246d727cb3b32c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 4ed554bf020b9098d48e17ba1214ca6feb1678c3..5e36d9ff1aced4025a31bf964bf963e9519271b4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index c610453a68ab70fceb6fcc546b5abacbb808d910..ba585979d4e187adea65f634011e1803e68ed89e 100644 (file)
 
 """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 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
index 5a4e929b66fefee6c693bb4fee239a6c30b4abc3..f08e8a9ee278853e5a887ccd4cb55b80ba29eaaf 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index c4a2c487484b28413c307158af673640fa7a72d0..d906933e1b0d942e7099517c0b03d01a6e2c7791 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index db5da48a4397a0a124740d355ac25bce60a3c17e..6de576d1cabe687ca1e980f7efd2ad3d6d6dd243 100644 (file)
@@ -44,6 +44,7 @@ from contextlib import contextmanager
 
 import pytest
 
+pytest_plugins = ('gmxapi.testsupport',)
 
 def pytest_addoption(parser):
     """Add a command-line user option for the pytest invocation."""
index 3c764e07c98c95a7ea9b3104afaa83afa6d69176..e18d2bbe8b00c1d7545ce4c8ca8b56bc67937ee5 100644 (file)
@@ -47,7 +47,6 @@ import os
 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)
@@ -81,7 +80,7 @@ def test_run_from_tpr(spc_water_box):
     # 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
index db5da48a4397a0a124740d355ac25bce60a3c17e..6de576d1cabe687ca1e980f7efd2ad3d6d6dd243 100644 (file)
@@ -44,6 +44,7 @@ from contextlib import contextmanager
 
 import pytest
 
+pytest_plugins = ('gmxapi.testsupport',)
 
 def pytest_addoption(parser):
     """Add a command-line user option for the pytest invocation."""
index 427fce5f081512d8d9a7963ce06fb0bf283386ad..cad3b695122382ce18bdb9262a68add599426613 100644 (file)
@@ -103,15 +103,26 @@ set(IGNORED_CLANG_ALL_WARNINGS
     "-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)
 
index 124b8dbc9d7e96f4c68b9d11fa476f3efe309e47..8b824e0461868b030976a714da3678a80181cbfb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index f22edbbbe84dac8c318a03b264c99798810bb46d..1f6e172060ac0fbb0655ca783d05d17e753edec2 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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.
index bed5e8f95c499395407e3f376fe71b23f291ca68..99d4bf40084572d20175608806273956f129be78 100644 (file)
 /* Use ORCA for QM-MM calculations */
 #cmakedefine01 GMX_QMMM_ORCA
 
-/* Use cycle counters */
-#cmakedefine01 GMX_CYCLECOUNTERS
-
 /* Use sub-counters */
 #cmakedefine01 GMX_CYCLE_SUBCOUNTERS
 
index 535b418a61b0b2caa448e6f101e20186184331f8..57f9e5a6a962d167d81cb120578fd0bd6f0bb7c7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 0e9f4e611bc9258494c3d6ba3be60f0d7d8bf1d4..80c7797bf610d32106ed7daecd8175cfa0627bcb 100644 (file)
@@ -288,8 +288,8 @@ void set_ddbox(const gmx_domdec_t&            dd,
         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);
     }
 
index 28078ffc54bfd45b2c663529cf18a3aad64b527e..4867f64330aebaac43ddc9c040398bae851ae8f0 100644 (file)
@@ -70,7 +70,7 @@ static void set_pme_maxshift(gmx_domdec_t*      dd,
     int                sh;
 
     comm = dd->comm;
-    nc   = dd->nc[ddpme->dim];
+    nc   = dd->numCells[ddpme->dim];
     ns   = ddpme->nslab;
 
     if (!ddpme->dim_match)
@@ -137,13 +137,13 @@ static void check_box_size(const gmx_domdec_t* dd, const gmx_ddbox_t* ddbox)
         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);
         }
     }
@@ -221,14 +221,14 @@ set_dd_cell_sizes_slb(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, int setmode, i
     {
         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;
                     }
@@ -261,16 +261,16 @@ set_dd_cell_sizes_slb(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, int setmode, i
             }
             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]++;
                 }
@@ -286,7 +286,7 @@ set_dd_cell_sizes_slb(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, int setmode, i
          * 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];
 
@@ -295,7 +295,7 @@ set_dd_cell_sizes_slb(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, int setmode, i
                     "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)
             {
@@ -346,7 +346,7 @@ static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t*      dd,
 
     comm = dd->comm;
 
-    const int ncd = dd->nc[dim];
+    const int ncd = dd->numCells[dim];
 
     const bool dimHasPbc = (dim < ddbox->npbcdim);
 
@@ -391,7 +391,7 @@ static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t*      dd,
             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;
                 }
@@ -572,7 +572,7 @@ static void set_dd_cell_sizes_dlb_root(gmx_domdec_t*      dd,
     /* 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);
 
@@ -688,7 +688,7 @@ static void set_dd_cell_sizes_dlb_root(gmx_domdec_t*      dd,
                     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];
@@ -757,7 +757,7 @@ static void distribute_dd_cell_sizes_dlb(gmx_domdec_t*       dd,
     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)
@@ -860,7 +860,7 @@ static void set_dd_cell_sizes_dlb(gmx_domdec_t*      dd,
     /* 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];
index 50b17507ce8bdb23d9f3db9b18e816b4665c2cea..a681378a0514147c1271370e75683dbd7a4e3f32 100644 (file)
@@ -310,7 +310,7 @@ static inline int computeAtomGroupDomainIndex(const gmx_domdec_t& dd,
         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++)
@@ -359,13 +359,13 @@ static inline int computeAtomGroupDomainIndex(const gmx_domdec_t& dd,
         }
         /* 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);
 }
 
 
index de3fc3c4b367160b238c7506416addda8f0c3787..3e8a3d87c93875c503752b948cea37c965a1d786 100644 (file)
@@ -2,7 +2,7 @@
  * 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) 2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -143,18 +143,6 @@ static const int ddNonbondedZonePairRanges[DD_MAXIZONE][3] = { { 0, 0, 8 },
                                                                { 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]);
@@ -167,7 +155,7 @@ static int ddcoord2ddnodeid(gmx_domdec_t* dd, ivec c)
     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];
@@ -701,24 +689,11 @@ static int gmx_ddcoord2pmeindex(const t_commrec* cr, int x, int y, int z)
     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;
 }
@@ -737,7 +712,7 @@ static int ddcoord2simnodeid(const t_commrec* cr, int x, int y, int z)
     }
     else
     {
-        int ddindex = dd_index(cr->dd->nc, coords);
+        int ddindex = dd_index(cr->dd->numCells, coords);
         if (cartSetup.bCartesianPP)
         {
             nodeid = cartSetup.ddindex2simnodeid[ddindex];
@@ -884,7 +859,7 @@ static gmx_bool receive_vir_ener(const gmx_domdec_t* dd, gmx::ArrayRef<const int
             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);
@@ -922,9 +897,9 @@ static void set_slb_pme_dim_f(gmx_domdec_t* dd, int dim, real** dim_f)
 
     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])
         {
@@ -932,10 +907,10 @@ static void set_slb_pme_dim_f(gmx_domdec_t* dd, int dim, real** dim_f)
         }
         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)
@@ -965,13 +940,13 @@ 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.
          */
@@ -1067,10 +1042,10 @@ static void make_load_communicator(gmx_domdec_t* dd, int dim_ind, ivec loc)
 
     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 */
@@ -1092,13 +1067,13 @@ static void make_load_communicator(gmx_domdec_t* dd, int dim_ind, ivec loc)
 
                 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
             {
@@ -1108,7 +1083,7 @@ static void make_load_communicator(gmx_domdec_t* dd, int dim_ind, ivec loc)
         }
         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);
         }
     }
 }
@@ -1191,7 +1166,7 @@ static void make_load_communicators(gmx_domdec_t gmx_unused* dd)
     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);
@@ -1200,11 +1175,11 @@ static void make_load_communicators(gmx_domdec_t gmx_unused* dd)
     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);
@@ -1231,10 +1206,10 @@ static void setup_neighbor_relations(gmx_domdec_t* dd)
     {
         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)
         {
@@ -1267,11 +1242,11 @@ static void setup_neighbor_relations(gmx_domdec_t* dd)
             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];
             }
         }
     }
@@ -1290,7 +1265,7 @@ static void setup_neighbor_relations(gmx_domdec_t* dd)
                                            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;
@@ -1343,8 +1318,8 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
     {
         /* 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++)
@@ -1352,7 +1327,8 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
             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;
     }
@@ -1366,7 +1342,7 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
          * 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.
@@ -1402,7 +1378,7 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
         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,
@@ -1415,7 +1391,7 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
         {
             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);
             }
         }
@@ -1428,7 +1404,7 @@ static void make_pp_communicator(const gmx::MDLogger& mdlog,
     {
         /* 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);
@@ -1456,7 +1432,7 @@ static void receive_ddindex2simnodeid(gmx_domdec_t* dd, t_commrec* cr)
         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,
@@ -1704,7 +1680,7 @@ static void setupGroupCommunication(const gmx::MDLogger&     mdlog,
     /* 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);
     }
 }
 
@@ -1787,7 +1763,7 @@ static int dd_getenv(const gmx::MDLogger& mdlog, const char* env_var, int def)
 
 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->ePBC == epbcSCREW && (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]);
@@ -2441,18 +2417,18 @@ static void set_dd_limits(const gmx::MDLogger& mdlog,
     }
 
     /* 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 */
@@ -2466,7 +2442,7 @@ static void set_dd_limits(const gmx::MDLogger& mdlog,
              * 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))
             {
@@ -2512,17 +2488,17 @@ static void set_dd_limits(const gmx::MDLogger& mdlog,
     }
 }
 
-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;
 
@@ -2567,16 +2543,16 @@ static void writeSettings(gmx::TextWriter*   log,
         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);
             }
@@ -2595,7 +2571,7 @@ static void writeSettings(gmx::TextWriter*   log,
         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]);
             }
@@ -2727,7 +2703,7 @@ static void set_cell_limits_dlb(const gmx::MDLogger& mdlog,
     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)
@@ -2739,7 +2715,7 @@ static void set_cell_limits_dlb(const gmx::MDLogger& mdlog,
             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);
         }
@@ -2763,10 +2739,10 @@ static void set_cell_limits_dlb(const gmx::MDLogger& mdlog,
         }
         else
         {
-            comm->cd[d].np_dlb = std::min(npulse, 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->nc[dd->dim[d]] - 1)
+        if (comm->cd[d].np_dlb < dd->numCells[dd->dim[d]] - 1)
         {
             comm->bVacDLBNoLimit = FALSE;
         }
@@ -2812,7 +2788,7 @@ gmx_bool dd_bonded_molpbc(const gmx_domdec_t* dd, int ePBC)
      * 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)));
+            && !(dd->numCells[XX] > 1 && dd->numCells[YY] > 1 && (dd->numCells[ZZ] > 1 || ePBC == epbcXY)));
 }
 
 /*! \brief Sets grid size limits and PP-PME setup, prints settings to log */
@@ -2862,7 +2838,7 @@ static void set_ddgrid_parameters(const gmx::MDLogger& mdlog,
     }
     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)
@@ -2971,8 +2947,8 @@ static bool canMake1DAnd1PulseDomainDecomposition(const DDSettings&
 
 bool is1DAnd1PulseDD(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 =
@@ -3167,7 +3143,7 @@ static gmx_bool test_dd_cutoff(t_commrec* cr, const matrix box, gmx::ArrayRef<co
     {
         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;
index 9fb46bc0608c722f5b136c8462a7c108beb2a900..cf915168681500c54bcffcace8fcd71b61920804 100644 (file)
@@ -2,7 +2,7 @@
  * 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,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -158,13 +158,13 @@ bool ddUsesUpdateGroups(const gmx_domdec_t& dd);
 bool is1DAnd1PulseDD(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);
@@ -298,7 +298,7 @@ void dd_init_local_state(struct gmx_domdec_t* dd, const t_state* state_global, t
  *
  * 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,
index 0a62ae980ee58c162770ab360bfb74fd28e6e3cb..99b79d828d192f085bc823efdf6de98c11245b6b 100644 (file)
 #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
 {
@@ -141,7 +143,7 @@ static void walk_out(int                       con,
                      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,
@@ -149,9 +151,6 @@ static void walk_out(int                       con,
                      t_ilist*                  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 */
@@ -163,10 +162,10 @@ static void walk_out(int                       con,
             il_local->nalloc = over_alloc_dd(il_local->nr + 3);
             srenew(il_local->iatoms, il_local->nalloc);
         }
-        iap                              = constr_iatomptr(ia1, ia2, con);
+        const int* iap                   = constr_iatomptr(ia1, ia2, con);
         il_local->iatoms[il_local->nr++] = iap[0];
-        a1_gl                            = offset + iap[1];
-        a2_gl                            = offset + iap[2];
+        const int a1_gl                  = offset + iap[1];
+        const int a2_gl                  = offset + iap[2];
         /* The following indexing code can probably be optizimed */
         if (const int* a_loc = ga2la.findHome(a1_gl))
         {
@@ -200,13 +199,14 @@ static void walk_out(int                       con,
 
     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];
@@ -306,17 +306,14 @@ static void atoms_to_settles(gmx_domdec_t*                         dd,
 }
 
 /*! \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,
+                                 t_ilist*                              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;
 
@@ -344,15 +341,16 @@ static void atoms_to_constraints(gmx_domdec_t*                 dd,
              * 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];
@@ -373,7 +371,7 @@ static void atoms_to_constraints(gmx_domdec_t*                 dd,
                             ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3);
                             srenew(ilc_local->iatoms, ilc_local->nalloc);
                         }
-                        b_lo                               = *a_loc;
+                        const int 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);
@@ -416,13 +414,11 @@ int dd_make_local_constraints(gmx_domdec_t*            dd,
                               int                      nrec,
                               t_ilist*                 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;
+    t_ilist *                 ilc_local, *ils_local;
+    gmx::HashedMap<int>*      ga2la_specat;
+    int                       at_end, i, j;
+    t_iatom*                  iap;
 
     // This code should not be called unless this condition is true,
     // because that's the only time init_domdec_constraints is
@@ -446,6 +442,8 @@ int dd_make_local_constraints(gmx_domdec_t*            dd,
 
     dc->ncon      = 0;
     ilc_local->nr = 0;
+    gmx::ArrayRef<const ListOfLists<int>> at2con_mt;
+    std::vector<int>*                     ireq = nullptr;
     if (dd->constraint_comm)
     {
         // TODO Perhaps gmx_domdec_constraints_t should keep a valid constr?
@@ -454,12 +452,6 @@ int dd_make_local_constraints(gmx_domdec_t*            dd,
         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 */
index 1b62f894b093964c6f0d804a07d28e78f700f8b6..354f94352c1f9fcb91213a2dc6d217cd5fae79a6 100644 (file)
@@ -778,7 +778,7 @@ static inline int dd_index(const ivec numDomains, const ivec domainCoordinates)
 /*! 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
index 04faddad435aa3791c6a9662dc3e28ec5b3ec5e4..7c15e8ab3323fdd69f2e0f54085ea257a7e2c300 100644 (file)
@@ -76,7 +76,7 @@ void dd_move_f_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, rvec* f,
     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];
@@ -89,7 +89,8 @@ void dd_move_f_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, rvec* f,
                               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];
@@ -145,7 +146,7 @@ void dd_move_f_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, rvec* f,
                        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)
@@ -187,7 +188,7 @@ void dd_move_x_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, const ma
     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());
@@ -199,7 +200,7 @@ void dd_move_x_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, const ma
                     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);
@@ -295,7 +296,7 @@ void dd_move_x_specat(gmx_domdec_t* dd, gmx_domdec_specat_comm_t* spac, const ma
             {
                 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.
@@ -379,7 +380,7 @@ int setup_specat_communication(gmx_domdec_t*             dd,
         /* 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;
@@ -390,8 +391,8 @@ int setup_specat_communication(gmx_domdec_t*             dd,
         }
         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;
@@ -423,7 +424,7 @@ int setup_specat_communication(gmx_domdec_t*             dd,
     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;
         }
index 55a6a3e9690b253df20089df981867b88cbb3808..12a134c96c3b6ecf022e31506980ce38c81b2e60 100644 (file)
@@ -94,21 +94,21 @@ struct DDPairInteractionRanges
     //! 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
@@ -129,13 +129,13 @@ 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 */
@@ -170,10 +170,10 @@ struct gmx_domdec_t
     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;
@@ -185,9 +185,10 @@ struct gmx_domdec_t
     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 } };
index 6e28cad22c6e52fd7adcfc8c8eaf08dd5383f02b..a8424c8a6c1764fd28d2871cc017a10f56804fc4 100644 (file)
@@ -75,6 +75,7 @@
 #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"
@@ -87,6 +88,8 @@
 #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
 
@@ -111,7 +114,7 @@ struct thread_work_t
     t_idef                    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 */
 };
 
@@ -119,8 +122,6 @@ struct thread_work_t
 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?
@@ -453,14 +454,15 @@ static void global_atomnr_to_moltype_ind(const gmx_reverse_top_t* rt, int i_gl,
 }
 
 /*! \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);
@@ -717,10 +719,7 @@ void dd_make_reverse_top(FILE*              fplog,
             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);
@@ -729,7 +728,6 @@ void dd_make_reverse_top(FILE*              fplog,
         {
             dd->haveExclusions = true;
         }
-        rt->n_excl_at_max = std::max(rt->n_excl_at_max, maxNumExclusionsPerAtom);
     }
 
     if (vsite && vsite->numInterUpdategroupVsites > 0)
@@ -995,40 +993,6 @@ static real dd_dist2(t_pbc* pbc_null, const rvec* x, const int i, int j)
     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)
 {
@@ -1377,11 +1341,11 @@ static int make_bondeds_zone(gmx_domdec_t*                      dd,
 }
 
 /*! \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)
+static void set_no_exclusions_zone(const gmx_domdec_zones_t* zones, int iz, ListOfLists<int>* lexcls)
 {
     for (int a = zones->cg_range[iz]; a < zones->cg_range[iz + 1]; a++)
     {
-        lexcls->index[a + 1] = lexcls->nra;
+        lexcls->pushBack({});
     }
 }
 
@@ -1390,52 +1354,33 @@ 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
@@ -1444,16 +1389,11 @@ static void make_exclusions_zone(gmx_domdec_t*                     dd,
                      */
                     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(),
@@ -1462,51 +1402,26 @@ static void make_exclusions_zone(gmx_domdec_t*                     dd,
 
         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);
-    }
+    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 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)
+static void finish_local_exclusions(gmx_domdec_t* dd, gmx_domdec_zones_t* zones, ListOfLists<int>* lexcls)
 {
     const gmx::Range<int> nonhomeIzonesAtomRange(zones->iZones[0].iAtomRange.end(),
                                                  zones->iZones.back().iAtomRange.end());
@@ -1516,19 +1431,10 @@ static void finish_local_exclusions(gmx_domdec_t* dd, gmx_domdec_zones_t* zones,
         /* There are no exclusions involving non-home charge groups,
          * but we need to set the indices for neighborsearching.
          */
-        for (int la : nonhomeIzonesAtomRange)
+        for (int gmx_unused la : nonhomeIzonesAtomRange)
         {
-            lexcls->index[la] = lexcls->nra;
+            lexcls->pushBack({});
         }
-
-        /* 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();
     }
 }
 
@@ -1556,7 +1462,7 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
                                     t_pbc*              pbc_null,
                                     rvec*               cg_cm,
                                     t_idef*             idef,
-                                    t_blocka*           lexcls,
+                                    ListOfLists<int>*   lexcls,
                                     int*                excl_count)
 {
     int                nzone_bondeds, nzone_excl;
@@ -1588,8 +1494,6 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
         nzone_excl = 1;
     }
 
-    check_exclusions_alloc(dd, zones, lexcls);
-
     rt = dd->reverse_top;
 
     rc2 = rc * rc;
@@ -1598,8 +1502,7 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
     clear_idef(idef);
     nbonded_local = 0;
 
-    lexcls->nr  = 0;
-    lexcls->nra = 0;
+    lexcls->clear();
     *excl_count = 0;
 
     for (int izone = 0; izone < nzone_bondeds; izone++)
@@ -1613,9 +1516,8 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
         {
             try
             {
-                int       cg0t, cg1t;
-                t_idef*   idef_t;
-                t_blocka* excl_t;
+                int     cg0t, cg1t;
+                t_idef* idef_t;
 
                 cg0t = cg0 + ((cg1 - cg0) * thread) / numThreads;
                 cg1t = cg0 + ((cg1 - cg0) * (thread + 1)) / numThreads;
@@ -1636,15 +1538,17 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
 
                 if (izone < nzone_excl)
                 {
+                    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 */
@@ -1667,11 +1571,10 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
 
         if (izone < nzone_excl)
         {
-            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;
@@ -1690,7 +1593,7 @@ static int make_local_bondeds_excls(gmx_domdec_t*       dd,
     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;
@@ -1737,9 +1640,10 @@ void dd_make_local_top(gmx_domdec_t*       dd,
             /* 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;
@@ -1760,7 +1664,7 @@ void dd_make_local_top(gmx_domdec_t*       dd,
         {
             if (fr->bMolPBC)
             {
-                pbc_null = set_pbc_dd(&pbc, fr->ePBC, dd->nc, TRUE, box);
+                pbc_null = set_pbc_dd(&pbc, fr->ePBC, dd->numCells, TRUE, box);
             }
             else
             {
@@ -1857,7 +1761,7 @@ static void check_link(t_blocka* link, int cg_gl, int cg_gl_j)
     }
 }
 
-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;
@@ -1868,35 +1772,35 @@ t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_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.
@@ -1907,7 +1811,7 @@ t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_mb)
         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++)
             {
@@ -1931,7 +1835,7 @@ t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_mb)
                     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])
@@ -1997,7 +1901,7 @@ t_blocka* makeBondedLinks(const gmx_mtop_t* mtop, cginfo_mb_t* cginfo_mb)
 
     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;
@@ -2062,12 +1966,11 @@ static void bonded_cg_distance_mol(const gmx_moltype_t* molt,
     }
     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]);
index 28db18d212d455e594929bc1b897e8a22b34eaa2..e0e1a549e7c0b527911402facb53b54421943e72 100644 (file)
@@ -87,7 +87,7 @@ void write_dd_grid_pdb(const char* fn, int64_t step, gmx_domdec_t* dd, matrix bo
                 }
                 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];
                     }
index b00ceec520596409c50bc96b027913a0dc0e7749..487514edae70a00b6e050768b0c5324499f2b096 100644 (file)
@@ -209,7 +209,7 @@ static void dd_move_cellx(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, rvec cell_
         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
         {
@@ -243,7 +243,7 @@ static void dd_move_cellx(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, rvec cell_
         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),
@@ -325,8 +325,8 @@ static void dd_move_cellx(gmx_domdec_t* dd, const gmx_ddbox_t* ddbox, rvec cell_
                  */
                 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;
@@ -462,8 +462,8 @@ static void dd_set_cginfo(gmx::ArrayRef<const int> index_gl, int cg0, int cg1, t
 {
     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++)
         {
@@ -732,7 +732,7 @@ static void comm_dd_ns_cell_sizes(gmx_domdec_t* dd, gmx_ddbox_t* ddbox, rvec cel
         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])
         {
@@ -863,7 +863,7 @@ static void get_load_distribution(gmx_domdec_t* dd, gmx_wallcycle_t wcycle)
                 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]);
@@ -904,7 +904,7 @@ static void get_load_distribution(gmx_domdec_t* dd, gmx_wallcycle_t wcycle)
                 }
                 if (isDlbOn(comm) && rowMaster->dlbIsLimited)
                 {
-                    load->sum_m *= dd->nc[dim];
+                    load->sum_m *= dd->numCells[dim];
                     load->flags |= (1 << d);
                 }
             }
@@ -1258,7 +1258,7 @@ static void turn_on_dlb(const gmx::MDLogger& mdlog, gmx_domdec_t* dd, int64_t st
         {
             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);
@@ -1327,7 +1327,7 @@ static void merge_cg_buffers(int                            ncell,
                              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;
@@ -1820,7 +1820,6 @@ static void setup_dd_communication(gmx_domdec_t*                dd,
     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;
@@ -1894,8 +1893,8 @@ static void setup_dd_communication(gmx_domdec_t*                dd,
         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;
index eb130157c64b42808990291014d794c0e671674c..ba86477b598c5db0b46f25b3fa3c1c2ce7c7877f 100644 (file)
@@ -299,7 +299,7 @@ static int computeMoveFlag(const gmx_domdec_t& dd, const ivec& dev)
             flag |= DD_FLAG_BW(d);
             if (firstMoveDimValue == -1)
             {
-                if (dd.nc[dim] > 2)
+                if (dd.numCells[dim] > 2)
                 {
                     firstMoveDimValue = d * 2 + 1;
                 }
@@ -344,7 +344,7 @@ static void calc_cg_move(FILE*              fplog,
         /* 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 */
@@ -365,7 +365,7 @@ static void calc_cg_move(FILE*              fplog,
                                       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)
@@ -468,7 +468,7 @@ static void calcGroupMove(FILE*                     fplog,
         /* 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];
@@ -488,7 +488,7 @@ static void calcGroupMove(FILE*                     fplog,
                                       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]);
                     }
@@ -584,7 +584,7 @@ void dd_redistribute_cg(FILE*                        fplog,
         {
             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;
         }
@@ -736,7 +736,7 @@ void dd_redistribute_cg(FILE*                        fplog,
     /* 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;
@@ -748,7 +748,7 @@ void dd_redistribute_cg(FILE*                        fplog,
         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 */
@@ -787,7 +787,7 @@ void dd_redistribute_cg(FILE*                        fplog,
             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.
@@ -819,7 +819,7 @@ void dd_redistribute_cg(FILE*                        fplog,
                          * 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 */
@@ -842,7 +842,7 @@ void dd_redistribute_cg(FILE*                        fplog,
                              * 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);
                             }
@@ -861,7 +861,7 @@ void dd_redistribute_cg(FILE*                        fplog,
                     }
                     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;
                         }
index 9d7db1f11235161c117f31deb98b49f368b36ea8..353dc327b0f39a0c4207c7379a080568b583748a 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "gromacs/gpu_utils/hostallocator.h"
 #include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/utility/arrayref.h"
 
 #include "domdec_internal.h"
 
@@ -77,14 +78,16 @@ void make_tric_corr_matrix(int npbcdim, const matrix box, matrix tcm);
 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 */
index dfe848159380f441bb2a12be37fb8963773937ef..a4a608b5a25b1dd265ca412eeb64dc44524389f7 100644 (file)
@@ -66,7 +66,7 @@ public:
      * send coordinates buffer address to PP rank
      * \param[in] d_x   coordinates buffer in GPU memory
      */
-    void sendCoordinateBufferAddressToPpRanks(rvec* d_x);
+    void sendCoordinateBufferAddressToPpRanks(DeviceBuffer<float> d_x);
 
 
     /*! \brief
index 35ddc077336c5b1110a43c697fae388cf91fe117..213a88c59edaf5426aaaad7aa2998a4a685e8135 100644 (file)
@@ -60,9 +60,9 @@ class PmeCoordinateReceiverGpu::Impl
 };
 
 /*!\brief Constructor stub. */
-PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void gmx_unused* pmeStream,
-                                                   MPI_Comm gmx_unused    comm,
-                                                   gmx::ArrayRef<PpRanks> gmx_unused ppRanks) :
+PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void* /* pmeStream */,
+                                                   MPI_Comm /* comm */,
+                                                   gmx::ArrayRef<PpRanks> /* ppRanks */) :
     impl_(nullptr)
 {
     GMX_ASSERT(false,
@@ -73,14 +73,14 @@ PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void gmx_unused* pmeStream,
 PmeCoordinateReceiverGpu::~PmeCoordinateReceiverGpu() = default;
 
 /*!\brief init PME-PP GPU communication stub */
-void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(rvec gmx_unused* d_x)
+void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(const DeviceBuffer<float> /* d_x */)
 {
     GMX_ASSERT(false,
                "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,
                "A CPU stub for PME-PP GPU communication was called instead of the correct "
index 3ca69e27a882225bba32590da8afb32f0d2f0501..fd55c832ff2d3dc1c4cf4287766f481113d115d8 100644 (file)
@@ -72,7 +72,7 @@ PmeCoordinateReceiverGpu::Impl::Impl(void* pmeStream, MPI_Comm comm, gmx::ArrayR
 
 PmeCoordinateReceiverGpu::Impl::~Impl() = default;
 
-void PmeCoordinateReceiverGpu::Impl::sendCoordinateBufferAddressToPpRanks(rvec* d_x)
+void PmeCoordinateReceiverGpu::Impl::sendCoordinateBufferAddressToPpRanks(const DeviceBuffer<float> d_x)
 {
 
     int ind_start = 0;
@@ -134,7 +134,7 @@ PmeCoordinateReceiverGpu::PmeCoordinateReceiverGpu(void*                  pmeStr
 
 PmeCoordinateReceiverGpu::~PmeCoordinateReceiverGpu() = default;
 
-void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(rvec* d_x)
+void PmeCoordinateReceiverGpu::sendCoordinateBufferAddressToPpRanks(const DeviceBuffer<float> d_x)
 {
     impl_->sendCoordinateBufferAddressToPpRanks(d_x);
 }
index fe689799e1cb3a4b46d9578786fc0b9cac5c1fc7..84a554725b8e439c9d0ab595d5afafa6b514d28b 100644 (file)
@@ -67,7 +67,7 @@ public:
      * send coordinates buffer address to PP rank
      * \param[in] d_x   coordinates buffer in GPU memory
      */
-    void sendCoordinateBufferAddressToPpRanks(rvec* d_x);
+    void sendCoordinateBufferAddressToPpRanks(const DeviceBuffer<float> d_x);
 
     /*! \brief
      * launch receive of coordinate data from PP rank
index e0431a76cdc05b15f94aba0f919d6cad248301d4..19eca520debe4ce22a8e6f34d38fb9291f43f240 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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-2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 1e6682d46c6b63462557f8571197b5509361d65e..b163d349eccbecec8372216bf2c2f9945c2ec090 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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-2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 4e66664ae22663f3c2afa15cd2bfaae033dc1a7b..6c8077bbabddae3f36280e5719c547dead264c26 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -423,14 +423,10 @@ static int gmx_pme_recv_coeffs_coords(struct gmx_pme_t*            pme,
                                "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(
+                            pme_gpu_get_device_x(pme));
+                    pme_pp->pmeForceSenderGpu->sendForceBufferAddressToPpRanks(
+                            reinterpret_cast<rvec*>(pme_gpu_get_device_f(pme)));
                 }
             }
 
index fc68e96f4131af69cbc38c607be52f92230f1946..57bed345c4573ce8cd395cad7b6407b6afeae56d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index f431614cc8a512e39d767b6fd97c9a9d9726a755..c842577de67b6557227922b5891d53eac07378a2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 86698e5e82bfceee2d8883f17848023644b28aa4..801174e5e55f312f5f50c5bb489a3336350ef257 100644 (file)
@@ -2125,19 +2125,25 @@ static void do_block(gmx::ISerializer* serializer, t_block* block)
     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
@@ -2450,7 +2456,7 @@ static void do_moltype(gmx::ISerializer* serializer, gmx_moltype_t* molt, t_symt
     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)
index bfe16bede134eead6646469ce52e79c2d1819237..2731d4a11d69fd83467764910fe6cbb114cf854e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 3ee9a99542e339aef73bcf8ce03262fd89b3fd00..3bf1507dd74075d11171d64a6d8a1021a8f25a75 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 5c68c4df4e91cfced228b711cfd4034c7acb6ce2..52ab32a3be5252ed88a008ccd382ab095d8aa6ca 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 07368d9d41b2c5ddff94daa131bd7edcd54e5d96..96f20a86dabb9e9b85da9d2ac03724b2770f334e 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index e99bee5628e958d5ed9574e09c120adb03d3d753..5b6246a96c10c8e8acb1d33d62c51624d4d1483c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 8395379dad3f16295d38fe2df94a22242d05126c..e440a146f6489129ac8e6e37eb02af0e64eae1f7 100644 (file)
@@ -265,7 +265,7 @@ static void nb_free_energy_kernel(const t_nblist* gmx_restrict nlist,
     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];
index 19aa460d27637b7f6bf294e815b7d27a392f8fb9..5f6801a4dc67b7efb80d080c4df3a7f89b8add57 100644 (file)
@@ -172,14 +172,14 @@ void __print_nnb(t_nextnb* nnb, char* s)
 }
 #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 */
@@ -230,16 +230,13 @@ static void nnb2excl(t_nextnb* nnb, t_blocka* excl)
         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);
@@ -432,7 +429,7 @@ static void sort_and_purge_nnb(t_nextnb* 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)
 {
     t_nextnb nnb;
     if (nrexcl < 0)
@@ -441,8 +438,7 @@ void generate_excl(int nrexcl, int nratoms, gmx::ArrayRef<InteractionsOfType> pl
     }
     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);
 }
index 4d014cdf97a6afb61f478eb8b7cd902251330212..8e640c1bab5060438ad4ac42e9ef9bc3242508c3 100644 (file)
 
 #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)            */
@@ -75,7 +80,7 @@ void gen_nnb(t_nextnb* nnb, gmx::ArrayRef<InteractionsOfType> plist);
  * 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.
  */
index 3922eeb01c1e046fad881d005632817aa2e477c6..21f967e02a1c4764183ee2337d0cde5630b3d0ee 100644 (file)
 #include "gromacs/utility/futil.h"
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/keyvaluetreebuilder.h"
+#include "gromacs/utility/listoflists.h"
 #include "gromacs/utility/mdmodulenotification.h"
 #include "gromacs/utility/smalloc.h"
 #include "gromacs/utility/snprintf.h"
@@ -234,7 +235,7 @@ void InteractionOfType::setForceParameter(int pos, real value)
 void MoleculeInformation::initMolInfo()
 {
     init_block(&mols);
-    init_blocka(&excls);
+    excls.clear();
     init_t_atoms(&atoms, 0, FALSE);
 }
 
@@ -1426,7 +1427,7 @@ static bool haveDecoupledModeInMol(const gmx_moltype_t&           molt,
 
     const t_atom* atom = molt.atoms.atom;
 
-    t_blocka atomToConstraints =
+    const auto atomToConstraints =
             gmx::make_at2con(molt, iparams, gmx::FlexibleConstraintTreatment::Exclude);
 
     bool haveDecoupledMode = false;
@@ -1456,23 +1457,21 @@ static bool haveDecoupledModeInMol(const gmx_moltype_t&           molt,
                 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;
                         }
@@ -1486,8 +1485,6 @@ static bool haveDecoupledModeInMol(const gmx_moltype_t&           molt,
         }
     }
 
-    done_blocka(&atomToConstraints);
-
     return haveDecoupledMode;
 }
 
index 1e06a7d6da5103cef538af118254c62822ce52ca..7eaa8f1c233a00b04df356fe431adaf72e6d0f35 100644 (file)
@@ -47,6 +47,7 @@
 #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
@@ -176,7 +177,7 @@ struct MoleculeInformation
     //! 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;
 
index 8ad44f530073e2a3ecd3167c08cff8d0f0a9f9c7..9a5e6908edd86719bdd72c7e05852f5b64bb6d77 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, 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.
index 7058eb623b62caf89134349657154f9ac6c6a96a..041cb951369c199c3d1edc0ab149e35e61be157b 100644 (file)
@@ -1376,7 +1376,7 @@ void generate_qmexcl(gmx_mtop_t* sys, t_inputrec* ir, warninp* wi, GmxQmmmMode q
                     /* 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;
                 }
index af199cdc799e50b0184338e1ce7ccc60d8217dc9..f78a72af0282f114c0864a2d2c884f357f44360d 100644 (file)
@@ -2615,10 +2615,8 @@ static void convert_pairs_to_pairsQ(gmx::ArrayRef<InteractionsOfType> interactio
 
 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;
@@ -2628,20 +2626,20 @@ static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, Interact
                "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)
                 {
@@ -2661,24 +2659,20 @@ static void generate_LJCpairsNB(MoleculeInformation* mol, int nb_funct, Interact
     }
 }
 
-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,
index 041ee514b77ffa37252ad0d82769b665c9409b24..ba983faeb1fe8f207ab84a9406a4de3562aa490c 100644 (file)
@@ -120,7 +120,7 @@ static bool fTypeHasPerturbedEntries(const t_idef& idef, int fType)
 
     const t_ilist& ilist = idef.il[fType];
 
-    return (idef.ilsort != ilsortNO_FE && ilist.nr_nonperturbed != ilist.nr);
+    return (idef.ilsort != ilsortNO_FE && idef.numNonperturbedInteractions[fType] != ilist.nr);
 }
 
 //! Converts \p src with atom indices in state order to \p dest in nbnxn order
index 4b46781c2e154bb0b43c5f8b6d6773ba4a4966c6..4e1533ae1e6f9625361ac28fd68a51e119c00289 100644 (file)
@@ -80,6 +80,8 @@
 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. */
@@ -298,6 +300,8 @@ BondedKernelFlavor selectBondedKernelFlavor(const gmx::StepWorkload& stepWork,
 real calc_one_bond(int                      thread,
                    int                      ftype,
                    const t_idef*            idef,
+                   ArrayRef<const int>      iatoms,
+                   const int                numNonperturbedInteractions,
                    const WorkDivision&      workDivision,
                    const rvec               x[],
                    rvec4                    f[],
@@ -318,7 +322,7 @@ real calc_one_bond(int                      thread,
                "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;
@@ -331,11 +335,10 @@ real calc_one_bond(int                      thread,
         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);
@@ -350,13 +353,13 @@ real calc_one_bond(int                      thread,
                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, idef->iparams, idef->cmap_grid, x, f, fshift,
+                          pbc, g, 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, idef->iparams, x, f, fshift,
+                                    pbc, g, lambda[efptFTYPE], &(dvdl[efptFTYPE]), md, fcd,
                                     global_atom_index, flavor);
         }
     }
@@ -365,8 +368,8 @@ real calc_one_bond(int                      thread,
         /* 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, idef->iparams, x, f, fshift, pbc, g, lambda, dvdl,
+                 md, fr, havePerturbedInteractions, stepWork, grpp, global_atom_index);
     }
 
     if (thread == 0)
@@ -435,11 +438,14 @@ static void calcBondedForces(const t_idef*            idef,
             /* 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 t_ilist& ilist = idef->il[ftype];
+                if (ilist.nr > 0 && 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::constArrayRefFromArray(ilist.iatoms, ilist.nr);
+                    v                          = calc_one_bond(
+                            thread, ftype, idef, iatoms, idef->numNonperturbedInteractions[ftype],
+                            fr->bondedThreading->workDivision, x, ft, fshift, fr, pbc_null, g, grpp,
+                            nrnb, lambda, dvdlt, md, fcd, stepWork, global_atom_index);
                     epot[ftype] += v;
                 }
             }
@@ -615,21 +621,22 @@ void calc_listed_lambda(const t_idef*         idef,
         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;
+            /* Create a temporary iatom list with only perturbed interactions */
+            const int           numNonperturbed = idef->numNonperturbedInteractions[ftype];
+            ArrayRef<const int> iatoms = gmx::constArrayRefFromArray(ilist.iatoms + numNonperturbed,
+                                                                     ilist.nr - numNonperturbed);
+            t_ilist&            ilist_fe = idef_fe.il[ftype];
             /* Set the work range of thread 0 to the perturbed bondeds */
             workDivision.setBound(ftype, 0, 0);
-            workDivision.setBound(ftype, 1, ilist_fe.nr);
+            workDivision.setBound(ftype, 1, iatoms.ssize());
 
             if (ilist_fe.nr > 0)
             {
                 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, iatoms, iatoms.ssize(), workDivision, x, f,
+                                  fshift, fr, pbc_null, g, grpp, nrnb, lambda, dvdl_dum, md, fcd,
+                                  tempFlags, global_atom_index);
                 epot[ftype] += v;
             }
         }
index f8d4ff05848abe7217f334ee91e08bc1d00d5371..b696861250d6a45d4ac5d005236941b590d201f0 100644 (file)
@@ -196,7 +196,7 @@ static bool ftypeHasPerturbedEntries(const t_idef& idef, int ftype)
 
     const t_ilist& ilist = idef.il[ftype];
 
-    return (idef.ilsort != ilsortNO_FE && ilist.nr_nonperturbed != ilist.nr);
+    return (idef.ilsort != ilsortNO_FE && idef.numNonperturbedInteractions[ftype] != ilist.nr);
 }
 
 //! Divides bonded interactions over threads and GPU
index eccc21f1f07ba174969b664840d449d0fa5ff7e7..1e418cc78e91611fc165a16055f1c07399aa005b 100644 (file)
@@ -72,7 +72,6 @@
 #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"
@@ -80,6 +79,7 @@
 #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"
@@ -132,7 +132,7 @@ public:
     //! 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.
@@ -431,7 +431,7 @@ bool Constraints::Impl::apply(bool               bLog,
          * 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.ePBC, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, FALSE, box);
     }
     else
     {
@@ -743,14 +743,17 @@ FlexibleConstraintTreatment flexibleConstraintTreatment(bool haveDynamicsIntegra
  * \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,
+                                                   const T*                    ilists,
+                                                   const t_iparams*            iparams,
+                                                   FlexibleConstraintTreatment flexibleConstraintTreatment)
 {
     GMX_ASSERT(flexibleConstraintTreatment == FlexibleConstraintTreatment::Include || iparams != nullptr,
                "With flexible constraint detection we need valid iparams");
@@ -775,19 +778,13 @@ static t_blocka makeAtomsToConstraintsList(int                         numAtoms,
         }
     }
 
-    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.
@@ -804,28 +801,28 @@ static t_blocka makeAtomsToConstraintsList(int                         numAtoms,
             {
                 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,
+                             const t_ilist*              ilist,
+                             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(),
                                       flexibleConstraintTreatment);
@@ -924,10 +921,10 @@ void Constraints::setConstraints(const gmx_localtop_t& top, const t_mdatoms& 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)
     {
@@ -1094,10 +1091,6 @@ Constraints::Impl::Impl(const gmx_mtop_t&     mtop_p,
 
 Constraints::Impl::~Impl()
 {
-    for (auto blocka : at2con_mt)
-    {
-        done_blocka(&blocka);
-    }
     if (bSettleErrorHasOccurred != nullptr)
     {
         sfree(bSettleErrorHasOccurred);
@@ -1118,7 +1111,7 @@ void Constraints::saveEdsamPointer(gmx_edsam* ed)
     impl_->ed = ed;
 }
 
-ArrayRef<const t_blocka> Constraints::atom2constraints_moltype() const
+ArrayRef<const ListOfLists<int>> Constraints::atom2constraints_moltype() const
 {
     return impl_->at2con_mt;
 }
index 2ddc2704d1dc35d791deaa1acbff2b225dd416ca..a6d159f92af87ce303db46f25531caa590f5b098 100644 (file)
@@ -63,7 +63,6 @@ struct gmx_mtop_t;
 struct gmx_multisim_t;
 struct gmx_wallcycle;
 struct pull_t;
-struct t_blocka;
 struct t_commrec;
 struct t_ilist;
 struct t_inputrec;
@@ -76,6 +75,8 @@ namespace gmx
 {
 template<typename T>
 class ArrayRefWithPadding;
+template<typename>
+class ListOfLists;
 
 //! Describes supported flavours of constrained updates.
 enum class ConstraintVariable : int
@@ -183,7 +184,7 @@ public:
     //! 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;
 
@@ -234,40 +235,43 @@ enum class FlexibleConstraintTreatment
 /*! \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,
+                             const t_ilist*              ilist,
+                             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);
index 7e5b320e4db61a55b24e52389e57a48a0d8b97da..10f00fa29c86380a5f343382b76596712fbe53ee 100644 (file)
 
 #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;
 
@@ -80,12 +78,11 @@ static void constr_recur(const t_blocka*                at2con,
     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])
             {
@@ -124,7 +121,7 @@ static void constr_recur(const t_blocka*                at2con,
                     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);
@@ -138,6 +135,7 @@ static void constr_recur(const t_blocka*                at2con,
              */
             if (depth + 1 < nc && *count < 1000 * nc)
             {
+                int a1;
                 if (ia[1] == at)
                 {
                     a1 = ia[2];
@@ -160,10 +158,9 @@ static real constr_r_max_moltype(const gmx_moltype_t*           molt,
                                  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)
     {
@@ -172,8 +169,9 @@ static real constr_r_max_moltype(const gmx_moltype_t*           molt,
 
     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;
@@ -186,7 +184,7 @@ static real constr_r_max_moltype(const gmx_moltype_t*           molt,
         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)
@@ -201,7 +199,7 @@ static real constr_r_max_moltype(const gmx_moltype_t*           molt,
             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;
@@ -217,9 +215,6 @@ static real constr_r_max_moltype(const gmx_moltype_t*           molt,
         }
     }
 
-    done_blocka(&at2con);
-    sfree(path);
-
     return rmax;
 }
 
index 7cbd9e41c7c76cc1cf368a1033193d4840fc4b8c..e436bc9d42614f2ad2bed5543efc4d561f37a17c 100644 (file)
@@ -186,17 +186,14 @@ DispersionCorrection::TopologyParams::TopologyParams(const gmx_mtop_t&         m
              */
             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);
index f2532f3dfe063cbfa5a30337ceb2ce11f3a89a42..c692c03f87f0f58e57c9a2d630b169604adb6cea 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 070b7eeb230d79abf3c5e18a0d71f3ab268a2890..898093092af71d56660432b150d836a4bbd447f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index f659874b92a704244cb4c6b0d92dc9a50f89f176..3e7c359e0326f478548ef83dc85e7523e3af3729 100644 (file)
@@ -126,7 +126,7 @@ void do_force_lowlevel(t_forcerec*                         fr,
     /* do QMMM first if requested */
     if (fr->bQMMM)
     {
-        enerd->term[F_EQM] = calculate_QMMM(cr, &forceOutputs->forceWithShiftForces(), fr);
+        enerd->term[F_EQM] = calculate_QMMM(cr, &forceOutputs->forceWithShiftForces(), fr->qr);
     }
 
     /* Call the short range functions all in one go. */
@@ -177,7 +177,7 @@ void do_force_lowlevel(t_forcerec*                         fr,
             /* 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->ePBC, DOMAINDECOMP(cr) ? cr->dd->numCells : nullptr, TRUE, box);
         }
 
         do_force_listed(wcycle, box, ir->fepvals, cr, ms, idef, x, hist, forceOutputs, fr, &pbc,
index c8a42aac5896ea3b95e02b2d792eb07133607c95..adfb6caf090e7a8d97387b39fc1585f9440f08bb 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, 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.
 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;
@@ -124,10 +125,11 @@ static real* mk_nbfp(const gmx_ffparams_t* idef, gmx_bool bBHAM)
     }
     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;
@@ -186,14 +188,10 @@ enum
     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, gmx_bool* bFEP_NonBonded)
 {
-    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++)
@@ -208,12 +206,13 @@ static cginfo_mb_t* init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr,
 
     *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.
@@ -241,11 +240,12 @@ static cginfo_mb_t* init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr,
             }
         }
 
-        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);
@@ -285,9 +285,9 @@ static cginfo_mb_t* init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr,
 
                 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;
@@ -322,14 +322,16 @@ static cginfo_mb_t* init_cginfo_mb(const gmx_mtop_t* mtop, const t_forcerec* fr,
 
         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;
 
@@ -348,19 +350,6 @@ static std::vector<int> cginfo_expand(const int nmb, const cginfo_mb_t* cgi_mb)
     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.
  */
@@ -1271,7 +1260,7 @@ void init_forcerec(FILE*                            fp,
 
     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);
@@ -1452,8 +1441,7 @@ void init_forcerec(FILE*                            fp,
     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);
     }
 
@@ -1474,67 +1462,10 @@ void init_forcerec(FILE*                            fp,
 
 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)
+t_forcerec::~t_forcerec()
 {
-    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)
-{
-    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);
 }
index e28e717b501fdd0d55f9e302fd547d3c643100dc..0c9033f84e0232910783d220d72ff72b1eecce33 100644 (file)
@@ -59,9 +59,6 @@ class MDLogger;
 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
@@ -135,8 +132,4 @@ void init_forcerec(FILE*                            fplog,
  */
 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
index 4415158d32ea7d051e16d327afa515c1b4b28934..ac4135960740aea0c45f4e8db8deb27856b2db45 100644 (file)
@@ -336,11 +336,6 @@ LeapFrogCuda::~LeapFrogCuda()
     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)
 {
     numAtoms_                       = md.nr;
index cb71267a209ff1619f4dc331a734fdf0ceb783b0..cbf3738a8f82e6270f4363b67b29acba725f4583 100644 (file)
@@ -69,15 +69,6 @@ public:
     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.
-     */
-    void setPbc(const t_pbc* pbc);
-
     /*! \brief Integrate
      *
      * Integrates the equation of motion using Leap-Frog algorithm.
@@ -125,8 +116,6 @@ private:
     CommandStream commandStream_;
     //! CUDA kernel launch config
     KernelLaunchConfig kernelLaunchConfig_;
-    //! Periodic boundary data
-    PbcAiuc pbcAiuc_;
     //! Number of atoms
     int numAtoms_;
 
index 81fce323554e08b01c229393373f636c7a131af9..9e4b18f3042a75b0523cdf356a164019d90bda87 100644 (file)
@@ -73,7 +73,6 @@
 #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"
@@ -83,6 +82,7 @@
 #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
@@ -1342,33 +1342,29 @@ static void set_lincs_matrix(Lincs* li, real* invmass, real lambda)
 }
 
 //! 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;
@@ -1377,9 +1373,8 @@ static int count_triangle_constraints(const InteractionLists& ilist, const t_blo
                 {
                     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);
@@ -1403,40 +1398,36 @@ static int count_triangle_constraints(const InteractionLists& ilist, const t_blo
 }
 
 //! 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;
@@ -1458,9 +1449,10 @@ Lincs* init_lincs(FILE*                    fplog,
     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()));
         }
     }
 
@@ -1468,11 +1460,12 @@ Lincs* init_lincs(FILE*                    fplog,
     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;
         }
@@ -1645,7 +1638,13 @@ static void lincs_thread_setup(Lincs* li, int natoms)
 }
 
 //! 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;
 
@@ -1664,8 +1663,7 @@ static void assign_constraint(Lincs* li, int constraint_index, int a1, int a2, r
     /* 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;
 
@@ -1675,13 +1673,13 @@ static void assign_constraint(Lincs* li, int constraint_index, int a1, int a2, r
 
 /*! \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,
+                                   const t_iatom*          iatom,
+                                   const t_idef&           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
@@ -1690,28 +1688,18 @@ static void check_assign_connected(Lincs*          li,
      * 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)
                 {
@@ -1725,24 +1713,21 @@ static void check_assign_connected(Lincs*          li,
 /*! \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,
+                                  const t_iatom*          iatom,
+                                  const t_idef&           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;
@@ -1764,11 +1749,8 @@ static void check_assign_triangle(Lincs*          li,
         }
     }
 
-    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;
@@ -1827,7 +1809,7 @@ static void check_assign_triangle(Lincs*          li,
 }
 
 //! 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++)
     {
@@ -1835,17 +1817,17 @@ static void set_matrix_indices(Lincs* li, const Task& li_task, const t_blocka* a
         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;
@@ -1863,7 +1845,6 @@ static void set_matrix_indices(Lincs* li, const Task& li_task, const t_blocka* a
 void set_lincs(const t_idef& 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;
@@ -1915,7 +1896,8 @@ void set_lincs(const t_idef& idef, const t_mdatoms& md, bool bDynamics, const t_
         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;
 
@@ -2018,21 +2000,21 @@ void set_lincs(const t_idef& idef, const t_mdatoms& md, bool bDynamics, const t_
                 /* 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);
                     }
                 }
             }
@@ -2096,13 +2078,11 @@ void set_lincs(const t_idef& idef, const t_mdatoms& md, bool bDynamics, const t_
                 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 */
index dfc847127e6e61847c0d08cbcb3f4115649907a0..ef43c3a5865bad17c99e917c760f80a1468c065e 100644 (file)
@@ -53,7 +53,6 @@
 
 struct gmx_mtop_t;
 struct gmx_multisim_t;
-struct t_blocka;
 struct t_commrec;
 struct t_idef;
 struct t_inputrec;
@@ -65,9 +64,10 @@ namespace gmx
 {
 
 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);
@@ -76,13 +76,13 @@ 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);
index 04d7b751b24aa9e7aaef162ef68eaf06e25db085..1a48c3bc955bc92b089c4d1ba4cfccd513948897 100644 (file)
@@ -40,8 +40,6 @@
  * 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>
@@ -435,7 +433,8 @@ void LincsCuda::apply(const float3* d_x,
                       float3*       d_v,
                       const real    invdt,
                       const bool    computeVirial,
-                      tensor        virialScaled)
+                      tensor        virialScaled,
+                      const PbcAiuc pbcAiuc)
 {
     ensureNoPendingCudaError("In CUDA version of LINCS");
 
@@ -479,6 +478,8 @@ void LincsCuda::apply(const float3* d_x,
     }
     config.stream = commandStream_;
 
+    kernelParams_.pbcAiuc = pbcAiuc;
+
     const auto kernelArgs =
             prepareGpuKernelArguments(kernelPtr, config, &kernelParams_, &d_x, &d_xp, &d_v, &invdt);
 
@@ -943,9 +944,4 @@ void LincsCuda::set(const t_idef& idef, const t_mdatoms& md)
                        GpuApiCallBehavior::Sync, nullptr);
 }
 
-void LincsCuda::setPbc(const t_pbc* pbc)
-{
-    setPbcAiuc(pbc->ndim_ePBC, pbc->box, &kernelParams_.pbcAiuc);
-}
-
 } // namespace gmx
index 06c8bb40ab0eb4abf0837c90227dd93d69a65e97..1d56e34303582d86e495efaf37d10457ead3f558 100644 (file)
@@ -113,7 +113,7 @@ public:
      * 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
@@ -125,6 +125,7 @@ public:
      *                                  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,
@@ -132,7 +133,8 @@ public:
                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).
@@ -155,17 +157,6 @@ public:
      */
     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);
-
     /*! \brief
      * Returns whether the maximum number of coupled constraints is supported
      * by the CUDA LINCS code.
index 24215b1b33d1c9803982aa804d9a7e7018eeda87..085f30201c82f5a9afd109e49156afdc08e983a4 100644 (file)
@@ -297,7 +297,7 @@ void mdoutf_write_to_trajectory_files(FILE*                    fplog,
             fflush_tng(of->tng_low_prec);
             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));
index db14315e70b945f2d25470d01f10efc57e7ada22..461a4984ab3dbfd3d3b14e1a363ea070ef9af266 100644 (file)
@@ -179,7 +179,7 @@ void get_nsgrid_boundaries(int           nboundeddim,
                 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];
@@ -238,7 +238,7 @@ static void set_grid_sizes(matrix              box,
         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;
index c93de7f1051e1d0f321699dce161a9e4a25f73a5..b2b061061fa0bd0af50130b08992fc919bdeb5cf 100644 (file)
@@ -233,7 +233,7 @@ void count_bonded_distances(const gmx_mtop_t& mtop, const t_inputrec& ir, double
         }
         if (bExcl)
         {
-            ndtot_c += molb.nmol * (molt->excls.nra - molt->atoms.nr) / 2.;
+            ndtot_c += molb.nmol * (molt->excls.numElements() - molt->atoms.nr) / 2.;
         }
     }
 
index b9885bfff340c261b5e4abe841d0b41512292731..60fb57d0f2ddfb73ec7c000fa11a366401ee1a4b 100644 (file)
@@ -52,7 +52,6 @@
 #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"
@@ -216,16 +215,11 @@ void init_gaussian(t_QMrec* qm)
 }
 
 
-static void write_gaussian_SH_input(int step, gmx_bool swap, const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
+static void write_gaussian_SH_input(int step, gmx_bool swap, const t_QMMMrec* QMMMrec, 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");
+    int   i;
+    bool  bSA = (qm->SAstep > 0);
+    FILE* out = fopen("input.com", "w");
     /* write the route */
     fprintf(out, "%s", "%scr=input\n");
     fprintf(out, "%s", "%rwf=input\n");
@@ -380,14 +374,11 @@ static void write_gaussian_SH_input(int step, gmx_bool swap, const t_forcerec* f
     fclose(out);
 } /* write_gaussian_SH_input */
 
-static void write_gaussian_input(int step, const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
+static void write_gaussian_input(int step, const t_QMMMrec* QMMMrec, t_QMrec* qm, t_MMrec* mm)
 {
-    int        i;
-    t_QMMMrec* QMMMrec;
-    FILE*      out;
+    int i;
 
-    QMMMrec = fr->qr;
-    out     = fopen("input.com", "w");
+    FILE* out = fopen("input.com", "w");
     /* write the route */
 
     if (qm->QMmethod >= eQMmethodRHF)
@@ -758,7 +749,7 @@ static void do_gaussian(int step, char* exe)
     }
 }
 
-real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
+real call_gaussian(const t_QMMMrec* qmmm, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
 {
     /* normal gaussian jobs */
     static int step = 0;
@@ -772,7 +763,7 @@ real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rve
     snew(QMgrad, qm->nrQMatoms);
     snew(MMgrad, mm->nrMMatoms);
 
-    write_gaussian_input(step, fr, qm, mm);
+    write_gaussian_input(step, qmmm, 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
@@ -800,7 +791,7 @@ real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rve
 
 } /* call_gaussian */
 
-real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
+real call_gaussian_SH(const t_QMMMrec* qmmm, 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
@@ -845,7 +836,7 @@ real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[],
     /*  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);
+    write_gaussian_SH_input(step, swapped, qmmm, qm, mm);
 
     do_gaussian(step, exe);
     QMener = read_gaussian_SH_output(QMgrad, MMgrad, step, qm, mm);
@@ -867,7 +858,7 @@ real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[],
         }
         if (swap) /* change surface, so do another call */
         {
-            write_gaussian_SH_input(step, swapped, fr, qm, mm);
+            write_gaussian_SH_input(step, swapped, qmmm, qm, mm);
             do_gaussian(step, exe);
             QMener = read_gaussian_SH_output(QMgrad, MMgrad, step, qm, mm);
         }
index 1933fc7893c39d628e4ef264da49f30fc8063a54..9c3088413232c801a9420865f64fd12635312ee3 100644 (file)
@@ -50,23 +50,23 @@ void init_gaussian(t_QMrec* qm);
 /*! \brief
  * Call gaussian to do qm calculation.
  *
- * \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] qmmm   QMMM part 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.
  */
-real call_gaussian(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+real call_gaussian(const t_QMMMrec* qmmm, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
 
 /*! \brief
  * Call gaussian SH(?) to do qm calculation.
  *
- * \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] qmmm   QMMM part 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.
  */
-real call_gaussian_SH(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+real call_gaussian_SH(const t_QMMMrec* qmmm, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
 
 #endif
index 075d8d68340f8e5f296ddb22f31a0fbde91430be..1bd0cca0738566ae0d625a27866189e5d29e3e0e 100644 (file)
@@ -51,7 +51,6 @@
 #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"
@@ -110,19 +109,16 @@ void init_orca(t_QMrec* qm)
 }
 
 
-static void write_orca_input(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
+static void write_orca_input(const t_QMMMrec* QMMMrec, t_QMrec* qm, t_MMrec* mm)
 {
-    int        i;
-    t_QMMMrec* QMMMrec;
-    FILE *     out, *pcFile, *addInputFile;
-    char *     buf, *orcaInput, *addInputFilename, *pcFilename;
-
-    QMMMrec = fr->qr;
+    int   i;
+    FILE *pcFile, *addInputFile;
+    char *buf, *orcaInput, *addInputFilename, *pcFilename;
 
     /* write the first part of the input-file */
     snew(orcaInput, 200);
     sprintf(orcaInput, "%s.inp", qm->orca_basename);
-    out = fopen(orcaInput, "w");
+    FILE* out = fopen(orcaInput, "w");
 
     snew(addInputFilename, 200);
     sprintf(addInputFilename, "%s.ORCAINFO", qm->orca_basename);
@@ -193,15 +189,13 @@ static void write_orca_input(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
     fclose(out);
 } /* write_orca_input */
 
-static real read_orca_output(rvec QMgrad[], rvec MMgrad[], const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm)
+static real read_orca_output(rvec QMgrad[], rvec MMgrad[], const t_QMMMrec* QMMMrec, 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;
+    int   i, j;
+    char  buf[300], orca_pcgradFilename[300], orca_engradFilename[300];
+    real  QMener;
+    FILE *pcgrad, *engrad;
+    int   k;
 
     /* 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.
@@ -328,7 +322,7 @@ static void do_orca(char* orca_dir, char* basename)
     }
 }
 
-real call_orca(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
+real call_orca(const t_QMMMrec* qmmm, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[])
 {
     /* normal orca jobs */
     static int step = 0;
@@ -342,9 +336,9 @@ real call_orca(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fs
     snew(QMgrad, qm->nrQMatoms);
     snew(MMgrad, mm->nrMMatoms);
 
-    write_orca_input(fr, qm, mm);
+    write_orca_input(qmmm, qm, mm);
     do_orca(qm->orca_dir, qm->orca_basename);
-    QMener = read_orca_output(QMgrad, MMgrad, fr, qm, mm);
+    QMener = read_orca_output(QMgrad, MMgrad, qmmm, qm, mm);
     /* put the QMMM forces in the force array and to the fshift
      */
     for (i = 0; i < qm->nrQMatoms; i++)
index cf89d941c8fc907e3d15d3331147fc9172253487..c6a3b55917bb8e9038bf5d8838b21440b4cca37d 100644 (file)
@@ -39,6 +39,6 @@
 
 void init_orca(t_QMrec* qm);
 
-real call_orca(const t_forcerec* fr, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
+real call_orca(const t_QMMMrec* qmmm, t_QMrec* qm, t_MMrec* mm, rvec f[], rvec fshift[]);
 
 #endif
index 2482bf592712f7d86d2c09f694cbc7ddfbea4dab..078afe88cf21a603fbaac3850e6c4037b7fd42a3 100644 (file)
@@ -95,7 +95,7 @@ static bool struct_comp(const t_j_particle& a, const t_j_particle& b)
 }
 
 static real call_QMroutine(const t_commrec gmx_unused* cr,
-                           const t_forcerec gmx_unused* fr,
+                           const t_QMMMrec gmx_unused* qmmm,
                            t_QMrec gmx_unused* qm,
                            t_MMrec gmx_unused* mm,
                            rvec gmx_unused f[],
@@ -131,7 +131,7 @@ static real call_QMroutine(const t_commrec gmx_unused* cr,
         {
             if (GMX_QMMM_GAUSSIAN)
             {
-                return call_gaussian_SH(fr, qm, mm, f, fshift);
+                return call_gaussian_SH(qmmm, qm, mm, f, fshift);
             }
             else
             {
@@ -146,11 +146,11 @@ static real call_QMroutine(const t_commrec gmx_unused* cr,
             }
             else if (GMX_QMMM_GAUSSIAN)
             {
-                return call_gaussian(fr, qm, mm, f, fshift);
+                return call_gaussian(qmmm, qm, mm, f, fshift);
             }
             else if (GMX_QMMM_ORCA)
             {
-                return call_orca(fr, qm, mm, f, fshift);
+                return call_orca(qmmm, qm, mm, f, fshift);
             }
             else
             {
@@ -614,7 +614,7 @@ void update_QMMMrec(const t_commrec* cr, const t_forcerec* fr, const rvec* x, co
     /*  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);
+    set_pbc_dd(&pbc, fr->ePBC, DOMAINDECOMP(cr) ? cr->dd->numCells : 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.
@@ -827,17 +827,16 @@ void update_QMMMrec(const t_commrec* cr, const t_forcerec* fr, const rvec* x, co
     }
 } /* update_QMMM_rec */
 
-real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShiftForces, const t_forcerec* fr)
+real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShiftForces, const t_QMMMrec* qr)
 {
     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,
+    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;
 
@@ -848,7 +847,6 @@ real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShi
 
     /* make a local copy the QMMMrec pointer
      */
-    qr = fr->qr;
     mm = qr->mm;
 
     /* now different procedures are carried out for one layer ONION and
@@ -861,7 +859,7 @@ real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShi
         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);
+        QMener = call_QMroutine(cr, qr, qm, mm, forces, fshift);
         for (i = 0; i < qm->nrQMatoms; i++)
         {
             for (j = 0; j < DIM; j++)
@@ -907,13 +905,13 @@ real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShi
             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);
+            QMener += call_QMroutine(cr, qr, 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);
+            QMener -= call_QMroutine(cr, qr, 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
@@ -933,7 +931,7 @@ real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShi
         init_QMroutine(cr, qm, mm);
         srenew(forces, qm->nrQMatoms);
         srenew(fshift, qm->nrQMatoms);
-        QMener += call_QMroutine(cr, fr, qm, mm, forces, fshift);
+        QMener += call_QMroutine(cr, qr, qm, mm, forces, fshift);
         for (i = 0; i < qm->nrQMatoms; i++)
         {
             for (j = 0; j < DIM; j++)
index 8172e9766007e9b1f51e3c48f455e8dbc4a0facd..8de4084926469fa39c73dde1186c99d88bfce919 100644 (file)
@@ -139,7 +139,7 @@ void update_QMMMrec(const t_commrec* cr, const t_forcerec* fr, const rvec* x, co
  * 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);
+real calculate_QMMM(const t_commrec* cr, gmx::ForceWithShiftForces* forceWithShiftForces, const t_QMMMrec* qmmm);
 
 /* QMMM computes the QM forces. This routine makes either function
  * calls to gmx QM routines (derived from MOPAC7 (semi-emp.) and MPQC
index d09bc9bf7a4dab51846f365ff503552ec13af1bd..7a4113399999520f24bba256acfe7fc0d4dd001a 100644 (file)
@@ -40,8 +40,6 @@
  * 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>
@@ -89,10 +87,10 @@ constexpr static int c_maxThreadsPerBlock = c_threadsPerBlock;
  * \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__
@@ -101,10 +99,10 @@ __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)
 {
     /* ******************************************************************* */
     /*                                                                  ** */
@@ -421,7 +419,8 @@ void SettleCuda::apply(const float3* d_x,
                        float3*       d_v,
                        const real    invdt,
                        const bool    computeVirial,
-                       tensor        virialScaled)
+                       tensor        virialScaled,
+                       const PbcAiuc pbcAiuc)
 {
 
     ensureNoPendingCudaError("In CUDA version SETTLE");
@@ -460,8 +459,8 @@ void SettleCuda::apply(const float3* d_x,
     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);
 
@@ -627,9 +626,4 @@ void SettleCuda::set(const t_idef& idef, const t_mdatoms gmx_unused& md)
                        GpuApiCallBehavior::Sync, nullptr);
 }
 
-void SettleCuda::setPbc(const t_pbc* pbc)
-{
-    setPbcAiuc(pbc->ndim_ePBC, pbc->box, &pbcAiuc_);
-}
-
 } // namespace gmx
index caef2dbedcdba5e539c697da2821ffd4719e0b8f..ca666156125064c9782f4d12c818575856557b66 100644 (file)
@@ -222,6 +222,7 @@ public:
      *                                  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,
@@ -229,7 +230,8 @@ public:
                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).
@@ -246,23 +248,9 @@ public:
      */
     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);
-
-
 private:
     //! CUDA stream
     CommandStream commandStream_;
-    //! Periodic boundary data
-    PbcAiuc pbcAiuc_;
 
     //! Scaled virial tensor (9 reals, GPU)
     std::vector<float> h_virialScaled_;
index c8d3cbb713cf504460c7342a1e563f59e24ac7fa..938e774d5d85a65cd365b78d3ffbc2d2eb7d925f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, 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.
@@ -843,7 +843,7 @@ static StepWorkload setupStepWorkload(const int                 legacyFlags,
 
 /* \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,
@@ -851,12 +851,11 @@ 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
@@ -875,7 +874,7 @@ static void launchGpuEndOfStepTasks(nonbonded_verlet_t*               nbv,
         wallcycle_stop(wcycle, ewcLAUNCH_GPU);
     }
 
-    if (useGpuPme)
+    if (useGpuPmeOnThisRank)
     {
         pme_gpu_reinit_computation(pmedata, wcycle);
     }
@@ -1167,10 +1166,7 @@ void do_force(FILE*                               fplog,
             }
             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(
@@ -1179,7 +1175,7 @@ void do_force(FILE*                               fplog,
         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);
 
@@ -1272,7 +1268,7 @@ void do_force(FILE*                               fplog,
             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);
@@ -1774,7 +1770,7 @@ void do_force(FILE*                               fplog,
     }
 
     launchGpuEndOfStepTasks(nbv, fr->gpuBonded, fr->pmedata, enerd, *runScheduleWork,
-                            simulationWork.useGpuNonbonded, useGpuPmeOnThisRank, step, wcycle);
+                            useGpuPmeOnThisRank, step, wcycle);
 
     if (DOMAINDECOMP(cr))
     {
index 710e9ac48c1b83ba40293f68dfb41ca9fba3bf4b..ffd8f99e684670ee6dd6b10897cc8735864c1d36 100644 (file)
 #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"
@@ -115,7 +115,7 @@ void applyLincs(ConstraintsTestData* testData, t_pbc pbc)
     gmx_omp_nthreads_set(emntLINCS, 1);
 
     // 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)
     {
@@ -138,11 +138,6 @@ void applyLincs(ConstraintsTestData* testData, t_pbc pbc)
             &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);
 }
 
index c62e67e94b151065af69960c42d3595613a542e1..43c7edca6a5f5c70da27ad6ec94b520306d05ccb 100644 (file)
@@ -78,7 +78,8 @@ void applyLincsCuda(ConstraintsTestData* testData, t_pbc pbc)
     float3 *d_x, *d_xp, *d_v;
 
     lincsCuda->set(testData->idef_, testData->md_);
-    lincsCuda->setPbc(&pbc);
+    PbcAiuc pbcAiuc;
+    setPbcAiuc(pbc.ndim_ePBC, pbc.box, &pbcAiuc);
 
     allocateDeviceBuffer(&d_x, numAtoms, nullptr);
     allocateDeviceBuffer(&d_xp, numAtoms, nullptr);
@@ -94,7 +95,7 @@ void applyLincsCuda(ConstraintsTestData* testData, t_pbc pbc)
                            GpuApiCallBehavior::Sync, nullptr);
     }
     lincsCuda->apply(d_x, d_xp, updateVelocities, d_v, testData->invdt_, testData->computeVirial_,
-                     testData->virialScaled_);
+                     testData->virialScaled_, pbcAiuc);
 
     copyFromDeviceBuffer((float3*)(testData->xPrime_.data()), &d_xp, 0, numAtoms, nullptr,
                          GpuApiCallBehavior::Sync, nullptr);
index dae26029590b2056f3f0aa21573f8dce4752469b..06f2bf73280810331d6841ebc9402b34ffe1f74e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 8feab2e0a02b2249dce77ffefc02049c309e24c3..4cea8e864a3ca4b036a3f802d4805563bea9310d 100644 (file)
@@ -139,8 +139,7 @@ SettleTestData::SettleTestData(int numSettles) :
     }
 
     // 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 };
+    ilist_ = { mtop_.moltype[0].ilist[F_SETTLE].size(), mtop_.moltype[0].ilist[F_SETTLE].iatoms.data(), 0 };
     idef_.il[F_SETTLE] = ilist_;
 }
 
index e75466af86ac5b247a502df0e12d4bbf726e8199..b8823389902be63c177b4ce2c5b9a1bd0d72fe8f 100644 (file)
@@ -87,8 +87,10 @@ void applySettleGpu(SettleTestData*  testData,
     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_);
+    PbcAiuc pbcAiuc;
+    setPbcAiuc(pbc.ndim_ePBC, pbc.box, &pbcAiuc);
 
     int numAtoms = testData->mdatoms_.homenr;
 
@@ -109,7 +111,7 @@ void applySettleGpu(SettleTestData*  testData,
         copyToDeviceBuffer(&d_v, (float3*)h_v, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
     }
     settleCuda->apply(d_x, d_xp, updateVelocities, d_v, testData->reciprocalTimeStep_, calcVirial,
-                      testData->virial_);
+                      testData->virial_, pbcAiuc);
 
     copyFromDeviceBuffer((float3*)h_xp, &d_xp, 0, numAtoms, nullptr, GpuApiCallBehavior::Sync, nullptr);
     if (updateVelocities)
index e06b416a0a1ad0837fab92262a5e8a66619b8a0c..9cca0c87f184bf5ceb5e81b7b70740ec72206cf4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index c11a74ad819ba0a58154f6f513723184bf75ee01..f682e011f7fce8cb09ae8fbf01746d3ac57f74bc 100644 (file)
@@ -127,8 +127,8 @@ void UpdateConstrainCuda::Impl::integrate(GpuEventSynchronizer*             fRea
     // 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);
+    lincsCuda_->apply(d_xp_, d_x_, updateVelocities, d_v_, 1.0 / dt, computeVirial, virial, pbcAiuc_);
+    settleCuda_->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);
@@ -222,9 +222,6 @@ void UpdateConstrainCuda::Impl::set(DeviceBuffer<float>       d_x,
 void UpdateConstrainCuda::Impl::setPbc(const t_pbc* pbc)
 {
     setPbcAiuc(pbc->ndim_ePBC, pbc->box, &pbcAiuc_);
-    integrator_->setPbc(pbc);
-    lincsCuda_->setPbc(pbc);
-    settleCuda_->setPbc(pbc);
 }
 
 GpuEventSynchronizer* UpdateConstrainCuda::Impl::getCoordinatesReadySync()
index 5ee169a4737271a94532bc99e41145d21ed2b87d..3aa3feb3592f1078c182d85970d16dc820857799 100644 (file)
 #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
 {
@@ -196,15 +196,17 @@ static AtomIndexExtremes vsiteConstructRange(int a, const gmx_moltype_t& moltype
 }
 
 /*! \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);
         }
@@ -231,10 +233,10 @@ static std::vector<bool> buildIsParticleVsite(const gmx_moltype_t& moltype)
 }
 
 /*! \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,
@@ -243,7 +245,7 @@ static int detectGroup(int                    firstAtom,
     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;
     }
@@ -274,7 +276,7 @@ static int detectGroup(int                    firstAtom,
         }
         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 */
@@ -356,8 +358,8 @@ static RangePartitioning makeUpdateGroups(const gmx_moltype_t& moltype, gmx::Arr
     ilistsCombined[F_CONSTR].iatoms = constraintsCombined.iatoms.data();
     ilistsCombined[F_CONSTRNC].nr   = 0;
     /* 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.data(),
+                                                FlexibleConstraintTreatment::Include);
 
     bool satisfiesCriteria = true;
 
@@ -383,8 +385,6 @@ static RangePartitioning makeUpdateGroups(const gmx_moltype_t& moltype, gmx::Arr
         groups.clear();
     }
 
-    done_blocka(&at2con);
-
     return groups;
 }
 
@@ -441,19 +441,19 @@ template<int numPartnerAtoms>
 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 */
@@ -597,7 +597,7 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           moltype,
 
     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);
 
@@ -615,7 +615,7 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           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;
@@ -633,9 +633,10 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           moltype,
         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())
             {
@@ -646,9 +647,10 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           moltype,
                 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)
             {
@@ -664,7 +666,7 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           moltype,
             sumConstraintLengths += constraintLength;
         }
 
-        int  numConstraints = at2con.index[maxAtom + 1] - at2con.index[maxAtom];
+        int  numConstraints = at2con[maxAtom].ssize();
         real radius;
         if (numConstraints == 1)
         {
@@ -721,8 +723,6 @@ static real computeMaxUpdateGroupRadius(const gmx_moltype_t&           moltype,
         maxRadius        = std::max(maxRadius, dCAny);
     }
 
-    done_blocka(&at2con);
-
     return maxRadius;
 }
 
index 4a0fe17a00e9e3ad1e9945044ff596d533ddb5c9..152567de68ccfdf054ff995edeb5bc925cbfbe88 100644 (file)
@@ -641,7 +641,7 @@ void construct_vsites(const gmx_vsite_t* vsite,
          */
         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, ePBC, useDomdec ? cr->dd->numCells : null_ivec, FALSE, box);
     }
     else
     {
@@ -1748,7 +1748,7 @@ void spread_vsite_f(const gmx_vsite_t* vsite,
         /* 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, ePBC, useDomdec ? cr->dd->numCells : nullptr, FALSE, box);
     }
     else
     {
index d03f55344c6d58cee867920516f3740ae0e81267..aab096a6f45204a63bae9397e3ee57d88462f45b 100644 (file)
@@ -176,7 +176,7 @@ real do_walls(const t_inputrec&     ir,
     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++)
index 8505f8649d6695c82ed79a346fd5c1dcff28a887..99421cbd9a3249b76d47c17c3a57a390633f83d0 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011-2019, by the GROMACS development team, led by
+ * Copyright (c) 2011-2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 65e08ed342ff599994757e921ca3fa48b444af14..6c2e4e7ba57a1fcdb9f9fc381b449122cbd2ea24 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index e20b7e88b0fe19231ebcf91463edf43948042efc..8afbb528fbe86235fa88ea7e1dc45bc52bdc194f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index c75be98e38a590a0db99618a84eee49ff4e1b3d7..bbf7655135be424db65a9dbc3c233ab01dc5e7f2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index f5b9cb1b7ab66d47a762e7f311f315a601023ae5..95a95f5c24decd92f1de1f8df98417ca5ec6c3a6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011-2019, by the GROMACS development team, led by
+ * Copyright (c) 2011-2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -1550,7 +1550,7 @@ int Mdrunner::mdrunner()
             /* 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);
         }
 
@@ -1650,18 +1650,45 @@ int Mdrunner::mdrunner()
     }
 
     // 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
+    /* 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());
     sfree(fcd);
 
     if (doMembed)
index 2ed8bd4586eb53126c8881264dbea9f9eb3ce17c..1c9066c7be0929d416054a47021176c1e0e3e177 100644 (file)
@@ -666,7 +666,7 @@ void LegacySimulator::do_tpi()
                 /* 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;
             }
index 72291ff816680b7353b42d10b177bcd19308edd9..524b76395f399e4ce0dae5dee3e93b98018e85ec 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 2b0832a80a7503dc61bfd10ef2488bd63022ddbd..05bcab152e7729ab6abf4ac48e19d4cd8c72359c 100644 (file)
@@ -110,10 +110,10 @@ enum
 
 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;
 };
 
 
@@ -192,7 +192,7 @@ struct t_forcerec
     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;
 
@@ -234,10 +234,10 @@ struct t_forcerec
     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;
index 697f9d2c861053326f139df573bd4d39c273570e..44cbc8d7e53887f0aa75abc272dbbe15bcb2f589 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 1e2eadaff463886f9b683890f6993c07d3b5dd71..ae6bcd6c71eef3d217c1c46e46c79604d7078caf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 9ac9711d298862052e1cc3c138f93ba8ea3a292c..142327772274c4c29db5b922a43b18569868fecc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 29821a43133ddaacd8078a7c2ae2596c95aa2037..031327e80d844b1917b4c65c5317e95aac721b56 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
@@ -257,8 +257,12 @@ void StatePropagatorDataGpu::Impl::copyToDevice(DeviceBuffer<float>
 {
     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(commandStream != nullptr,
+               "No stream is valid for copying with given atom locality.");
     wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
     wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
 
@@ -291,8 +295,12 @@ void StatePropagatorDataGpu::Impl::copyFromDevice(gmx::ArrayRef<gmx::RVec> h_dat
 {
     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(commandStream != nullptr,
+               "No stream is valid for copying with given atom locality.");
     wallcycle_start_nocount(wcycle_, ewcLAUNCH_GPU);
     wallcycle_sub_start(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
 
@@ -341,7 +349,7 @@ void StatePropagatorDataGpu::Impl::copyCoordinatesToGpu(const gmx::ArrayRef<cons
     // 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(xCopyStreams_[atomLocality]);
     }
 
     wallcycle_sub_stop(wcycle_, ewcsLAUNCH_STATE_PROPAGATOR_DATA);
index 7e8a8199c39a862fb39cfb2cbf26f3f98a8cfdd7..bf6935b20c31daa2ad17b8c4aadfb077a0717a0a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index dc8fc3e4930b5b13e246f01e9ae6dc388030e421..7ae50a611661c0b50cadc54bb321614130112c03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index c785f5d3dddf88ab0be79ab9679b576bdc143712..b116f29b2cfc8029a035dd396ea493017ec4fa03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 6d4986d2dd9137f97ed21b9fd6fe8a9fc0d34a54..de1e152718d425fe24c408291018af4c7908c2d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 54df4768d77a2b295dd5116f4a2ee60f10ab1130..11f9212f7cf5b905561e99056e5ab4dc67afe48e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 17b8eb47cb30ccf1cdafda2a07c38fa3ea9c9097..c0ed27be688ca93c6e298b743f84ac6291224b6a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index d6a7fac8d385700b3e20373b05a8d8187b1e8a77..71a3d269f30799543d668331aa77564c77dcc920 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index c4a15ba97481dd5a79421b220172412c47bd296e..07684c90092d0db2957748c738695f5e1252490c 100644 (file)
@@ -442,7 +442,7 @@ static void nbnxn_atomdata_params_init(const gmx::MDLogger&      mdlog,
                                        const Nbnxm::KernelType   kernelType,
                                        int                       enbnxninitcombrule,
                                        int                       ntype,
-                                       const real*               nbfp,
+                                       ArrayRef<const real>      nbfp,
                                        int                       n_energygroups)
 {
     real     c6, c12, tol;
@@ -625,7 +625,7 @@ void nbnxn_atomdata_init(const gmx::MDLogger&    mdlog,
                          const Nbnxm::KernelType kernelType,
                          int                     enbnxninitcombrule,
                          int                     ntype,
-                         const real*             nbfp,
+                         ArrayRef<const real>    nbfp,
                          int                     n_energygroups,
                          int                     nout)
 {
index 1b1e3b763a17f9c23b09007c27a5233e835b6750..6f4e11561ca0131bc31756e7b2f289bac310facc 100644 (file)
@@ -288,14 +288,14 @@ enum
  * 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);
 
 void nbnxn_atomdata_set(nbnxn_atomdata_t*     nbat,
                         const Nbnxm::GridSet& gridSet,
index ecfe6af14de3ee1e349ed0f3d2d3a0679f376120..c2c2328f66508dda20d36da78c8cfa96777c1e63 100644 (file)
@@ -199,7 +199,7 @@ static std::unique_ptr<nonbonded_verlet_t> setupNbnxmForBenchInstance(const Kern
                                                     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;
 
@@ -223,7 +223,7 @@ static std::unique_ptr<nonbonded_verlet_t> setupNbnxmForBenchInstance(const Kern
                       { 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
index ffe0a899ff9b7e820f95ac5b1652561c421c447f..bf2768b4146da30b8670dae73867d2f78a50a991 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "bench_system.h"
 
+#include <numeric>
 #include <vector>
 
 #include "gromacs/math/vec.h"
@@ -167,9 +168,6 @@ BenchmarkSystem::BenchmarkSystem(const int multiplicationFactor)
     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++)
     {
@@ -191,16 +189,14 @@ BenchmarkSystem::BenchmarkSystem(const int multiplicationFactor)
         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);
 }
index 512368ddda507fe8937ab58d4e797a08d813553a..adcc85d4ffacc443b36b48dc8040e09ffa2fb1aa 100644 (file)
@@ -48,7 +48,7 @@
 
 #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
@@ -80,7 +80,7 @@ struct BenchmarkSystem
     //! 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.
index 53bd7541efddd79f6758ee27091f9dcf45374021..efb713c093b8f1c414b70867594fe11d20e90401 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index acf3717d8eba6746aa389cc392cdd111f9a82b84..2bec5d520b9c66f82e39e7bc90775650505f5060 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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-2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 1548f3704ff9c74b83d01b82d29a29ce1e2a1cd4..cb5da28eede392e4da2e658a7c4fbab6eeba48ff 100644 (file)
@@ -133,7 +133,6 @@ struct interaction_const_t;
 struct nonbonded_verlet_t;
 class PairSearch;
 class PairlistSets;
-struct t_blocka;
 struct t_commrec;
 struct t_lambda;
 struct t_mdatoms;
@@ -153,6 +152,8 @@ class GpuEventSynchronizer;
 namespace gmx
 {
 class ForceWithShiftForces;
+template<typename>
+class ListOfLists;
 class MDLogger;
 class UpdateGroupsCog;
 } // namespace gmx
@@ -251,7 +252,10 @@ public:
     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);
+    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);
index 89a34776391caa3f252bb9100e5cdd2524c7ea80..686179accd91db4e7399a735afc04febf3499792 100644 (file)
@@ -456,7 +456,7 @@ std::unique_ptr<nonbonded_verlet_t> init_nb_verlet(const gmx::MDLogger&     mdlo
                                                        minimumIlistCountForGpuBalancing);
 
     auto pairSearch = std::make_unique<PairSearch>(
-            ir->ePBC, EI_TPI(ir->eI), DOMAINDECOMP(cr) ? &cr->dd->nc : nullptr,
+            ir->ePBC, 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);
 
index 6174905d578fffe2f68497beee7ea8e84cf12139..f5efbef63864fe3af81188c9637cc4fd93d4b1e4 100644 (file)
 #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"
@@ -1363,12 +1363,12 @@ static nbnxn_sci_t* getOpenIEntry(NbnxnPairlistGpu* nbl)
  * 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)
     {
@@ -1391,11 +1391,8 @@ static void setExclusionsForIEntry(const Nbnxm::GridSet& gridSet,
         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 */
@@ -1876,9 +1873,9 @@ static void make_fep_list(gmx::ArrayRef<const int> atomIndices,
 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)
     {
@@ -1912,11 +1909,8 @@ static void setExclusionsForIEntry(const Nbnxm::GridSet& gridSet,
             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 */
@@ -3083,7 +3077,7 @@ static void nbnxn_make_pairlist_part(const Nbnxm::GridSet&   gridSet,
                                      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,
@@ -3924,7 +3918,7 @@ static void prepareListsForDynamicPruning(gmx::ArrayRef<NbnxnPairlistCpu> lists)
 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)
@@ -4037,14 +4031,14 @@ void PairlistSet::constructPairlists(const Nbnxm::GridSet&         gridSet,
                     /* 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);
@@ -4202,12 +4196,12 @@ void PairlistSet::constructPairlists(const Nbnxm::GridSet&         gridSet,
 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,
-                                              minimumIlistCountForGpuBalancing_, nrnb,
+    pairlistSet(iLocality).constructPairlists(pairSearch->gridSet(), pairSearch->work(), nbat,
+                                              exclusions, minimumIlistCountForGpuBalancing_, nrnb,
                                               &pairSearch->cycleCounting_);
 
     if (iLocality == InteractionLocality::Local)
@@ -4234,11 +4228,11 @@ void PairlistSets::construct(const InteractionLocality iLocality,
 }
 
 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())
     {
index d0e930330c54202269dabe7b4878d6dc9332f38c..1133846a6bccdcf774b632c5af7be9742cae762c 100644 (file)
@@ -62,9 +62,14 @@ struct nbnxn_atomdata_t;
 struct PairlistParams;
 struct PairsearchWork;
 struct SearchCycleCounting;
-struct t_blocka;
 struct t_nrnb;
 
+namespace gmx
+{
+template<typename>
+class ListOfLists;
+}
+
 namespace Nbnxm
 {
 class GridSet;
@@ -85,7 +90,7 @@ public:
     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);
index 2349159a1dd328df5537ebe8166a395f0490eff9..960f5f96791dbf4e2a529672a28b1b779f6524a9 100644 (file)
@@ -57,9 +57,13 @@ struct nbnxn_atomdata_t;
 class PairlistSet;
 enum class PairlistType;
 class PairSearch;
-struct t_blocka;
 struct t_nrnb;
 
+namespace gmx
+{
+template<typename>
+class ListOfLists;
+}
 
 class PairlistSets
 {
@@ -69,12 +73,12 @@ public:
                  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,
index a93cda1ea6d0638ce7dbf72242bfaf052dc80b5f..b70211fbcd0d59abca5966dc378fa5a02e31de22 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index de6ec28f5abcc90d666f2036f18afabfc727392c..c9e304e19bdbda8a34f669203e293700a8fc75b7 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index ddc8bd67d341b1dee67fb8009a6f21076bf6ed13..08d8f6cc7b0d028933598d4c3ec8577aba4ca374 100644 (file)
 #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"
 
@@ -137,7 +137,7 @@ public:
      */
     void                  init(AnalysisNeighborhood::SearchMode     mode,
                                bool                                 bXY,
-                               const t_blocka*                      excls,
+                               const ListOfLists<int>*              excls,
                                const t_pbc*                         pbc,
                                const AnalysisNeighborhoodPositions& positions);
     PairSearchImplPointer getPairSearch();
@@ -280,7 +280,7 @@ private:
     //! Reference position indices (NULL if no indices).
     const int* refIndices_;
     //! Exclusions.
-    const t_blocka* excls_;
+    const ListOfLists<int>* excls_;
     //! PBC data.
     t_pbc pbc_;
 
@@ -337,8 +337,6 @@ public:
         testPositions_    = nullptr;
         testExclusionIds_ = nullptr;
         testIndices_      = nullptr;
-        nexcl_            = 0;
-        excl_             = nullptr;
         clear_rvec(xtest_);
         clear_rvec(testcell_);
         clear_ivec(currCell_);
@@ -376,10 +374,8 @@ private:
     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.
@@ -862,7 +858,7 @@ int AnalysisNeighborhoodSearchImpl::shiftCell(const ivec cell, rvec shift) const
 
 void AnalysisNeighborhoodSearchImpl::init(AnalysisNeighborhood::SearchMode     mode,
                                           bool                                 bXY,
-                                          const t_blocka*                      excls,
+                                          const ListOfLists<int>*              excls,
                                           const t_pbc*                         pbc,
                                           const AnalysisNeighborhoodPositions& positions)
 {
@@ -988,16 +984,13 @@ void AnalysisNeighborhoodPairSearchImpl::reset(int testIndex)
         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>();
             }
         }
     }
@@ -1014,15 +1007,16 @@ void AnalysisNeighborhoodPairSearchImpl::nextTestPosition()
 
 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;
@@ -1258,12 +1252,12 @@ public:
 
     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()
@@ -1304,7 +1298,7 @@ void AnalysisNeighborhood::setXYMode(bool bXY)
     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");
index ffe93854b644f4ddba04e4a2a41c4ac90f37f7ba..7066cafd12d14bedad6061bdf7e26e821a58c8ff 100644 (file)
 #include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/real.h"
 
-struct t_blocka;
 struct t_pbc;
 
 namespace gmx
 {
+template<typename>
+class ListOfLists;
 
 namespace internal
 {
@@ -282,7 +283,7 @@ public:
      *
      * \see AnalysisNeighborhoodPositions::exclusionIds()
      */
-    void setTopologyExclusions(const t_blocka* excls);
+    void setTopologyExclusions(const ListOfLists<int>* excls);
     /*! \brief
      * Sets the algorithm to use for searching.
      *
index 7e85995a1dda77e71e6e2e62fd10a1b9812eef4b..e32d8495099ab248196ae3c4336f016710f0e00b 100644 (file)
@@ -64,6 +64,7 @@
 #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"
 
@@ -309,13 +310,13 @@ void NeighborhoodSearchTestData::computeReferencesInternal(t_pbc* pbc, bool bXY)
 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
     {
@@ -327,21 +328,18 @@ public:
     }
 
 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);
@@ -364,13 +362,6 @@ ExclusionsHelper::ExclusionsHelper(int refPosCount, int testPosCount) :
     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()
@@ -379,21 +370,15 @@ 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();
 }
 
 /********************************************************************
@@ -414,7 +399,7 @@ public:
     void 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);
@@ -522,7 +507,7 @@ void NeighborhoodSearchTest::testPairSearchIndexed(gmx::AnalysisNeighborhood*
 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)
index 9b069fd890a44c139a700fe8bc9a00001855848a..bfd43291b253cb55c63ad9c10c65d26064b208ff 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 45ba2d333f43312593fdec38641d882d5532319e..573cac02cfcbf742df5015b9a403c6913643f275 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 7be59377af786604e39edc8bbe56256d1e44d90a..648a7b68eb5822498f38efa293886120f7984759 100644 (file)
@@ -71,17 +71,17 @@ typedef unsigned long long     gmx_cycles_t;
 
 #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 */
@@ -94,11 +94,11 @@ typedef unsigned long          gmx_cycles_t;
 #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 */
@@ -111,7 +111,7 @@ typedef unsigned long          gmx_cycles_t;
 #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 */
@@ -119,7 +119,7 @@ typedef unsigned long long   gmx_cycles_t;
 
 #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 */
@@ -130,7 +130,7 @@ typedef unsigned long long gmx_cycles_t;
 #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 */
@@ -138,7 +138,7 @@ typedef unsigned long long     gmx_cycles_t;
 
 #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
@@ -173,13 +173,8 @@ typedef long gmx_cycles_t;
  *  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 */
@@ -407,14 +402,9 @@ static gmx_cycles_t gmx_cycles_read(void)
  *       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 */
index 638b8dc475e7da59a742f77479e202089109fdb0..9c5ff6e63a14e61b42dc3371e0874d083b7a6da1 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2018,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index c2d5bc8bf51798a5dc8514c85377b5d12ac8cbd9..85bd5b59d573d5ee68487be35c26a7295ab97d4b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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,2019,2020, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
index 09adddc79534ef0660d78c4fd3eda462db9ff7cb..905b3443cb003cd59d9283724f4b3fafc71b4a41 100644 (file)
               "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;
@@ -99,69 +95,34 @@ static int* invind(int gnx, int natoms, int index[])
     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;
-
-    snew(index, block->nr);
+    gmx::ListOfLists<int> lists;
 
-    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[])
@@ -220,7 +181,11 @@ static void reduce_atom(int gnx, const int index[], t_atom atom[], char*** atomn
     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,
+                         t_ilist*                 il,
+                         int                      nratoms,
+                         const char*              name)
 {
     t_iatom* ia;
     int      i, j, newnr;
@@ -261,33 +226,30 @@ static void reduce_ilist(const int invindex[], const gmx_bool bKeep[], t_ilist*
 
 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;
+    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);
@@ -296,14 +258,12 @@ static void reduce_topology_x(int gnx, int index[], gmx_mtop_t* mtop, rvec x[],
             ilist.iatoms[j] = top.idef.il[i].iatoms[j];
         }
     }
-    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)
index 7c1cc84357f905775b0f3f38749d84ea473567a1..f0a91414fe2bc066042e865bd57792ca96ecae93 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <algorithm>
 
+#include "gromacs/utility/listoflists.h"
 #include "gromacs/utility/smalloc.h"
 #include "gromacs/utility/txtdump.h"
 
@@ -218,6 +219,19 @@ static int pr_blocka_title(FILE* fp, int indent, const char* title, const t_bloc
     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;
@@ -325,6 +339,43 @@ void pr_blocka(FILE* fp, int indent, const char* title, const t_blocka* block, g
     }
 }
 
+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;
index 8db0164b90c8e6ef9ca008c3666b98b62c1ac3df..fe0a30a56a15661f993bb13d56e711c90b85925a 100644 (file)
@@ -48,6 +48,9 @@
 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
@@ -217,5 +220,6 @@ void stupid_fill_blocka(t_blocka* grp, int natom);
 
 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
index 9472c43781e67e9c831f26ca6521ca807ae0a00f..b73b68097e676ee50a04dc2ac816c123d8a1ca0f 100644 (file)
 
 #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++)
@@ -79,21 +108,12 @@ void exclusionBlocksToBlocka(gmx::ArrayRef<const ExclusionBlock> b2, t_blocka* b
     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)
     {
@@ -118,10 +138,29 @@ void mergeExclusions(t_blocka* excl, gmx::ArrayRef<ExclusionBlock> 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
index b27db36093d71f0c40a945ea8562a80079d86a93..69c9c54c21047ce8bc8add7e2403c8df4c1a37d9 100644 (file)
@@ -44,6 +44,8 @@ struct t_blocka;
 
 namespace gmx
 {
+template<typename>
+class ListOfLists;
 
 /*! \libinternal \brief
  * Describes exclusions for a single atom.
@@ -61,7 +63,7 @@ struct ExclusionBlock
  * 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.
index ef3f17e8374d4ec1197a70dd7a35adc51c02d8ca..b438c3583db518dd01590746695e241ba43de338 100644 (file)
@@ -411,15 +411,15 @@ void init_idef(t_idef* idef)
     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->numNonperturbedInteractions[f] = 0;
     }
     idef->cmap_grid               = nullptr;
     idef->iparams_posres_nalloc   = 0;
     idef->iparams_fbposres_nalloc = 0;
-    idef->ilsort                  = 0;
+    idef->ilsort                  = ilsortUNKNOWN;
 }
 
 void done_idef(t_idef* idef)
@@ -439,11 +439,10 @@ void done_idef(t_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;
+    dst->nr     = src->nr;
+    dst->nalloc = src->nr;
 
-    snew(dst->iatoms, dst->nr);
+    snew(dst->iatoms, dst->nalloc);
     for (int i = 0; i < dst->nr; ++i)
     {
         dst->iatoms[i] = src->iatoms[i];
index 15c010e286c48ee702f994c67efa113c799d1bdc..269d531fc0380b7a7fa022e4f0ff0cf22ecee8c9 100644 (file)
@@ -244,7 +244,6 @@ struct t_ilist
     int size() const { return nr; }
 
     int      nr;
-    int      nr_nonperturbed;
     t_iatom* iatoms;
     int      nalloc;
 };
@@ -345,7 +344,9 @@ typedef struct t_idef
     int         iparams_posres_nalloc, iparams_fbposres_nalloc;
 
     t_ilist il[F_NRE];
-    int     ilsort;
+    /* The number of non-perturbed interactions at the start of each entry in il */
+    int numNonperturbedInteractions[F_NRE];
+    int ilsort;
 } t_idef;
 
 /*
index 4bc2e2946e229397becd7045b3bf00bcf5b9cd6b..bdee8d1ea65fc8c89b529d5a22457220234721e0 100644 (file)
@@ -650,45 +650,6 @@ t_atoms gmx_mtop_global_atoms(const gmx_mtop_t* mtop)
  * 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)
-{
-    int i, j, l, size;
-    int destnr  = dest->nr;
-    int destnra = dest->nra;
-
-    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);
-    }
-
-    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++)
-    {
-        for (i = 0; (i < src->nra); i++)
-        {
-            dest->a[l++] = dnum + src->a[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)
 {
     int nral, c, i, a;
@@ -933,29 +894,28 @@ static void copyAtomtypesFromMtop(const gmx_mtop_t& mtop, t_atomtypes* atomtypes
     }
 }
 
-/*! \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
@@ -966,21 +926,21 @@ static void copyExclsFromMtop(const gmx_mtop_t& mtop, t_blocka* excls)
  * \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;
     }
@@ -1012,7 +972,7 @@ static void addMimicExclusions(t_blocka* excls, const gmx::ArrayRef<const int> i
 
     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
@@ -1026,7 +986,7 @@ static void gen_local_top(const gmx_mtop_t& mtop,
 {
     copyAtomtypesFromMtop(mtop, &top->atomtypes);
     copyIdefFromMtop(mtop, &top->idef, freeEnergyInteractionsAtEnd, bMergeConstr);
-    copyExclsFromMtop(mtop, &top->excls);
+    top->excls = globalExclusionLists(mtop);
     if (!mtop.intermolecularExclusionGroup.empty())
     {
         addMimicExclusions(&top->excls, mtop.intermolecularExclusionGroup);
@@ -1100,7 +1060,6 @@ static void gen_t_topology(const gmx_mtop_t& mtop,
 {
     copyAtomtypesFromMtop(mtop, &top->atomtypes);
     copyIdefFromMtop(mtop, &top->idef, freeEnergyInteractionsAtEnd, bMergeConstr);
-    copyExclsFromMtop(mtop, &top->excls);
 
     top->name                        = mtop.name;
     top->atoms                       = gmx_mtop_global_atoms(&mtop);
index ab9f1ad1227d98909f09b37739599105213112c2..0a45f88c03f3cbf7242b823a13a60a57e4523714 100644 (file)
 
 #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"
@@ -101,6 +103,21 @@ void makeTestBlockAData(t_blocka* ba)
     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:
@@ -108,6 +125,7 @@ public:
     {
         const int natom = 3;
         makeTestBlockAData(&ba_);
+        list_ = makeTestListOfLists();
         b_.resize(natom);
     }
     ~ExclusionBlockTest() override { done_blocka(&ba_); }
@@ -126,8 +144,20 @@ public:
         }
     }
 
+    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_;
 };
 
@@ -148,8 +178,8 @@ TEST_F(ExclusionBlockTest, ConvertExclusionBlockToBlocka)
 
 TEST_F(ExclusionBlockTest, MergeExclusions)
 {
-    mergeExclusions(&ba_, b_);
-    compareBlocks();
+    mergeExclusions(&list_, b_);
+    compareBlocksAndList();
 }
 
 } // namespace
index e01993300bb2ab27429e88d045912376cb8f1816..fbc0d3cef3c6097dfcf400ccfbd27f9ae73ef963 100644 (file)
@@ -71,12 +71,11 @@ void init_top(t_topology* top)
     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);
 }
@@ -84,7 +83,6 @@ gmx_moltype_t::gmx_moltype_t() : name(nullptr), excls()
 gmx_moltype_t::~gmx_moltype_t()
 {
     done_atom(&atoms);
-    done_blocka(&excls);
 }
 
 gmx_mtop_t::gmx_mtop_t()
@@ -112,7 +110,6 @@ void done_top(t_topology* top)
 
     done_symtab(&(top->symtab));
     done_block(&(top->mols));
-    done_blocka(&(top->excls));
 }
 
 void done_top_mtop(t_topology* top, gmx_mtop_t* mtop)
@@ -123,7 +120,6 @@ 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);
@@ -136,7 +132,6 @@ void done_top_mtop(t_topology* top, gmx_mtop_t* mtop)
 
 gmx_localtop_t::gmx_localtop_t()
 {
-    init_blocka_null(&excls);
     init_idef(&idef);
     init_atomtypes(&atomtypes);
 }
@@ -146,7 +141,6 @@ gmx_localtop_t::~gmx_localtop_t()
     if (!useInDomainDecomp_)
     {
         done_idef(&idef);
-        done_blocka(&excls);
         done_atomtypes(&atomtypes);
     }
 }
@@ -287,7 +281,7 @@ static void pr_moltype(FILE*                 fp,
     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(),
@@ -365,7 +359,6 @@ void pr_top(FILE* fp, int indent, const char* title, const t_topology* top, gmx_
         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);
     }
 }
@@ -457,15 +450,18 @@ static void cmp_cmap(FILE* fp, const gmx_cmap_t* cmap1, const gmx_cmap_t* cmap2,
     }
 }
 
-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,
@@ -534,7 +530,7 @@ static void compareMoltypes(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());
     }
 }
 
@@ -674,8 +670,8 @@ int getGroupType(const SimulationGroups& group, SimulationAtomGroupType type, in
 
 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);
index 710bbbd2d8ecbf6e1123d95521198a5e07d99cc8..ac35171337026b1c4c67c1f8cf64e372b0c04c6e 100644 (file)
@@ -48,6 +48,7 @@
 #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
@@ -83,10 +84,10 @@ struct gmx_moltype_t
     /*! \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 */
@@ -214,7 +215,7 @@ struct gmx_localtop_t
     //! Atomtype properties
     t_atomtypes atomtypes;
     //! The exclusions
-    t_blocka excls;
+    gmx::ListOfLists<int> excls;
     //! Flag for domain decomposition so we don't free already freed memory.
     bool useInDomainDecomp_ = false;
 };
@@ -228,8 +229,8 @@ typedef struct t_topology
     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);
index cf7ed9d3564a2ddb72ba9bd19d33c185d008bb44..960e39ca426935ae72653a511b1a2712ec2dcc94 100644 (file)
@@ -229,7 +229,7 @@ void gmx_sort_ilist_fe(t_idef* idef, const real* qA, const real* qB)
                 }
             }
             /* Now we now the number of non-perturbed interactions */
-            ilist->nr_nonperturbed = ic;
+            idef->numNonperturbedInteractions[ftype] = ic;
 
             /* Copy the buffer with perturbed interactions to the ilist */
             for (a = 0; a < ib; a++)
@@ -239,8 +239,9 @@ void gmx_sort_ilist_fe(t_idef* idef, const real* qA, const real* qB)
 
             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->nr - numNonperturbed);
             }
         }
     }
index cc45dadebcee5dcbef639e6e4dce08c45b02bd10..f9a58d2f2f0e3c78881cfd37d685bd29bc236350 100644 (file)
@@ -386,7 +386,7 @@ void Rdf::initAnalysis(const TrajectoryAnalysisSettings& settings, const Topolog
             }
         }
         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"));
index 782753d3d359fa752a269c92917890acecd19ed3..ec4c13f2d91a99deaed52c84c2171b90ff344277 100644 (file)
@@ -50,7 +50,10 @@ if(GMX_INSTALL_LEGACY_API)
   install(FILES
           arrayref.h
           baseversion.h
+          classhelpers.h
           enumerationhelpers.h
+          exceptions.h
+          listoflists.h
           programcontext.h
           range.h
           smalloc.h
diff --git a/src/gromacs/utility/listoflists.h b/src/gromacs/utility/listoflists.h
new file mode 100644 (file)
index 0000000..96927dc
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * 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
index e8040f05f7a5909654efe9add4ab6402d3b91263..1d3cd824848b0c3f69cef00567efe1fda286d54a 100644 (file)
@@ -43,6 +43,7 @@ gmx_add_unit_test(UtilityUnitTests utility-test
                   inmemoryserializer.cpp
                   keyvaluetreeserializer.cpp
                   keyvaluetreetransform.cpp
+                  listoflists.cpp
                   logger.cpp
                   mutex.cpp
                   path.cpp
diff --git a/src/gromacs/utility/tests/listoflists.cpp b/src/gromacs/utility/tests/listoflists.cpp
new file mode 100644 (file)
index 0000000..e36fb75
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * 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
index c6bda330656d5d723ae79f650c249904d51cc2d1..beb86b9b3a610446dc11cad134eea2c5458ab9d3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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,2018,2019,2020, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
index 5b0db0bfe0dadf01ec5f93ac32b2a13a58963d30..9414b16c9f2e2659a8b53e2728627c363f1c0668 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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.
index 2dbc14b37f0ca0476a1f7d4d729b56c0f85e644f..0f0200396f0519087be651958a4bd5e373541ee6 100644 (file)
@@ -1,7 +1,7 @@
 #
 # 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,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.