Merge branch 'origin/release-2021' into merge-2021-into-master
authorPaul Bauer <paul.bauer.q@gmail.com>
Tue, 24 Nov 2020 15:58:43 +0000 (16:58 +0100)
committerPaul Bauer <paul.bauer.q@gmail.com>
Tue, 24 Nov 2020 15:58:43 +0000 (16:58 +0100)
Resolved Conflicts:
cmake/gmxVersionInfo.cmake
docs/release-notes/index.rst
src/gromacs/mdlib/CMakeLists.txt
src/gromacs/mdrun/md.cpp

17 files changed:
1  2 
admin/gitlab-ci/archive.gitlab-ci.yml
admin/gitlab-ci/gromacs.gitlab-ci.yml
admin/gitlab-ci/lint.gitlab-ci.yml
admin/gitlab-ci/python-gmxapi.gitlab-ci.yml
admin/gitlab-ci/sample_restraint.gitlab-ci.yml
api/nblib/CMakeLists.txt
api/nblib/tests/CMakeLists.txt
cmake/gmxVersionInfo.cmake
docs/release-notes/index.rst
python_packaging/src/CMakeLists.txt
src/gromacs/hardware/detecthardware.cpp
src/gromacs/mdlib/CMakeLists.txt
src/gromacs/mdrun/md.cpp
src/gromacs/nbnxm/nbnxm_gpu_data_mgmt.cpp
src/gromacs/simd/support.cpp
src/programs/CMakeLists.txt
src/testutils/test_hardware_environment.cpp

index 9d44b76a345ffdf3bea59dcb1e802eda3da8912f,4b2cb78693f9343d5eb9692fe178625a68e6bbd1..a1736411125e79db323fb4f2c705bfc8bc800139
@@@ -5,7 -5,7 +5,7 @@@ prepare-release-version
      - .variables:default
      - .rules:nightly-only-for-release
    cache: {}
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    stage: configure-build
    variables:
      KUBERNETES_CPU_LIMIT: 1
@@@ -25,15 -25,15 +25,15 @@@ regressiontests:prepare
      - .variables:default
      - .rules:merge-and-post-merge-acceptance
    cache: {}
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    stage: configure-build
    variables:
      KUBERNETES_CPU_LIMIT: 1
      KUBERNETES_CPU_REQUEST: 1
      KUBERNETES_MEMORY_REQUEST: 2Gi
 -  # Always clone the default version for this branch, 2021 in this case
 +  # Always clone the default version for this branch, master in this case
    script:
 -    - export REGTESTBRANCH=release-2021
 +    - export REGTESTBRANCH=master
      - if [[ ! -z $REGRESSIONTESTBRANCH ]] ; then
        export REGTESTBRANCH=$REGRESSIONTESTBRANCH ;
        echo "Using $REGTESTBRANCH instead of default" ;
@@@ -69,7 -69,7 +69,7 @@@ regressiontests:package
    cache: {}
    # Docker image uploaded to dockerhub by user eriklindahl
    # TODO: Get DockerFile for admin/dockerfiles
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    stage: release-package
    variables:
      KUBERNETES_CPU_LIMIT: 1
@@@ -84,7 -84,7 +84,7 @@@
      - if [[ $GROMACS_RELEASE != "true" ]] ; then
        REGTESTNAME=$REGTESTNAME-dev ;
        fi
 -    - export REGTESTBRANCH=release-2021
 +    - 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
@@@ -143,7 -143,7 +143,7 @@@ archive:configure:release
      - .use-ccache
      - .before_script:default
      - .docs:build
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    variables:
      KUBERNETES_CPU_LIMIT: 4
      KUBERNETES_CPU_REQUEST: 2
@@@ -206,7 -206,7 +206,7 @@@ archive:package
      BUILD_DIR: build-package
  
  release-verify:
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    stage: release-verify
    extends:
      - .variables:default
@@@ -254,16 -254,8 +254,16 @@@ archive:nightly-webpage
      - job: webpage:build
    variables:
      BUILD_DIR: build-docs
 +  before_script:
 +    - eval $(ssh-agent -s)
 +    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
 +    - mkdir -p ~/.ssh
 +    - chmod 700 ~/.ssh
 +    - ssh-keyscan www.gromacs.org > ~/.ssh/known_hosts # Force overwrite the known hosts so we only have that one key in it.
 +    - chmod 644 ~/.ssh/known_hosts
    script:
      - tar czf webpage.tar.gz $BUILD_DIR/docs/html/
 +    - rsync --chmod=u+rwX,g+rwX,o+rX -av $BUILD_DIR/docs/html/* $BUILD_DIR/docs/html/.[a-z]* pbauer@www.gromacs.org:/var/www/manual/nightly/
  
    artifacts:
      when: always
index 8ddef2991554c48400995b30a1dd2fe3b725577e,2360be64bc178d40b841abec4b488a0b3cb998d8..939b51142de68461cbb6563f1d59f6281b1f45dc
@@@ -8,7 -8,7 +8,7 @@@ simple-build
      - .use-clang:base
      - .rules:basic-push
    stage: pre-build
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_CPU_LIMIT: 8
@@@ -226,11 -226,11 +226,11 @@@ gromacs:gcc-7:configure
      - .use-gcc:base
      - .use-opencl
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=AVX2_256"
 -    CMAKE_EXTRA_OPTIONS: "-DGMX_EXTERNAL_CLFFT=ON"
 +    CMAKE_EXTRA_OPTIONS: "-DGMX_EXTERNAL_CLFFT=ON -DGMX_INSTALL_LEGACY_API=ON"
      COMPILER_MAJOR_VERSION: 7
  
  gromacs:clang-8-cuda-10.0:configure:
      - .use-clang:base
      - .use-cuda
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      CMAKE_SIMD_OPTIONS: "-DGMX_USE_SIMD_KERNELS=off"
@@@ -253,7 -253,7 +253,7 @@@ gromacs:gcc-8-cuda-11.0:configure
      - .use-gcc:base
      - .use-cuda
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=SSE4.1"
@@@ -266,7 -266,7 +266,7 @@@ gromacs:gcc-8-cuda-11.0:configureMPI
      - .use-cuda
      - .use-mpi
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      CMAKE_SIMD_OPTIONS: "-DGMX_SIMD=SSE4.1"
@@@ -277,7 -277,7 +277,7 @@@ gromacs:clang-TSAN:configure
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      COMPILER_MAJOR_VERSION: 8
@@@ -288,7 -288,7 +288,7 @@@ gromacs:clang-8:configure
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:merge-requests
-   image: gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    variables:
      COMPILER_MAJOR_VERSION: 8
  
@@@ -298,7 -298,7 +298,7 @@@ gromacs:clang-9-mpi:configure
     - .use-clang:base
     - .use-mpi
     - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      COMPILER_MAJOR_VERSION: 9
@@@ -309,7 -309,7 +309,7 @@@ gromacs:clang-static-analyzer:configure
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      CMAKE_COMPILER_SCRIPT: "-DCMAKE_CXX_COMPILER=/usr/local/libexec/c++-analyzer -DCMAKE_C_COMPILER=gcc"
@@@ -321,7 -321,7 +321,7 @@@ gromacs:clang-ASAN:configure
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      COMPILER_MAJOR_VERSION: 8
@@@ -333,7 -333,7 +333,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:con
     - .use-oneapi:base
     - .use-opencl
     - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      COMPILER_MAJOR_VERSION: 2021
@@@ -344,7 -344,7 +344,7 @@@ gromacs:oneapi-2021.1-beta09-sycl:confi
     - .use-oneapi:base
     - .use-sycl
     - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      COMPILER_MAJOR_VERSION: 2021
@@@ -354,7 -354,7 +354,7 @@@ gromacs:clang-UBSAN:configure
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      COMPILER_MAJOR_VERSION: 8
@@@ -367,7 -367,7 +367,7 @@@ gromacs:gcc-8-cuda-11.0:release:configu
      - .use-mpi
      - .use-cuda
      - .rules:nightly-only-for-release
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      COMPILER_MAJOR_VERSION: 8
@@@ -386,7 -386,7 +386,7 @@@ gromacs:gcc-7:release:configure
      - .use-gcc:base
      - .use-opencl
      - .rules:nightly-only-for-release
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      COMPILER_MAJOR_VERSION: 7
@@@ -404,7 -404,7 +404,7 @@@ gromacs:clang-9:release:configure
      - .use-clang:base
      - .use-mpi
      - .rules:nightly-only-for-release
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      COMPILER_MAJOR_VERSION: 9
@@@ -422,7 -422,7 +422,7 @@@ gromacs:clang-8-cuda-10.1:release:confi
      - .use-clang:base
      - .use-cuda
      - .rules:nightly-only-for-release
-   image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi-master
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.1
    variables:
      COMPILER_MAJOR_VERSION: 8
      RELEASE_BUILD_DIR: release-builds-clang
@@@ -434,7 -434,7 +434,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:rel
     - .use-oneapi:base
     - .use-opencl
     - .rules:nightly-only-for-release
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      COMPILER_MAJOR_VERSION: 2021
@@@ -485,7 -485,7 +485,7 @@@ gromacs:gcc-7:build
      - .before_script:default
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    needs:
@@@ -498,7 -498,7 +498,7 @@@ gromacs:clang-8-cuda-10.0:build
      - .use-clang:base
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    needs:
@@@ -511,7 -511,7 +511,7 @@@ gromacs:gcc-8-cuda-11.0:build
      - .before_script:default
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
    needs:
@@@ -524,7 -524,7 +524,7 @@@ gromacs:gcc-8-cuda-11.0:buildMPI
      - .before_script:default
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
    needs:
@@@ -537,7 -537,7 +537,7 @@@ gromacs:clang-TSAN:build
      - .use-clang:base
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    needs:
@@@ -550,7 -550,7 +550,7 @@@ gromacs:clang-ASAN:build
      - .use-clang:base
      - .use-ccache
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -565,7 -565,7 +565,7 @@@ gromacs:clang-UBSAN:build
      - .use-clang:base
      - .use-ccache
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -580,7 -580,7 +580,7 @@@ gromacs:clang-static-analyzer:build
      - .use-clang:base
      - .use-ccache
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -595,7 -595,7 +595,7 @@@ gromacs:clang-8:build
      - .before_script:default
      - .use-ccache
      - .rules:merge-requests
-   image: gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    needs:
      - job: gromacs:clang-8:configure
  
@@@ -606,7 -606,7 +606,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:bui
      - .use-ccache
      - .use-oneapi:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -619,7 -619,7 +619,7 @@@ gromacs:oneapi-2021.1-beta09-sycl:build
      - .use-ccache
      - .use-oneapi:base
      - .rules:merge-and-post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -632,7 -632,7 +632,7 @@@ gromacs:clang-9-mpi:build
      - .before_script:default
      - .use-ccache
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
    needs:
@@@ -649,7 -649,7 +649,7 @@@ gromacs:gcc-8-cuda-11.0:release:build
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      BUILD_DIR: release-builds-gcc
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    needs:
      - job: gromacs:gcc-8-cuda-11.0:release:configure
  
@@@ -664,7 -664,7 +664,7 @@@ gromacs:gcc-7:release:build
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      BUILD_DIR: release-builds-gcc
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    needs:
      - job: gromacs:gcc-7:release:configure
  
@@@ -679,7 -679,7 +679,7 @@@ gromacs:clang-9:release:build
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      BUILD_DIR: release-builds-clang
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    needs:
      - job: gromacs:clang-9:release:configure
  
@@@ -693,7 -693,7 +693,7 @@@ gromacs:clang-8-cuda-10.1:release:build
    stage: release-build
    variables:
      BUILD_DIR: release-builds-clang
-   image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi-master
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.1
    needs:
      - job: gromacs:clang-8-cuda-10.1:release:configure
  
@@@ -710,7 -710,7 +710,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:rel
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      BUILD_DIR: release-builds-oneapi
      COMPILER_MAJOR_VERSION: 2021
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    needs:
      - job: gromacs:oneapi-2021.1-beta09-opencl:release:configure
  
@@@ -798,7 -798,7 +798,7 @@@ gromacs:gcc-7:test
    extends:
      - .gromacs:base:test
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "amd.com/gpu"
@@@ -813,7 -813,7 +813,7 @@@ gromacs:clang-8-cuda-10.0:test
    extends:
      - .gromacs:base:test
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -827,7 -827,7 +827,7 @@@ gromacs:gcc-8-cuda-11.0:test
    extends:
      - .gromacs:base:test
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -841,7 -841,7 +841,7 @@@ gromacs:gcc-8-cuda-11.0:test-gpucommupd
    extends:
      - .gromacs:base:test
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -858,7 -858,7 +858,7 @@@ gromacs:clang-8:test
    extends:
      - .gromacs:base:test
      - .rules:merge-requests
-   image: gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    needs:
      - job: gromacs:clang-8:build
  
@@@ -866,7 -866,7 +866,7 @@@ gromacs:clang-TSAN:test
    extends:
      - .gromacs:base:test
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    needs:
@@@ -877,7 -877,7 +877,7 @@@ gromacs:clang-ASAN:test
      - .gromacs:base:test
      - .use-clang:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      CTEST_RUN_MODE: "ExperimentalMemCheck"
@@@ -891,7 -891,7 +891,7 @@@ gromacs:clang-UBSAN:test
      - .gromacs:base:test
      - .use-clang:base
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -904,7 -904,7 +904,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:tes
      - .gromacs:base:test
      - .use-oneapi:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -915,7 -915,7 +915,7 @@@ gromacs:oneapi-2021.1-beta09-sycl:test
      - .gromacs:base:test
      - .use-oneapi:base
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -925,7 -925,7 +925,7 @@@ gromacs:clang-9-mpi:test
    extends:
      - .gromacs:base:test
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
    tags:
@@@ -937,7 -937,7 +937,7 @@@ gromacs:gcc-7:regressiontest
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "amd.com/gpu"
@@@ -956,7 -956,7 +956,7 @@@ gromacs:clang-8-cuda-10.0:regressiontes
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -975,7 -975,7 +975,7 @@@ gromacs:gcc-8-cuda-11.0:regressiontest
    extends:
      - .gromacs:base:regressiontest
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -993,7 -993,7 +993,7 @@@ gromacs:gcc-8-cuda-11.0:regressiontest-
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -1019,7 -1019,7 +1019,7 @@@ gromacs:gcc-8-cuda-11.0:regressiontest-
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/cmake-3.15.7-gcc-8-cuda-11.0-nvidiaopencl-clfft-openmpi-master
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
      KUBERNETES_EXTENDED_RESOURCE_LIMIT: 2
@@@ -1042,7 -1042,7 +1042,7 @@@ gromacs:gcc-8-cuda-11.0:regressiontest-
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -1069,7 -1069,7 +1069,7 @@@ gromacs:clang-8:regressiontest
    extends:
      - .gromacs:base:regressiontest
      - .rules:merge-requests
-   image: gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.0
    tags:
      - k8s-scilifelab
    needs:
@@@ -1080,7 -1080,7 +1080,7 @@@ gromacs:clang-TSAN:regressiontest
    extends:
      - .gromacs:base:regressiontest
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -1094,7 -1094,7 +1094,7 @@@ gromacs:clang-ASAN:regressiontest
      - .gromacs:base:regressiontest
      - .use-clang:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-8-tsan
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-tsan
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
    tags:
@@@ -1107,7 -1107,7 +1107,7 @@@ gromacs:clang-9:regressiontest
    extends:
      - .gromacs:base:regressiontest
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      REGRESSIONTEST_DOUBLE: "-double"
@@@ -1123,7 -1123,7 +1123,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:reg
      - .gromacs:base:regressiontest
      - .use-oneapi:base
      - .rules:merge-requests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -1135,7 -1135,7 +1135,7 @@@ gromacs:oneapi-2021.1-beta09-sycl:regre
      - .gromacs:base:regressiontest
      - .use-oneapi:base
      - .rules:post-merge-acceptance
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
    needs:
@@@ -1147,7 -1147,7 +1147,7 @@@ gromacs:gcc-8-cuda-11.0:release:test
      - .gromacs:base:test
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-8-cuda-11.0
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -1164,7 -1164,7 +1164,7 @@@ gromacs:gcc-7:release:test
      - .gromacs:base:test
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      BUILD_DIR: release-builds-gcc
@@@ -1182,7 -1182,7 +1182,7 @@@ gromacs:clang-9:release:test
      - .gromacs:base:test
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      BUILD_DIR: release-builds-clang
@@@ -1195,7 -1195,7 +1195,7 @@@ gromacs:clang-8-cuda-10.1:release:test
      - .gromacs:base:test
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi-master
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.1
    variables:
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
      KUBERNETES_EXTENDED_RESOURCE_LIMIT: 1
@@@ -1212,7 -1212,7 +1212,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:rel
      - .use-oneapi:base
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      BUILD_DIR: release-builds-oneapi
@@@ -1225,7 -1225,7 +1225,7 @@@ gromacs:gcc-7:release:regressiontest
      - .gromacs:base:regressiontest
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    variables:
      CMAKE: /usr/local/cmake-3.13.0/bin/cmake
      BUILD_DIR: release-builds-gcc
@@@ -1243,7 -1243,7 +1243,7 @@@ gromacs:clang-9:release:regressiontest
      - .gromacs:base:regressiontest
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      BUILD_DIR: release-builds-clang
@@@ -1260,7 -1260,7 +1260,7 @@@ gromacs:clang-8-cuda-10.1:release:regre
      - .gromacs:base:regressiontest
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/cmake-3.15.7-llvm-8-cuda-10.1-openmpi-master
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-8-cuda-10.1
    variables:
      BUILD_DIR: release-builds-clang
      KUBERNETES_EXTENDED_RESOURCE_NAME: "nvidia.com/gpu"
@@@ -1280,7 -1280,7 +1280,7 @@@ gromacs:oneapi-2021.1-beta09-opencl:rel
      - .use-oneapi:base
      - .rules:nightly-only-for-release
    stage: release-tests
-   image: gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7-oneapi-2021.1-beta09
    variables:
      CMAKE: /usr/local/cmake-3.17.2/bin/cmake
      BUILD_DIR: release-builds-oneapi
index 548b9ec9a733e53c2ca589c5f18ae4f5e2fcc877,560e5cb991d6699a6d3ef94e090b249aa9eb6a23..e98ae896e09c190b22f4396bafc30a670d623de7
@@@ -5,7 -5,7 +5,7 @@@ clang-tidy:configure-push
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:basic-push
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      COMPILER_MAJOR_VERSION: 9
@@@ -17,7 -17,7 +17,7 @@@ clang-tidy:configure-schedule
      - .gromacs:base:configure
      - .use-clang:base
      - .rules:nightly-not-for-release
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    variables:
      CMAKE: /usr/local/cmake-3.15.7/bin/cmake
      COMPILER_MAJOR_VERSION: 9
@@@ -31,7 -31,7 +31,7 @@@ clang-tidy:build
      - .variables:default
      - .rules:nightly-not-for-release
    stage: source-check
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    needs:
      - job: clang-tidy:configure-schedule
    variables:
@@@ -44,7 -44,7 +44,7 @@@ clang-tidy:test
      - .variables:default
      - .rules:basic-push
    stage: source-check
-   image: gromacs/ci-ubuntu-18.04-llvm-9
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-9
    needs:
      - job: clang-tidy:configure-push
    variables:
@@@ -59,7 -59,7 +59,7 @@@
      # Make sure that a Python interpreter can be found for `/bin/env python`
      - test -x /usr/bin/python || update-alternatives --install /usr/bin/python python /usr/bin/python3 1
      # TODO (issue #3272) `master` is not appropriate for use on release-xxxx branches, how should we handle that?
 -    - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git release-2021 && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
 +    - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git master && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
      - HEAD_REV=$(git show -s --pretty=format:"%h" HEAD)
      - if [[ "$REV" == "$HEAD_REV" ]] ; then
          REV="HEAD~1" ;
@@@ -81,7 -81,7 +81,7 @@@ clang-format
      - .rules:basic-push
    cache: {}
    stage: pre-build
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    variables:
      COMPILER_MAJOR_VERSION: 7
      KUBERNETES_CPU_LIMIT: 1
@@@ -89,8 -89,7 +89,8 @@@
      KUBERNETES_MEMORY_REQUEST: 2Gi
      EXTRA_INSTALLS: clang-format-$COMPILER_MAJOR_VERSION
    script:
 -    - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git release-2021 && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
 +    # TODO (issue #3272) `master` is not appropriate for use on release-xxxx branches, how should we handle that?
 +    - REV=$(git fetch -q https://gitlab.com/gromacs/gromacs.git master && git show -s --pretty=format:"%h" `git merge-base FETCH_HEAD HEAD`)
      - HEAD_REV=$(git show -s --pretty=format:"%h" HEAD)
      - if [[ "$REV" == "$HEAD_REV" ]] ; then
          REV="HEAD~1" ;
@@@ -112,7 -111,7 +112,7 @@@ copyright-check
      - .rules:basic-push
    cache: {}
    stage: pre-build
-   image: gromacs/ci-ubuntu-18.04-llvm-7-docs
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-llvm-7-docs
    variables:
      KUBERNETES_CPU_LIMIT: 1
      KUBERNETES_CPU_REQUEST: 1
index 8e6b52a1d0d1a976e2b64f042841bed948b5407e,3ffd73e073be634a524b2a62414c36f47dfbb660..5b0fb42219e046e6b1ee389bf1071fa1985bdc78
@@@ -8,7 -8,7 +8,7 @@@
      - .variables:default
      - .use-clang:base
    stage: test
-   image: gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
+   image: ${CI_REGISTRY}/gromacs/gromacs/cmake-3.15.7-llvm-8-intelopencl-openmpi:2020
    variables:
      KUBERNETES_CPU_LIMIT: 2
      KUBERNETES_CPU_REQUEST: 2
@@@ -78,7 -78,7 +78,7 @@@ gmxapi-0.1:clang-8:py-3.8.2
    extends:
      - .variables:default
      - .use-clang:base
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    stage: test
    variables:
      KUBERNETES_CPU_LIMIT: 2
  gmxapi-0.2:gcc-7:gmx2021:py-3.6.10:
    extends:
      - .gmxapi-0.2:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.6"
      PY_VER: "3.6.10"
  gmxapi-0.2:gcc-7:gmx2021:py-3.7.7:
    extends:
      - .gmxapi-0.2:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.7"
      PY_VER: "3.7.7"
  gmxapi-0.2:gcc-7:gmx2021:py-3.8.2:
    extends:
      - .gmxapi-0.2:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.8"
      PY_VER: "3.8.2"
index 27e56e2296a0578f14ad831ff77b3f5fa048a22b,4f024eba9dcfa5197eb097edabb4f2646eba1cc2..8926edddeee26383dc17c6eb032598bdbecea49c
@@@ -3,7 -3,7 +3,7 @@@
    extends:
      - .variables:default
      - .use-clang:base
-   image: gromacs/ci-ubuntu-18.04-gcc-7
+   image: ${CI_REGISTRY}/gromacs/gromacs/ci-ubuntu-18.04-gcc-7
    stage: test
    variables:
      KUBERNETES_CPU_LIMIT: 2
@@@ -33,7 -33,7 +33,7 @@@
  sample_restraint:gcc-7:gmx2021:py-3.6.10:
    extends:
      - .sample_restraint:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.6"
      PY_VER: "3.6.10"
@@@ -41,7 -41,7 +41,7 @@@
  sample_restraint:gcc-7:gmx2021:py-3.7.7:
    extends:
      - .sample_restraint:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.7"
      PY_VER: "3.7.7"
@@@ -49,7 -49,7 +49,7 @@@
  sample_restraint:gcc-7:gmx2021:py-3.8.2:
    extends:
      - .sample_restraint:gcc-7:gmx2021
 -    - .rules:merge-requests:release-2021
 +    - .rules:merge-requests:master
    variables:
      VENVPATH: "/root/venv/py3.8"
      PY_VER: "3.8.2"
diff --combined api/nblib/CMakeLists.txt
index c62efde351f7a22f819c71db4dd443fa2a52c9a0,a87af6108132e1cb9643c300a32093ffc5e842d7..99fcfae3d5126ff8b58c1a386c4f6c8f805c7503
@@@ -47,31 -47,20 +47,20 @@@ set(IGNORED_CLANG_ALL_WARNING
          "-Wno-covered-switch-default" #GCC gives maybe-uninitialized without default label and checks for illegal enum values.
          "-Wno-switch-enum" # default statement for enum is OK
  
-         # We need to use macros like
-         # GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR. Those will look strange
-         # if they don't have a semicolon after them, and might confuse
-         # tools like IDEs also.
-         "-Wno-extra-semi-stmt"
-         #Following ones are undecided/TODO
-         "-Wno-disabled-macro-expansion"
-         "-Wno-cast-align"
-         "-Wno-reserved-id-macro"
-         "-Wno-global-constructors"
+         # These are all needed, mostly for testing code
+         "-Wno-conversion"
+         "-Wno-documentation"
+         "-Wno-double-promotion"
          "-Wno-exit-time-destructors"
+         "-Wno-float-equal"
+         "-Wno-global-constructors"
+         "-Wno-padded"
+         "-Wno-reserved-id-macro"
+         "-Wno-shadow"
          "-Wno-unused-macros"
          "-Wno-weak-vtables"
-         "-Wno-conditional-uninitialized"
-         "-Wno-format-nonliteral"
-         "-Wno-shadow"
-         "-Wno-cast-qual"
-         "-Wno-documentation"
-         "-Wno-used-but-marked-unused"
-         "-Wno-padded"
-         "-Wno-float-equal"
-         "-Wno-old-style-cast"
-         "-Wno-conversion"
-         "-Wno-double-promotion")
+         )
  string(REPLACE " " ";" IGNORED_CLANG_ALL_WARNINGS "${IGNORED_CLANG_ALL_WARNINGS}")
  
  set(TESTUTILS_DIR ${PROJECT_SOURCE_DIR}/src/testutils)
@@@ -122,11 -111,6 +111,11 @@@ gmx_target_compile_options(nblib
  target_link_libraries(nblib PRIVATE libgromacs)
  target_include_directories(nblib PRIVATE ${PROJECT_SOURCE_DIR}/api)
  include_directories(BEFORE ${CMAKE_SOURCE_DIR}/api)
 +target_link_libraries(nblib PRIVATE common)
 +# There are transitive dependencies on the legacy GROMACS headers.
 +target_link_libraries(nblib PUBLIC legacy_api)
 +# TODO: Explicitly link specific modules.
 +target_link_libraries(nblib PRIVATE legacy_modules)
  
  install(TARGETS nblib
          EXPORT nblib
index 05af36c7932ef427ef0467d4acd92351d8a027c6,4707595b4dbc0a262e0278be67817b5b5819511d..f2f2d889c4fd376317964f039a0ca6f35d42bb2c
@@@ -46,9 -46,6 +46,9 @@@ gmx_add_unit_test_library(nblib_test_in
      )
  target_include_directories(nblib_test_infrastructure PRIVATE ${PROJECT_SOURCE_DIR}/api)
  target_include_directories(nblib_test_infrastructure SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
 +target_link_libraries(nblib_test_infrastructure PRIVATE legacy_api)
 +# TODO: Explicitly link specific modules: math,
 +target_link_libraries(nblib_test_infrastructure PRIVATE legacy_modules)
  
  set(testname "NbLibSetupTests")
  set(exename "nblib-setup-test")
@@@ -60,6 -57,7 +60,7 @@@ gmx_add_gtest_executable
          box.cpp
          interactions.cpp
          particletype.cpp
+         pbcholder.cpp
          molecules.cpp
          topology.cpp
      )
index 1f88249c73f5be99f402a5d2ea260393295dd4fb,5a1fb99b093393f29c7dc1e17388afc2e62a682a..73295bdd962bacf31f8b85ed8f08f3d67a14c45c
@@@ -60,7 -60,6 +60,7 @@@
  #         GROMACS     2019   4
  #         GROMACS     2020   5
  #         GROMACS     2021   6
 +#         GROMACS     2022   7
  #   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 2021)
 +set(GMX_VERSION_MAJOR 2022)
  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 "-beta2")
 +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
  # 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 6)
 +set(LIBRARY_SOVERSION_MAJOR 7)
  set(LIBRARY_SOVERSION_MINOR 0)
  set(LIBRARY_VERSION ${LIBRARY_SOVERSION_MAJOR}.${LIBRARY_SOVERSION_MINOR}.0)
  
@@@ -257,13 -256,13 +257,13 @@@ if (NOT SOURCE_IS_SOURCE_DISTRIBUTION A
  endif()
  
  set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
 -set(REGRESSIONTEST_BRANCH "release-2021") 
 +set(REGRESSIONTEST_BRANCH "master")
  # Run the regressiontests packaging job with the correct pakage
  # version string, and the release box checked, in order to have it
  # build the regressiontests tarball with all the right naming. The
  # naming affects the md5sum that has to go here, and if it isn't right
  # release workflow will report a failure.
- set(REGRESSIONTEST_MD5SUM "0a391e1a8fefd59859704f58626767e6" CACHE INTERNAL "MD5 sum of the regressiontests tarball for this GROMACS version")
+ set(REGRESSIONTEST_MD5SUM "168992305e10b44c58cd22130558e5fc" CACHE INTERNAL "MD5 sum of the regressiontests tarball for this GROMACS version")
  
  math(EXPR GMX_VERSION_NUMERIC
       "${GMX_VERSION_MAJOR}*10000 + ${GMX_VERSION_PATCH}")
index 6915178928e706d9447cb3784d798b93d4fc5e37,6b41402eb98eb2ad7f5b0c7f8c9bd22fc1d504f0..90a44ee75e19e7f0aaac0cf48ab06651701a9568
@@@ -8,19 -8,19 +8,19 @@@ releases of |Gromacs|. Major releases c
  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 2021
 -series and the 2020 series. In the latter, only highly conservative
 +Two versions of |Gromacs| are under active maintenance, the 2022
 +series and the 2021 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 2020 ends, but we keep 2019 in the name so users understand how
 +year 2021 ends, but we keep 2021 in the name so users understand how
  up to date their version is. Such fixes will also be incorporated into
 -the 2021 release series, as appropriate. Around the time the 2022
 -release is made, the 2020 series will no longer be maintained.
 +the 2022 release series, as appropriate. Around the time the 2023
 +release is made, the 2021 series will no longer be maintained.
  
  Where issue numbers are reported in these release notes, more details
- can be found at https://gitlab.com/gromacs/gromacs/-/issues at that issue number.
+ can be found on the `issue tracker`_ at that issue number.
  
 -|Gromacs| 2021 series
 +|Gromacs| 2022 series
  ---------------------
  
  .. todolist::
  Major release
  ^^^^^^^^^^^^^
  
 +.. toctree::
 +   :maxdepth: 1
 +
 +   2022/major/highlights
 +   2022/major/features
 +   2022/major/performance
 +   2022/major/tools
 +   2022/major/bugs-fixed
 +   2022/major/deprecated-functionality
 +   2022/major/removed-functionality
 +   2022/major/portability
 +   2022/major/miscellaneous
 +
 +
 +|Gromacs| 2021 series
 +---------------------
 +
 +Major release
 +^^^^^^^^^^^^^
 +
  .. toctree::
     :maxdepth: 1
  
     2021/major/portability
     2021/major/miscellaneous
  
++
 +Older (unmaintained) |Gromacs| series
 +-------------------------------------------------------
 +
  |Gromacs| 2020 series
  ---------------------
  
@@@ -128,6 -105,9 +129,6 @@@ Major releas
     2019/major/portability
     2019/major/miscellaneous
  
 -Older (unmaintained) |Gromacs| series
 --------------------------------------------------------
 -
  |Gromacs| 2018 series
  ---------------------
  
index 32d19be17e311699536c59ed5040147a9e76ef3d,c75549fc8213ba825f08154b882a04fb168982ff..1e82f3ba95a9ce5fb4ec8354513badec46914f9a
@@@ -55,7 -55,7 +55,7 @@@ set(CMAKE_OSX_ARCHITECTURES x86_64 CACH
  # Note that this is the gmxapi._gmxapi Python bindings package version,
  # not the C++ API version. It is not essential that it match the pure Python
  # package version, but is likely to do so.
 -project(gmxapi VERSION 0.2.0)
 +project(gmxapi VERSION 0.3.0)
  
  # Check if Python package is being built directly or via add_subdirectory
  set(GMXAPI_MASTER_PROJECT OFF)
@@@ -153,6 -153,7 +153,7 @@@ set_target_properties(_gmxapi PROPERTIE
  if(GMXAPI_MASTER_PROJECT)
      # TODO: This requirement is probably overly restrictive.
      find_package(GROMACS 2021 REQUIRED
+                  NAMES gromacs gromacs_mpi
                   HINTS "$ENV{GROMACS_DIR}"
                   )
  endif()
index a775c1775136d86a08d79b22a773c70c83815805,d808249678abdb704be7cdbb13562ce846b41ae7..690457fc52e6a41a6ebb0ea7c6a96ed2216d9eb8
@@@ -1,7 -1,7 +1,7 @@@
  /*
   * This file is part of the GROMACS molecular simulation package.
   *
-  * Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team.
+  * Copyright (c) 2012,2013,2014,2015,2016, The GROMACS development team.
   * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
   * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
   * and including many others, as listed in the AUTHORS file in the
@@@ -209,7 -209,10 +209,7 @@@ static void gmx_collect_hardware_mpi(co
       * - family=23 with the below listed models;
       * - Hygon as vendor.
       */
 -    const bool cpuIsAmdZen1 = ((cpuInfo.vendor() == CpuInfo::Vendor::Amd && cpuInfo.family() == 23
 -                                && (cpuInfo.model() == 1 || cpuInfo.model() == 17
 -                                    || cpuInfo.model() == 8 || cpuInfo.model() == 24))
 -                               || cpuInfo.vendor() == CpuInfo::Vendor::Hygon);
 +    const bool cpuIsAmdZen1 = gmx::cpuIsAmdZen1(cpuInfo);
  
      int numCompatibleDevices = getCompatibleDevices(hardwareInfo->deviceInfoList).size();
  #if GMX_LIB_MPI
index a9d37b516dd0bdf40acfef30316c870f2724c7aa,949a3057972b5275f3aab35af1667cb72af66f78..f1d575bfbe2e6fdfaad97d5215e54201e3ef4666
  # To help us fund GROMACS development, we humbly ask that you cite
  # the research papers on the package. Check out http://www.gromacs.org.
  
 +add_library(mdlib INTERFACE)
 +
  file(GLOB MDLIB_SOURCES *.cpp)
+ # To avoid listing all the necessary files manually, we will remove SYCL-specfific one here:
+ list(REMOVE_ITEM MDLIB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/leapfrog_gpu_sycl.cpp)
  
  set(MDLIB_SOURCES ${MDLIB_SOURCES} PARENT_SCOPE)
 -if (BUILD_TESTING)
 -    add_subdirectory(tests)
 -endif()
  if(GMX_GPU_CUDA)
      gmx_add_libgromacs_sources(
         leapfrog_gpu.cu
         gpuforcereduction_impl.cu
         )
  endif()
 +
+ if(GMX_GPU_SYCL)
+     gmx_add_libgromacs_sources(
+         leapfrog_gpu_sycl.cpp
+     )
+     _gmx_add_files_to_property(SYCL_SOURCES
+         leapfrog_gpu_sycl.cpp
+     )
+ endif()
++
 +# Source files have the following private module dependencies.
 +target_link_libraries(mdlib PRIVATE
 +#                      gmxlib
 +#                      math
 +#                      mdtypes
 +#                      tng_io
 +                      )
 +
 +# Public interface for modules, including dependencies and interfaces
 +#target_include_directories(mdlib PUBLIC
 +target_include_directories(mdlib INTERFACE
 +                           $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
 +#target_link_libraries(mdlib PUBLIC
 +target_link_libraries(mdlib INTERFACE
 +                      legacy_api
 +                      )
 +
 +# TODO: when mdlib is an OBJECT target
 +#target_link_libraries(mdlib PUBLIC legacy_api)
 +#target_link_libraries(mdlib PRIVATE common)
 +
 +# Module dependencies
 +# mdlib interfaces convey transitive dependence on these modules.
 +#target_link_libraries(mdlib PUBLIC
 +target_link_libraries(mdlib INTERFACE
 +                      utility
 +                      )
 +# Source files have the following private module dependencies.
 +#target_link_libraries(mdlib PRIVATE tng_io)
 +# TODO: Explicitly link specific modules.
 +#target_link_libraries(mdlib PRIVATE legacy_modules)
 +
 +if (BUILD_TESTING)
 +    add_subdirectory(tests)
 +endif()
diff --combined src/gromacs/mdrun/md.cpp
index 4c274e8611ca7d6711ab8975fca2558e2942f284,caa25a7a43c484d0214eb2c4a1e4f779f6f800db..9d866de3803ec73969f1614e00bb1ec57e95c5a0
  #include "gromacs/mdlib/trajectory_writing.h"
  #include "gromacs/mdlib/update.h"
  #include "gromacs/mdlib/update_constrain_gpu.h"
 +#include "gromacs/mdlib/update_vv.h"
  #include "gromacs/mdlib/vcm.h"
  #include "gromacs/mdlib/vsite.h"
  #include "gromacs/mdrunutility/handlerestart.h"
@@@ -179,7 -178,7 +179,7 @@@ void gmx::LegacySimulator::do_md(
      gmx_global_stat_t gstat;
      gmx_shellfc_t*    shellfc;
      gmx_bool          bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
 -    gmx_bool          bTemp, bPres, bTrotter;
 +    gmx_bool          bTrotter;
      real              dvdl_constr;
      std::vector<RVec> cbuf;
      matrix            lastbox;
              init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider, mdModulesNotifier, ir,
                          top_global, oenv, wcycle, startingBehavior, simulationsShareState, ms);
      gmx::EnergyOutput energyOutput(mdoutf_get_fp_ene(outf), top_global, ir, pull_work,
-                                    mdoutf_get_fp_dhdl(outf), false, startingBehavior, mdModulesNotifier);
+                                    mdoutf_get_fp_dhdl(outf), false, startingBehavior,
+                                    simulationsShareState, mdModulesNotifier);
  
      gstat = global_stat_init(ir);
  
                             "Orientation restraints are not supported with the GPU update.\n");
          GMX_RELEASE_ASSERT(
                  ir->efep == efepNO
-                         || (!haveFreeEnergyType(*ir, efptBONDED) && !haveFreeEnergyType(*ir, efptMASS)),
+                         || (!haveFepPerturbedMasses(*top_global) && !havePerturbedConstraints(*top_global)),
                  "Free energy perturbation of masses and constraints are not supported with the GPU "
                  "update.");
  
  
          if (bExchanged)
          {
 -
              /* We need the kinetic energy at minus the half step for determining
               * the full step kinetic energy and possibly for T-coupling.*/
              /* This may not be quite working correctly yet . . . . */
          // if it is the first step after starting from a checkpoint.
          // That is, the half step is needed on all other steps, and
          // also the first step when starting from a .tpr file.
 -        if (EI_VV(ir->eI) && (!bFirstStep || startingBehavior == StartingBehavior::NewSimulation))
 -        /*  ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
 -        {
 -            rvec* vbuf = nullptr;
 -
 -            wallcycle_start(wcycle, ewcUPDATE);
 -            if (ir->eI == eiVV && bInitStep)
 -            {
 -                /* if using velocity verlet with full time step Ekin,
 -                 * take the first half step only to compute the
 -                 * virial for the first step. From there,
 -                 * revert back to the initial coordinates
 -                 * so that the input is actually the initial step.
 -                 */
 -                snew(vbuf, state->natoms);
 -                copy_rvecn(state->v.rvec_array(), vbuf, 0,
 -                           state->natoms); /* should make this better for parallelizing? */
 -            }
 -            else
 -            {
 -                /* this is for NHC in the Ekin(t+dt/2) version of vv */
 -                trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ,
 -                               trotter_seq, ettTSEQ1);
 -            }
 -
 -            upd.update_coords(*ir, step, mdatoms, state, f.view().forceWithPadding(), fcdata, ekind,
 -                              M, etrtVELOCITY1, cr, constr != nullptr);
 -
 -            wallcycle_stop(wcycle, ewcUPDATE);
 -            constrain_velocities(constr, do_log, do_ene, step, state, nullptr, bCalcVir, shake_vir);
 -            wallcycle_start(wcycle, ewcUPDATE);
 -            /* if VV, compute the pressure and constraints */
 -            /* For VV2, we strictly only need this if using pressure
 -             * control, but we really would like to have accurate pressures
 -             * printed out.
 -             * Think about ways around this in the future?
 -             * For now, keep this choice in comments.
 -             */
 -            /*bPres = (ir->eI==eiVV || inputrecNptTrotter(ir)); */
 -            /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && inputrecNptTrotter(ir)));*/
 -            bPres = TRUE;
 -            bTemp = ((ir->eI == eiVV && (!bInitStep)) || (ir->eI == eiVVAK));
 -            if (bCalcEner && ir->eI == eiVVAK)
 -            {
 -                bSumEkinhOld = TRUE;
 -            }
 -            /* for vv, the first half of the integration actually corresponds to the previous step.
 -               So we need information from the last step in the first half of the integration */
 -            if (bGStat || do_per_step(step - 1, nstglobalcomm))
 -            {
 -                wallcycle_stop(wcycle, ewcUPDATE);
 -                compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
 -                                makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, wcycle,
 -                                enerd, force_vir, shake_vir, total_vir, pres, constr, &nullSignaller,
 -                                state->box, &totalNumberOfBondedInteractions, &bSumEkinhOld,
 -                                (bGStat ? CGLO_GSTAT : 0) | (bCalcEner ? CGLO_ENERGY : 0)
 -                                        | (bTemp ? CGLO_TEMPERATURE : 0) | (bPres ? CGLO_PRESSURE : 0)
 -                                        | (bPres ? CGLO_CONSTRAINT : 0) | (bStopCM ? CGLO_STOPCM : 0)
 -                                        | (shouldCheckNumberOfBondedInteractions ? CGLO_CHECK_NUMBER_OF_BONDED_INTERACTIONS
 -                                                                                 : 0)
 -                                        | CGLO_SCALEEKIN);
 -                /* explanation of above:
 -                   a) We compute Ekin at the full time step
 -                   if 1) we are using the AveVel Ekin, and it's not the
 -                   initial step, or 2) if we are using AveEkin, but need the full
 -                   time step kinetic energy for the pressure (always true now, since we want accurate statistics).
 -                   b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
 -                   EkinAveVel because it's needed for the pressure */
 -                checkNumberOfBondedInteractions(mdlog, cr, totalNumberOfBondedInteractions,
 -                                                top_global, &top, makeConstArrayRef(state->x),
 -                                                state->box, &shouldCheckNumberOfBondedInteractions);
 -                if (bStopCM)
 -                {
 -                    process_and_stopcm_grp(fplog, &vcm, *mdatoms, makeArrayRef(state->x),
 -                                           makeArrayRef(state->v));
 -                    inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
 -                }
 -                wallcycle_start(wcycle, ewcUPDATE);
 -            }
 -            /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
 -            if (!bInitStep)
 -            {
 -                if (bTrotter)
 -                {
 -                    m_add(force_vir, shake_vir,
 -                          total_vir); /* we need the un-dispersion corrected total vir here */
 -                    trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ,
 -                                   trotter_seq, ettTSEQ2);
 -
 -                    /* TODO This is only needed when we're about to write
 -                     * a checkpoint, because we use it after the restart
 -                     * (in a kludge?). But what should we be doing if
 -                     * the startingBehavior is NewSimulation or bInitStep are true? */
 -                    if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
 -                    {
 -                        copy_mat(shake_vir, state->svir_prev);
 -                        copy_mat(force_vir, state->fvir_prev);
 -                    }
 -                    if (inputrecNvtTrotter(ir) && ir->eI == eiVV)
 -                    {
 -                        /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
 -                        enerd->term[F_TEMP] =
 -                                sum_ekin(&(ir->opts), ekind, nullptr, (ir->eI == eiVV), FALSE);
 -                        enerd->term[F_EKIN] = trace(ekind->ekin);
 -                    }
 -                }
 -                else if (bExchanged)
 -                {
 -                    wallcycle_stop(wcycle, ewcUPDATE);
 -                    /* We need the kinetic energy at minus the half step for determining
 -                     * the full step kinetic energy and possibly for T-coupling.*/
 -                    /* This may not be quite working correctly yet . . . . */
 -                    compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
 -                                    makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, wcycle,
 -                                    enerd, nullptr, nullptr, nullptr, nullptr, constr, &nullSignaller,
 -                                    state->box, nullptr, &bSumEkinhOld, CGLO_GSTAT | CGLO_TEMPERATURE);
 -                    wallcycle_start(wcycle, ewcUPDATE);
 -                }
 -            }
 -            /* if it's the initial step, we performed this first step just to get the constraint virial */
 -            if (ir->eI == eiVV && bInitStep)
 -            {
 -                copy_rvecn(vbuf, state->v.rvec_array(), 0, state->natoms);
 -                sfree(vbuf);
 -            }
 -            wallcycle_stop(wcycle, ewcUPDATE);
 -        }
 -
 -        /* compute the conserved quantity */
          if (EI_VV(ir->eI))
          {
 -            saved_conserved_quantity = NPT_energy(ir, state, &MassQ);
 -            if (ir->eI == eiVV)
 -            {
 -                last_ekin = enerd->term[F_EKIN];
 -            }
 -            if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres))
 -            {
 -                saved_conserved_quantity -= enerd->term[F_DISPCORR];
 -            }
 -            /* sum up the foreign kinetic energy and dK/dl terms for vv.  currently done every step so that dhdl is correct in the .edr */
 -            if (ir->efep != efepNO)
 -            {
 -                accumulateKineticLambdaComponents(enerd, state->lambda, *ir->fepvals);
 -            }
 +            integrateVVFirstStep(step, bFirstStep, bInitStep, startingBehavior, nstglobalcomm, ir,
 +                                 fr, cr, state, mdatoms, fcdata, &MassQ, &vcm, top_global, top, enerd,
 +                                 ekind, gstat, &last_ekin, bCalcVir, total_vir, shake_vir, force_vir,
 +                                 pres, M, do_log, do_ene, bCalcEner, bGStat, bStopCM, bTrotter,
 +                                 bExchanged, &bSumEkinhOld, &shouldCheckNumberOfBondedInteractions,
 +                                 &saved_conserved_quantity, &f, &upd, constr, &nullSignaller,
 +                                 trotter_seq, nrnb, mdlog, fplog, wcycle);
          }
  
          /* ########  END FIRST UPDATE STEP  ############## */
  
          dvdl_constr = 0;
  
-         wallcycle_start(wcycle, ewcUPDATE);
+         if (!useGpuForUpdate)
+         {
+             wallcycle_start(wcycle, ewcUPDATE);
+         }
          /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
          if (bTrotter)
          {
              update_pcouple_before_coordinates(fplog, step, ir, state, pressureCouplingMu, M, bInitStep);
          }
  
 -        if (EI_VV(ir->eI))
 -        {
 -            /* velocity half-step update */
 -            upd.update_coords(*ir, step, mdatoms, state, f.view().forceWithPadding(), fcdata, ekind,
 -                              M, etrtVELOCITY2, cr, constr != nullptr);
 -        }
 -
 -        /* Above, initialize just copies ekinh into ekin,
 -         * it doesn't copy position (for VV),
 -         * and entire integrator for MD.
 -         */
 -
 -        if (ir->eI == eiVVAK)
 -        {
 -            cbuf.resize(state->x.size());
 -            std::copy(state->x.begin(), state->x.end(), cbuf.begin());
 -        }
 -
          /* With leap-frog type integrators we compute the kinetic energy
           * at a whole time step as the average of the half-time step kinetic
           * energies of two subsequent steps. Therefore we need to compute the
          const bool doParrinelloRahman = (ir->epc == epcPARRINELLORAHMAN
                                           && do_per_step(step + ir->nstpcouple - 1, ir->nstpcouple));
  
 -        if (useGpuForUpdate)
 +        if (EI_VV(ir->eI))
          {
 -            if (bNS && (bFirstStep || DOMAINDECOMP(cr)))
 +            GMX_ASSERT(!useGpuForUpdate, "GPU update is not supported with VVAK integrator.");
 +
 +            integrateVVSecondStep(step, ir, fr, cr, state, mdatoms, fcdata, &MassQ, &vcm, pull_work,
 +                                  enerd, ekind, gstat, &dvdl_constr, bCalcVir, total_vir, shake_vir,
 +                                  force_vir, pres, M, lastbox, do_log, do_ene, bGStat, &bSumEkinhOld,
 +                                  &f, &cbuf, &upd, constr, &nullSignaller, trotter_seq, nrnb, wcycle);
 +        }
 +        else
 +        {
 +            if (useGpuForUpdate)
              {
 -                integrator->set(stateGpu->getCoordinates(), stateGpu->getVelocities(),
 -                                stateGpu->getForces(), top.idef, *mdatoms, ekind->ngtc);
  
 -                // Copy data to the GPU after buffers might have being reinitialized
 -                stateGpu->copyVelocitiesToGpu(state->v, AtomLocality::Local);
 -                stateGpu->copyCoordinatesToGpu(state->x, AtomLocality::Local);
 -            }
 +                wallcycle_stop(wcycle, ewcUPDATE);
  
 -            if (simulationWork.useGpuPme && !runScheduleWork->simulationWork.useGpuPmePpCommunication
 -                && !thisRankHasDuty(cr, DUTY_PME))
 -            {
 -                // The PME forces were recieved to the host, so have to be copied
 -                stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::All);
 -            }
 -            else if (!runScheduleWork->stepWork.useGpuFBufferOps)
 -            {
 -                // The buffer ops were not offloaded this step, so the forces are on the
 -                // host and have to be copied
 -                stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::Local);
 -            }
 +                if (bNS && (bFirstStep || DOMAINDECOMP(cr)))
 +                {
 +                    integrator->set(stateGpu->getCoordinates(), stateGpu->getVelocities(),
 +                                    stateGpu->getForces(), top.idef, *mdatoms, ekind->ngtc);
  
 -            const bool doTemperatureScaling =
 -                    (ir->etc != etcNO && do_per_step(step + ir->nsttcouple - 1, ir->nsttcouple));
 +                    // Copy data to the GPU after buffers might have being reinitialized
 +                    stateGpu->copyVelocitiesToGpu(state->v, AtomLocality::Local);
 +                    stateGpu->copyCoordinatesToGpu(state->x, AtomLocality::Local);
 +                }
  
 -            // This applies Leap-Frog, LINCS and SETTLE in succession
 -            integrator->integrate(stateGpu->getForcesReadyOnDeviceEvent(
 -                                          AtomLocality::Local, runScheduleWork->stepWork.useGpuFBufferOps),
 -                                  ir->delta_t, true, bCalcVir, shake_vir, doTemperatureScaling,
 -                                  ekind->tcstat, doParrinelloRahman, ir->nstpcouple * ir->delta_t, M);
 +                if (simulationWork.useGpuPme && !runScheduleWork->simulationWork.useGpuPmePpCommunication
 +                    && !thisRankHasDuty(cr, DUTY_PME))
 +                {
 +                    // The PME forces were recieved to the host, so have to be copied
 +                    stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::All);
 +                }
 +                else if (!runScheduleWork->stepWork.useGpuFBufferOps)
 +                {
 +                    // The buffer ops were not offloaded this step, so the forces are on the
 +                    // host and have to be copied
 +                    stateGpu->copyForcesToGpu(f.view().force(), AtomLocality::Local);
 +                }
  
 -            // Copy velocities D2H after update if:
 -            // - Globals are computed this step (includes the energy output steps).
 -            // - Temperature is needed for the next step.
 -            if (bGStat || needHalfStepKineticEnergy)
 -            {
 -                stateGpu->copyVelocitiesFromGpu(state->v, AtomLocality::Local);
 -                stateGpu->waitVelocitiesReadyOnHost(AtomLocality::Local);
 +                const bool doTemperatureScaling =
 +                        (ir->etc != etcNO && do_per_step(step + ir->nsttcouple - 1, ir->nsttcouple));
 +
 +                // This applies Leap-Frog, LINCS and SETTLE in succession
 +                integrator->integrate(
 +                        stateGpu->getForcesReadyOnDeviceEvent(
 +                                AtomLocality::Local, runScheduleWork->stepWork.useGpuFBufferOps),
 +                        ir->delta_t, true, bCalcVir, shake_vir, doTemperatureScaling, ekind->tcstat,
 +                        doParrinelloRahman, ir->nstpcouple * ir->delta_t, M);
 +
 +                // Copy velocities D2H after update if:
 +                // - Globals are computed this step (includes the energy output steps).
 +                // - Temperature is needed for the next step.
 +                if (bGStat || needHalfStepKineticEnergy)
 +                {
 +                    stateGpu->copyVelocitiesFromGpu(state->v, AtomLocality::Local);
 +                    stateGpu->waitVelocitiesReadyOnHost(AtomLocality::Local);
 +                }
              }
 -        }
 -        else
 -        {
 -            /* With multiple time stepping we need to do an additional normal
 -             * update step to obtain the virial, as the actual MTS integration
 -             * using an acceleration where the slow forces are multiplied by mtsFactor.
 -             * Using that acceleration would result in a virial with the slow
 -             * force contribution would be a factor mtsFactor too large.
 -             */
 -            if (fr->useMts && bCalcVir && constr != nullptr)
 +            else
              {
 -                upd.update_for_constraint_virial(*ir, *mdatoms, *state, f.view().forceWithPadding(), *ekind);
 +                /* With multiple time stepping we need to do an additional normal
 +                 * update step to obtain the virial, as the actual MTS integration
 +                 * using an acceleration where the slow forces are multiplied by mtsFactor.
 +                 * Using that acceleration would result in a virial with the slow
 +                 * force contribution would be a factor mtsFactor too large.
 +                 */
 +                if (fr->useMts && bCalcVir && constr != nullptr)
 +                {
 +                    upd.update_for_constraint_virial(*ir, *mdatoms, *state,
 +                                                     f.view().forceWithPadding(), *ekind);
  
 -                constrain_coordinates(constr, do_log, do_ene, step, state,
 -                                      upd.xp()->arrayRefWithPadding(), &dvdl_constr, bCalcVir, shake_vir);
 -            }
 +                    constrain_coordinates(constr, do_log, do_ene, step, state,
 +                                          upd.xp()->arrayRefWithPadding(), &dvdl_constr, bCalcVir,
 +                                          shake_vir);
 +                }
  
 -            ArrayRefWithPadding<const RVec> forceCombined =
 -                    (fr->useMts && step % ir->mtsLevels[1].stepFactor == 0)
 -                            ? f.view().forceMtsCombinedWithPadding()
 -                            : f.view().forceWithPadding();
 -            upd.update_coords(*ir, step, mdatoms, state, forceCombined, fcdata, ekind, M,
 -                              etrtPOSITION, cr, constr != nullptr);
 +                ArrayRefWithPadding<const RVec> forceCombined =
 +                        (fr->useMts && step % ir->mtsLevels[1].stepFactor == 0)
 +                                ? f.view().forceMtsCombinedWithPadding()
 +                                : f.view().forceWithPadding();
 +                upd.update_coords(*ir, step, mdatoms, state, forceCombined, fcdata, ekind, M,
 +                                  etrtPOSITION, cr, constr != nullptr);
  
 -            wallcycle_stop(wcycle, ewcUPDATE);
 +                wallcycle_stop(wcycle, ewcUPDATE);
  
 -            constrain_coordinates(constr, do_log, do_ene, step, state, upd.xp()->arrayRefWithPadding(),
 -                                  &dvdl_constr, bCalcVir && !fr->useMts, shake_vir);
 +                constrain_coordinates(constr, do_log, do_ene, step, state,
 +                                      upd.xp()->arrayRefWithPadding(), &dvdl_constr,
 +                                      bCalcVir && !fr->useMts, shake_vir);
  
 -            upd.update_sd_second_half(*ir, step, &dvdl_constr, mdatoms, state, cr, nrnb, wcycle,
 -                                      constr, do_log, do_ene);
 -            upd.finish_update(*ir, mdatoms, state, wcycle, constr != nullptr);
 -        }
 +                upd.update_sd_second_half(*ir, step, &dvdl_constr, mdatoms, state, cr, nrnb, wcycle,
 +                                          constr, do_log, do_ene);
 +                upd.finish_update(*ir, mdatoms, state, wcycle, constr != nullptr);
 +            }
  
 -        if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
 -        {
 -            updatePrevStepPullCom(pull_work, state);
 -        }
 +            if (ir->bPull && ir->pull->bSetPbcRefToPrevStepCOM)
 +            {
 +                updatePrevStepPullCom(pull_work, state);
 +            }
  
 -        if (ir->eI == eiVVAK)
 -        {
 -            /* erase F_EKIN and F_TEMP here? */
 -            /* just compute the kinetic energy at the half step to perform a trotter step */
 -            compute_globals(gstat, cr, ir, fr, ekind, makeConstArrayRef(state->x),
 -                            makeConstArrayRef(state->v), state->box, mdatoms, nrnb, &vcm, wcycle, enerd,
 -                            force_vir, shake_vir, total_vir, pres, constr, &nullSignaller, lastbox,
 -                            nullptr, &bSumEkinhOld, (bGStat ? CGLO_GSTAT : 0) | CGLO_TEMPERATURE);
 -            wallcycle_start(wcycle, ewcUPDATE);
 -            trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ4);
 -            /* now we know the scaling, we can compute the positions again */
 -            std::copy(cbuf.begin(), cbuf.end(), state->x.begin());
 -
 -            upd.update_coords(*ir, step, mdatoms, state, f.view().forceWithPadding(), fcdata, ekind,
 -                              M, etrtPOSITION, cr, constr != nullptr);
 -            wallcycle_stop(wcycle, ewcUPDATE);
 -
 -            /* do we need an extra constraint here? just need to copy out of as_rvec_array(state->v.data()) to upd->xp? */
 -            /* are the small terms in the shake_vir here due
 -             * to numerical errors, or are they important
 -             * physically? I'm thinking they are just errors, but not completely sure.
 -             * For now, will call without actually constraining, constr=NULL*/
 -            upd.finish_update(*ir, mdatoms, state, wcycle, false);
 -        }
 -        if (EI_VV(ir->eI))
 -        {
 -            /* this factor or 2 correction is necessary
 -               because half of the constraint force is removed
 -               in the vv step, so we have to double it.  See
 -               the Issue #1255.  It is not yet clear
 -               if the factor of 2 is exact, or just a very
 -               good approximation, and this will be
 -               investigated.  The next step is to see if this
 -               can be done adding a dhdl contribution from the
 -               rattle step, but this is somewhat more
 -               complicated with the current code. Will be
 -               investigated, hopefully for 4.6.3. However,
 -               this current solution is much better than
 -               having it completely wrong.
 -             */
 -            enerd->term[F_DVDL_CONSTR] += 2 * dvdl_constr;
 -        }
 -        else
 -        {
              enerd->term[F_DVDL_CONSTR] += dvdl_constr;
          }
  
      {
          if (ir->nstcalcenergy > 0)
          {
+             energyOutput.printEnergyConservation(fplog, ir->simulation_part, EI_MD(ir->eI));
              gmx::EnergyOutput::printAnnealingTemperatures(fplog, groups, &(ir->opts));
              energyOutput.printAverages(fplog, groups);
          }
index 08b35450d32939d50879399cd4b077e5906049d7,0c3586f7d68e510a7d4611e7820a8a8399470095..e98651f1adab6611e932cb430d0c9bd52c08911d
@@@ -58,7 -58,6 +58,7 @@@
  
  #include "nbnxm_gpu_data_mgmt.h"
  
 +#include "gromacs/mdtypes/interaction_const.h"
  #include "gromacs/nbnxm/gpu_data_mgmt.h"
  #include "gromacs/timing/gpu_timing.h"
  #include "gromacs/utility/cstringutil.h"
@@@ -96,9 -95,10 +96,9 @@@ void inline printEnvironmentVariableDep
      }
  }
  
 -int nbnxn_gpu_pick_ewald_kernel_type(const interaction_const_t& ic)
 +enum ElecType nbnxn_gpu_pick_ewald_kernel_type(const interaction_const_t& ic)
  {
      bool bTwinCut = (ic.rcoulomb != ic.rvdw);
 -    int  kernel_type;
  
      /* Benchmarking/development environment variables to force the use of
         analytical or tabulated Ewald kernel. */
              (getenv("GMX_GPU_NB_ANA_EWALD") != nullptr) || forceAnalyticalEwaldLegacy;
      const bool forceTabulatedEwald =
              (getenv("GMX_GPU_NB_TAB_EWALD") != nullptr) || forceTabulatedEwaldLegacy;
+     const bool forceTwinCutoffEwald =
+             (getenv("GMX_GPU_NB_EWALD_TWINCUT") != nullptr) || forceTwinCutoffEwaldLegacy;
  
      if (forceAnalyticalEwald && forceTabulatedEwald)
      {
  
      /* Use twin cut-off kernels if requested by bTwinCut or the env. var.
         forces it (use it for debugging/benchmarking only). */
-     if (!bTwinCut && ((getenv("GMX_GPU_NB_EWALD_TWINCUT") == nullptr) || forceTwinCutoffEwaldLegacy))
+     if (!bTwinCut && !forceTwinCutoffEwald)
      {
 -        kernel_type = bUseAnalyticalEwald ? eelTypeEWALD_ANA : eelTypeEWALD_TAB;
 +        return bUseAnalyticalEwald ? ElecType::EwaldAna : ElecType::EwaldTab;
      }
      else
      {
 -        kernel_type = bUseAnalyticalEwald ? eelTypeEWALD_ANA_TWIN : eelTypeEWALD_TAB_TWIN;
 +        return bUseAnalyticalEwald ? ElecType::EwaldAnaTwin : ElecType::EwaldTabTwin;
      }
 -
 -    return kernel_type;
  }
  
  void set_cutoff_parameters(NBParamGpu* nbp, const interaction_const_t* ic, const PairlistParams& listParams)
@@@ -194,7 -198,7 +196,7 @@@ void gpu_pme_loadbal_update_param(cons
  
      set_cutoff_parameters(nbp, ic, nbv->pairlistSets().params());
  
 -    nbp->eeltype = nbnxn_gpu_pick_ewald_kernel_type(*ic);
 +    nbp->elecType = nbnxn_gpu_pick_ewald_kernel_type(*ic);
  
      GMX_RELEASE_ASSERT(ic->coulombEwaldTables, "Need valid Coulomb Ewald correction tables");
      init_ewald_coulomb_force_table(*ic->coulombEwaldTables, nbp, *nb->deviceContext_);
@@@ -325,82 -329,7 +327,82 @@@ void gpu_reset_timings(nonbonded_verlet
  
  bool gpu_is_kernel_ewald_analytical(const NbnxmGpu* nb)
  {
 -    return ((nb->nbparam->eeltype == eelTypeEWALD_ANA) || (nb->nbparam->eeltype == eelTypeEWALD_ANA_TWIN));
 +    return ((nb->nbparam->elecType == ElecType::EwaldAna)
 +            || (nb->nbparam->elecType == ElecType::EwaldAnaTwin));
 +}
 +
 +enum ElecType nbnxmGpuPickElectrostaticsKernelType(const interaction_const_t* ic)
 +{
 +    if (ic->eeltype == eelCUT)
 +    {
 +        return ElecType::Cut;
 +    }
 +    else if (EEL_RF(ic->eeltype))
 +    {
 +        return ElecType::RF;
 +    }
 +    else if ((EEL_PME(ic->eeltype) || ic->eeltype == eelEWALD))
 +    {
 +        return nbnxn_gpu_pick_ewald_kernel_type(*ic);
 +    }
 +    else
 +    {
 +        /* Shouldn't happen, as this is checked when choosing Verlet-scheme */
 +        GMX_THROW(gmx::InconsistentInputError(
 +                gmx::formatString("The requested electrostatics type %s (%d) is not implemented in "
 +                                  "the GPU accelerated kernels!",
 +                                  EELTYPE(ic->eeltype), ic->eeltype)));
 +    }
 +}
 +
 +
 +enum VdwType nbnxmGpuPickVdwKernelType(const interaction_const_t* ic, int combRule)
 +{
 +    if (ic->vdwtype == evdwCUT)
 +    {
 +        switch (ic->vdw_modifier)
 +        {
 +            case eintmodNONE:
 +            case eintmodPOTSHIFT:
 +                switch (combRule)
 +                {
 +                    case ljcrNONE: return VdwType::Cut;
 +                    case ljcrGEOM: return VdwType::CutCombGeom;
 +                    case ljcrLB: return VdwType::CutCombLB;
 +                    default:
 +                        GMX_THROW(gmx::InconsistentInputError(gmx::formatString(
 +                                "The requested LJ combination rule %s (%d) is not implemented in "
 +                                "the GPU accelerated kernels!",
 +                                enum_name(combRule, ljcrNR, c_ljcrNames), combRule)));
 +                }
 +            case eintmodFORCESWITCH: return VdwType::FSwitch;
 +            case eintmodPOTSWITCH: return VdwType::PSwitch;
 +            default:
 +                GMX_THROW(gmx::InconsistentInputError(
 +                        gmx::formatString("The requested VdW interaction modifier %s (%d) is not "
 +                                          "implemented in the GPU accelerated kernels!",
 +                                          INTMODIFIER(ic->vdw_modifier), ic->vdw_modifier)));
 +        }
 +    }
 +    else if (ic->vdwtype == evdwPME)
 +    {
 +        if (ic->ljpme_comb_rule == ljcrGEOM)
 +        {
 +            assert(combRule == ljcrGEOM);
 +            return VdwType::EwaldGeom;
 +        }
 +        else
 +        {
 +            assert(combRule == ljcrLB);
 +            return VdwType::EwaldLB;
 +        }
 +    }
 +    else
 +    {
 +        GMX_THROW(gmx::InconsistentInputError(gmx::formatString(
 +                "The requested VdW type %s (%d) is not implemented in the GPU accelerated kernels!",
 +                EVDWTYPE(ic->vdwtype), ic->vdwtype)));
 +    }
  }
  
  } // namespace Nbnxm
index dee4ce2bfbb5d233536223cd8283160cebd3afda,0d1f9fd850a50b3bcd42f27b5995bdce5e153ca4..47fe1b582fde44ae9068248f2df11c5e78bc6460
@@@ -94,6 -94,28 +94,6 @@@ const std::string& simdString(SimdType 
      return name.at(s);
  }
  
 -namespace
 -{
 -
 -
 -//! Helper to detect correct AMD Zen architecture.
 -bool cpuIsAmdZen1(const CpuInfo& cpuInfo)
 -{
 -    // Both Zen/Zen+/Zen2 have family==23
 -    // Model numbers for Zen:
 -    // 1)  Naples, Whitehaven, Summit ridge, and Snowy Owl
 -    // 17) Raven ridge
 -    // Model numbers for Zen+:
 -    // 8)  Pinnacle Ridge
 -    // 24) Picasso
 -    return (cpuInfo.vendor() == gmx::CpuInfo::Vendor::Amd && cpuInfo.family() == 23
 -            && (cpuInfo.model() == 1 || cpuInfo.model() == 17 || cpuInfo.model() == 8
 -                || cpuInfo.model() == 24));
 -}
 -
 -} // namespace
 -
 -
  SimdType simdSuggested(const CpuInfo& c)
  {
      SimdType suggested = SimdType::None;
@@@ -311,7 -333,7 +311,7 @@@ bool simdCheck(gmx::SimdType wanted, FI
                  simdString(compiled).c_str(), simdString(wanted).c_str()));
  #if GMX_SIMD_ARM_SVE
      }
-     else if ((compiled == SimdType::Arm_Sve) && (svcntb() != GMX_SIMD_ARM_SVE_LENGTH / 8))
+     else if ((compiled == SimdType::Arm_Sve) && (svcntb() != GMX_SIMD_ARM_SVE_LENGTH_VALUE / 8))
      {
          logMsg  = wrapper.wrapToString(formatString(
                  "Longest SVE length requested by all nodes in run: %d\n"
                  "This program was compiled for different hardware than you are running on, "
                  "which will lead to incorrect behavior.\n"
                  "Aborting",
-                 GMX_SIMD_ARM_SVE_LENGTH, svcntb() * 8));
+                 GMX_SIMD_ARM_SVE_LENGTH_VALUE, svcntb() * 8));
          warnMsg = wrapper.wrapToString(formatString(
                  "Compiled SVE Length: %d, but for this process requires %ld (see log).",
-                 GMX_SIMD_ARM_SVE_LENGTH, svcntb() * 8));
+                 GMX_SIMD_ARM_SVE_LENGTH_VALUE, svcntb() * 8));
  #endif
      }
  
          fprintf(stderr, "%s\n", warnMsg.c_str());
      }
  #if GMX_SIMD_ARM_SVE
-     if ((compiled == SimdType::Arm_Sve) && (svcntb() != GMX_SIMD_ARM_SVE_LENGTH / 8))
+     if ((compiled == SimdType::Arm_Sve) && (svcntb() != GMX_SIMD_ARM_SVE_LENGTH_VALUE / 8))
      {
          gmx_exit_on_fatal_error(ExitType_Abort, 1);
      }
index f1209b75aa1b251348c187559b0699cf1370e8a1,b07d01d09ceb6d4024a5b429dd9d9891faa67efe..aa8a144a22c497aec57b2d4bb5b624242f80b6f3
@@@ -41,20 -41,17 +41,21 @@@ target_compile_definitions(mdrun_objli
  target_include_directories(mdrun_objlib SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
  # Should be possible to remove this when resolving #3290
  target_include_directories(mdrun_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
 +target_link_libraries(mdrun_objlib PRIVATE common)
 +target_link_libraries(mdrun_objlib PRIVATE legacy_api)
 +# TODO: Explicitly link specific modules.
 +target_link_libraries(mdrun_objlib PRIVATE legacy_modules)
  
  if(GMX_FAHCORE)
      # The lack of a real source file here alongside the object library
      # may break some generators, according to CMake documentation. If
      # so, we can consider adding some dummy file to make it work.
      add_library(fahcore $<TARGET_OBJECTS:mdrun_objlib>)
 -    target_link_libraries(fahcore PRIVATE ${GMX_COMMON_LIBRARIES})
 +    target_link_libraries(fahcore PRIVATE ${GMX_COMMON_LIBRARIES} legacy_api)
  elseif(GMX_BUILD_MDRUN_ONLY)
      add_executable(mdrun $<TARGET_OBJECTS:mdrun_objlib> mdrun_main.cpp)
      gmx_target_compile_options(mdrun)
+     target_include_directories(mdrun SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
      target_compile_definitions(mdrun PRIVATE HAVE_CONFIG_H)
      target_link_libraries(mdrun libgromacs
          ${GMX_COMMON_LIBRARIES}
@@@ -78,13 -75,7 +79,13 @@@ else(
      gmx_target_compile_options(view_objlib)
      target_compile_definitions(view_objlib PRIVATE HAVE_CONFIG_H)
      target_include_directories(view_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
 +    target_link_libraries(view_objlib PRIVATE common legacy_api)
 +    # TODO: Explicitly link specific modules.
 +    target_link_libraries(view_objlib PRIVATE legacy_modules)
      add_library(gmx_objlib OBJECT ${GMX_MAIN_SOURCES})
 +    target_link_libraries(gmx_objlib PRIVATE common legacy_api)
 +    # TODO: Explicitly link specific modules.
 +    target_link_libraries(gmx_objlib PRIVATE legacy_modules)
      target_include_directories(gmx_objlib SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/src/external)
      target_include_directories(gmx_objlib SYSTEM BEFORE PRIVATE ${PROJECT_SOURCE_DIR}/src/external/thread_mpi/include)
      add_executable(gmx
      add_executable(Gromacs::gmx ALIAS gmx)
      gmx_target_compile_options(gmx)
      target_compile_definitions(gmx PRIVATE HAVE_CONFIG_H)
 -    target_link_libraries(gmx libgromacs
 -        ${GMX_COMMON_LIBRARIES}
 -        ${GMX_EXE_LINKER_FLAGS})
 +    target_link_libraries(gmx PRIVATE
 +                          common
 +                          libgromacs
 +                          ${GMX_COMMON_LIBRARIES}
 +                          ${GMX_EXE_LINKER_FLAGS})
      if(GMX_X11)
          target_link_libraries(gmx ${X11_LIBRARIES})
      endif()
index da352962e1a6101822d85d5ec49d87268c1fae09,5a06c351318f4ad0d88848e12b741ee4087db4d1..c42f02d9e91ca741d13b005bb2c89d0fcfb4047d
@@@ -44,7 -44,7 +44,7 @@@
  
  #include "gmxpre.h"
  
 -#include "test_hardware_environment.h"
 +#include "testutils/test_hardware_environment.h"
  
  #include <memory>
  
@@@ -99,6 -99,7 +99,7 @@@ void TestHardwareEnvironment::SetUp(
      // Constructing contexts for all compatible GPUs - will be empty on non-GPU builds
      for (const DeviceInformation& compatibleDeviceInfo : getCompatibleDevices(hardwareInfo_->deviceInfoList))
      {
+         setActiveDevice(compatibleDeviceInfo);
          std::string description = getDeviceInformationString(compatibleDeviceInfo);
          testDeviceList_.emplace_back(std::make_unique<TestDevice>(description.c_str(), compatibleDeviceInfo));
      }