#
# 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.
# GPU update flag enables GPU update+constraints as well as buffer ops (dependency)
if context.opts.gpuupdate:
context.env.set_env_var('GMX_FORCE_UPDATE_DEFAULT_GPU', "1")
+ context.env.set_env_var('GMX_GPU_DD_COMMS', "1")
+ context.env.set_env_var('GMX_GPU_PME_PP_COMMS', "1")
regressiontests_path = context.workspace.get_project_dir(Project.REGRESSIONTESTS)
# GROMACS 2018 3
# GROMACS 2019 4
# GROMACS 2020 5
+# GROMACS 2021 6
# LIBRARY_SOVERSION_MINOR so minor version for the built libraries.
# Should be increased for each release that changes only the implementation.
# In GROMACS, the typical policy is to increase it for each patch version
# The GROMACS convention is that these are the version number of the next
# release that is going to be made from this branch.
-set(GMX_VERSION_MAJOR 2020)
-set(GMX_VERSION_PATCH 1)
+set(GMX_VERSION_MAJOR 2021)
+set(GMX_VERSION_PATCH 0)
# The suffix, on the other hand, is used mainly for betas and release
# candidates, where it signifies the most recent such release from
# this branch; it will be empty before the first such release, as well
# here. The important thing is to minimize the chance of third-party
# code being able to dynamically link with a version of libgromacs
# that might not work.
-set(LIBRARY_SOVERSION_MAJOR 5)
+set(LIBRARY_SOVERSION_MAJOR 6)
set(LIBRARY_SOVERSION_MINOR 0)
set(LIBRARY_VERSION ${LIBRARY_SOVERSION_MAJOR}.${LIBRARY_SOVERSION_MINOR}.0)
endif()
set(REGRESSIONTEST_VERSION "${GMX_VERSION_STRING}")
-set(REGRESSIONTEST_BRANCH "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
# naming affects the md5sum that has to go here, and if it isn't right
# release workflow will report a failure.
- set(REGRESSIONTEST_MD5SUM "42e3bfe74a8e8bf8e38919e10aaf8fa1" CACHE INTERNAL "MD5 sum of the regressiontests tarball for this GROMACS version")
+ set(REGRESSIONTEST_MD5SUM "2fe8e35878bc9ee3cf60e92d5b250175" CACHE INTERNAL "MD5 sum of the regressiontests tarball for this GROMACS version")
math(EXPR GMX_VERSION_NUMERIC
"${GMX_VERSION_MAJOR}*10000 + ${GMX_VERSION_PATCH}")
how-to/visualize.rst
install-guide/index.rst
release-notes/index.rst
+ release-notes/2021/major/highlights.rst
+ release-notes/2021/major/features.rst
+ release-notes/2021/major/performance.rst
+ release-notes/2021/major/tools.rst
+ release-notes/2021/major/bugs-fixed.rst
+ release-notes/2021/major/removed-functionality.rst
+ release-notes/2021/major/deprecated-functionality.rst
+ release-notes/2021/major/portability.rst
+ release-notes/2021/major/miscellaneous.rst
+ release-notes/2020/2020.1.rst
release-notes/2020/major/highlights.rst
release-notes/2020/major/features.rst
release-notes/2020/major/performance.rst
# 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
-q -b html
-w sphinx-html.log
-d "${SPHINX_CACHE_DIR}"
+ ${SPHINX_CONFIG_OVERRIDES}
"${SPHINX_INPUT_DIR}"
"${HTML_OUTPUT_DIR}"
WORKING_DIRECTORY
functionality supported, whereas patch releases contain only fixes for
issues identified in the corresponding major releases.
-Two versions of |Gromacs| are under active maintenance, the 2020
-series and the 2019 series. In the latter, only highly conservative
+Two versions of |Gromacs| are under active maintenance, the 2021
+series and the 2020 series. In the latter, only highly conservative
fixes will be made, and only to address issues that affect scientific
correctness. Naturally, some of those releases will be made after the
-year 2019 ends, but we keep 2019 in the name so users understand how
+year 2020 ends, but we keep 2019 in the name so users understand how
up to date their version is. Such fixes will also be incorporated into
-the 2020 release series, as appropriate. Around the time the 2021
-release is made, the 2019 series will no longer be maintained.
+the 2021 release series, as appropriate. Around the time the 2022
+release is made, the 2020 series will no longer be maintained.
Where issue numbers are reported in these release notes, more details
can be found at https://redmine.gromacs.org at that issue number.
+|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
---------------------
+ Patch releases
+ ^^^^^^^^^^^^^^
+
+ .. toctree::
+ :maxdepth: 1
+
+ 2020/2020.1
+
Major release
^^^^^^^^^^^^^
.. 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
=====================
``GMX_FORCE_UPDATE``
update forces when invoking ``mdrun -rerun``.
+ ``GMX_FORCE_UPDATE_DEFAULT_GPU``
+ Force update to run on the GPU by default, overriding the ``mdrun -update auto`` option. Works similar to setting
+ ``mdrun -update gpu``, but (1) falls back to the CPU code-path, if set with input that is not supported and
+ (2) can be used to run update on GPUs in multi-rank cases. The latter case should be
+ considered experimental since it lacks substantial testing. Also, GPU update is only supported with the GPU direct
+ communications and ``GMX_FORCE_UPDATE_DEFAULT_GPU`` variable should be set simultaneously with ``GMX_GPU_DD_COMMS``
+ and ``GMX_GPU_PME_PP_COMMS`` environment variables in multi-rank case. Does not override ``mdrun -update cpu``.
+
``GMX_GPU_ID``
set in the same way as ``mdrun -gpu_id``, ``GMX_GPU_ID``
allows the user to specify different GPU IDs for different ranks, which can be useful for selecting different
#
# 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.
mrcdensitymap.cpp
mrcdensitymapheader.cpp
readinp.cpp
+ fileioxdrserializer.cpp
)
if (GMX_USE_TNG)
list(APPEND test_sources tngio.cpp)
--- /dev/null
- * Copyright (c) 2019, by the GROMACS development team, led by
+ /*
+ * This file is part of the GROMACS molecular simulation package.
+ *
++ * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+ /*! \internal \file
+ * \brief
+ * Tests for gmx::FileIOXdrSerializer.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_fileio
+ */
+
+ #include "gmxpre.h"
+
+ #include <gtest/gtest.h>
+
+ #include "gromacs/fileio/gmxfio.h"
+ #include "gromacs/fileio/gmxfio_xdr.h"
+ #include "gromacs/utility/futil.h"
+
+ #include "testutils/testfilemanager.h"
+
+ namespace gmx
+ {
+ namespace test
+ {
+ namespace
+ {
+ union IntAndFloat32 {
+ std::int32_t int32Value_;
+ float floatValue_;
+ };
+
+ union IntAndFloat64 {
+ std::int64_t int64Value_;
+ double doubleValue_;
+ };
+
+ //! Constants used for testing endian swap operations
+ //! \{
+ constexpr std::int16_t c_int16Value = static_cast<std::int16_t>(0x7A2B);
+ constexpr std::int32_t c_int32Value = static_cast<std::int32_t>(0x78ABCDEF);
+ constexpr std::int64_t c_int64Value = static_cast<std::int64_t>(0x78ABCDEF12345678);
+
+ constexpr const IntAndFloat32 c_intAndFloat32{ c_int32Value };
+ constexpr const IntAndFloat64 c_intAndFloat64{ c_int64Value };
+ //! \}
+
+ //! Return the integer used for testing, depending on the size of int.
+ constexpr int integerSizeDependentTestingValue()
+ {
+ return sizeof(int) == 4 ? c_int32Value : sizeof(int) == 8 ? c_int64Value : c_int16Value;
+ }
+
+ class FileIOXdrSerializerTest : public ::testing::Test
+ {
+ public:
+ ~FileIOXdrSerializerTest() override
+ {
+ if (file_)
+ {
+ gmx_fio_close(file_);
+ }
+ }
+ struct SerializerValues
+ {
+ bool boolValue_ = true;
+ unsigned char unsignedCharValue_ = 0x78;
+ char charValue_ = 0x78;
+ unsigned short unsignedShortValue_ = static_cast<unsigned short>(c_int16Value);
+ std::int32_t int32Value_ = c_int32Value;
+ float floatValue_ = c_intAndFloat32.floatValue_;
+ std::int64_t int64Value_ = c_int64Value;
+ double doubleValue_ = c_intAndFloat64.doubleValue_;
+ int intValue_ = integerSizeDependentTestingValue();
+ real realValue_ = std::is_same<real, double>::value
+ ? static_cast<real>(c_intAndFloat64.doubleValue_)
+ : static_cast<real>(c_intAndFloat32.floatValue_);
+ } defaultValues_;
+
+ TestFileManager fileManager_;
+ // Make sure the file extension is one that gmx_fio_open will
+ // recognize to open as binary, even though we're just abusing it
+ // to write arbitrary XDR output.
+ std::string filename_ = fileManager_.getTemporaryFilePath("data.edr");
+ t_fileio* file_ = nullptr;
+ };
+
+ TEST_F(FileIOXdrSerializerTest, SizeIsCorrect)
+ {
+ file_ = gmx_fio_open(filename_.c_str(), "w");
+ FileIOXdrSerializer serializer(file_);
+ // These types all have well-defined widths in bytes AFTER XDR serialization,
+ // which we can test below.
+ serializer.doBool(&defaultValues_.boolValue_); // 4 bytes
+ serializer.doChar(&defaultValues_.charValue_); // 4 bytes
+ serializer.doInt32(&defaultValues_.int32Value_); // 4 bytes
+ serializer.doInt64(&defaultValues_.int64Value_); // 8 bytes
+ serializer.doFloat(&defaultValues_.floatValue_); // 4 bytes
+ serializer.doDouble(&defaultValues_.doubleValue_); // 8 bytes
+ std::vector<char> charBuffer = { 'a', 'b', 'c' };
+ serializer.doCharArray(charBuffer.data(), charBuffer.size()); // 12 bytes
+ serializer.doOpaque(charBuffer.data(), charBuffer.size()); // 4 bytes
+ std::vector<int32_t> int32Buffer = { 0x1BCDEF78, 0x654321FE };
+ serializer.doInt32Array(int32Buffer.data(), int32Buffer.size()); // 8 bytes
+ std::vector<int64_t> int64Buffer = { 0x1BCDEF78654321FE, 0x3726ABFEAB34716C };
+ serializer.doInt64Array(int64Buffer.data(), int64Buffer.size()); // 16 bytes
+ gmx_fio_close(file_);
+
+ file_ = gmx_fio_open(filename_.c_str(), "r");
+
+ // Determine file size
+ gmx_fseek(gmx_fio_getfp(file_), 0, SEEK_END);
+ gmx_off_t fileSize = gmx_fio_ftell(file_);
+ EXPECT_EQ(fileSize, 72);
+ }
+
+ } // namespace
+ } // namespace test
+ } // namespace gmx
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
-- * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
++ * Copyright (c) 2013,2014,2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
"multiple-time-stepping scheme for a twin-range cut-off. When used with "
"a single-range cut-off (or a correct Trotter multiple-time-stepping scheme), "
"physical properties, such as the density, might differ from the intended values. "
- "Check if molecules in your system are affected by such issues before proceeding. "
- "Further information may be available at https://redmine.gromacs.org/issues/2884.");
+ "Since there are researchers actively working on validating GROMOS with modern "
+ "integrators we have not yet removed the GROMOS force fields, but you should be "
+ "aware of these issues and check if molecules in your system are affected before "
+ "proceeding. "
+ "Further information is available at https://redmine.gromacs.org/issues/2884 , "
+ "and a longer explanation of our decision to remove physically incorrect "
+ "algorithms "
+ "can be found at https://doi.org/10.26434/chemrxiv.11474583.v1 .");
}
cpp_done(handle);
/* 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;
}
*
* 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.
// #3205 for more information)
#if defined(__GNUC__) && defined(__i386__) && defined(__OPTIMIZE__)
# pragma GCC push_options
- # pragma GCC optimize("O2")
+ # pragma GCC optimize("O1")
# define avoid_gcc_i386_o3_code_generation_bug
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
-- * Copyright (c) 2019, by the GROMACS development team, led by
++ * Copyright (c) 2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* 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>
float3* d_v,
const real invdt,
const bool computeVirial,
- tensor virialScaled)
+ tensor virialScaled,
+ const PbcAiuc pbcAiuc)
{
ensureNoPendingCudaError("In CUDA version of LINCS");
}
config.stream = commandStream_;
+ kernelParams_.pbcAiuc = pbcAiuc;
+
const auto kernelArgs =
prepareGpuKernelArguments(kernelPtr, config, &kernelParams_, &d_x, &d_xp, &d_v, &invdt);
}
}
- /*! \brief Constructs and returns an atom constraint adjacency list
- *
- * Each constraint will be represented as a tuple, containing index of the second
- * constrained atom, index of the constraint and a sign that indicates the order of atoms in
- * which they are listed. Sign is needed to compute the mass factors.
- */
- static std::vector<std::vector<std::tuple<int, int, int>>>
+ //! Helper type for discovering coupled constraints
+ struct AtomsAdjacencyListElement
+ {
+ AtomsAdjacencyListElement(const int indexOfSecondConstrainedAtom,
+ const int indexOfConstraint,
+ const int signFactor) :
+ indexOfSecondConstrainedAtom_(indexOfSecondConstrainedAtom),
+ indexOfConstraint_(indexOfConstraint),
+ signFactor_(signFactor)
+ {
+ }
+ //! The index of the other atom constrained to this atom.
+ int indexOfSecondConstrainedAtom_;
+ //! The index of this constraint in the container of constraints.
+ int indexOfConstraint_;
+ /*! \brief A multiplicative factor that indicates the relative
+ * order of the atoms in the atom list.
+ *
+ * Used for computing the mass factor of this constraint
+ * relative to any coupled constraints. */
+ int signFactor_;
+ };
+ //! Constructs and returns an atom constraint adjacency list
+ static std::vector<std::vector<AtomsAdjacencyListElement>>
constructAtomsAdjacencyList(const int numAtoms, ArrayRef<const int> iatoms)
{
const int stride = 1 + NRAL(F_CONSTR);
const int numConstraints = iatoms.ssize() / stride;
- std::vector<std::vector<std::tuple<int, int, int>>> atomsAdjacencyList(numAtoms);
+ std::vector<std::vector<AtomsAdjacencyListElement>> atomsAdjacencyList(numAtoms);
for (int c = 0; c < numConstraints; c++)
{
int a1 = iatoms[stride * c + 1];
// Each constraint will be represented as a tuple, containing index of the second
// constrained atom, index of the constraint and a sign that indicates the order of atoms in
// which they are listed. Sign is needed to compute the mass factors.
- atomsAdjacencyList[a1].push_back(std::make_tuple(a2, c, +1));
- atomsAdjacencyList[a2].push_back(std::make_tuple(a1, c, -1));
+ atomsAdjacencyList[a1].emplace_back(a2, c, +1);
+ atomsAdjacencyList[a2].emplace_back(a1, c, -1);
}
return atomsAdjacencyList;
*/
inline int countCoupled(int a,
ArrayRef<int> numCoupledConstraints,
- ArrayRef<const std::vector<std::tuple<int, int, int>>> atomsAdjacencyList)
+ ArrayRef<const std::vector<AtomsAdjacencyListElement>> atomsAdjacencyList)
{
int counted = 0;
for (const auto& adjacentAtom : atomsAdjacencyList[a])
{
- const int c2 = std::get<1>(adjacentAtom);
+ const int c2 = adjacentAtom.indexOfConstraint_;
if (numCoupledConstraints[c2] == -1)
{
numCoupledConstraints[c2] = 0; // To indicate we've been here
- counted += 1 + countCoupled(std::get<0>(adjacentAtom), numCoupledConstraints, atomsAdjacencyList);
+ counted += 1
+ + countCoupled(adjacentAtom.indexOfSecondConstrainedAtom_,
+ numCoupledConstraints, atomsAdjacencyList);
}
}
return counted;
*/
inline void addWithCoupled(ArrayRef<const int> iatoms,
const int stride,
- ArrayRef<const std::vector<std::tuple<int, int, int>>> atomsAdjacencyList,
+ ArrayRef<const std::vector<AtomsAdjacencyListElement>> atomsAdjacencyList,
ArrayRef<int> splitMap,
const int c,
int* currentMapIndex)
const int a1 = iatoms[stride * c + 1 + atomIndexInConstraint];
for (const auto& adjacentAtom : atomsAdjacencyList[a1])
{
- const int c2 = std::get<1>(adjacentAtom);
+ const int c2 = adjacentAtom.indexOfConstraint_;
if (c2 != c)
{
addWithCoupled(iatoms, stride, atomsAdjacencyList, splitMap, c2, currentMapIndex);
* numCoupledConstraints vector is also used to keep track if the constrain was already counted.
*/
static std::vector<int> countNumCoupledConstraints(ArrayRef<const int> iatoms,
- ArrayRef<const std::vector<std::tuple<int, int, int>>> atomsAdjacencyList)
+ ArrayRef<const std::vector<AtomsAdjacencyListElement>> atomsAdjacencyList)
{
const int stride = 1 + NRAL(F_CONSTR);
const int numConstraints = iatoms.ssize() / stride;
coupledConstraintsCountsHost.at(splitMap.at(c1)) = 0;
int c1a1 = iatoms[stride * c1 + 1];
int c1a2 = iatoms[stride * c1 + 2];
- int c2;
- int c2a1;
- int c2a2;
-
- int sign;
- // Constraints, coupled trough the first atom.
- c2a1 = c1a1;
- for (unsigned j = 0; j < atomsAdjacencyList.at(c1a1).size(); j++)
+ // Constraints, coupled through the first atom.
+ int c2a1 = c1a1;
+ for (const auto& atomAdjacencyList : atomsAdjacencyList[c1a1])
{
-
- std::tie(c2a2, c2, sign) = atomsAdjacencyList.at(c1a1).at(j);
+ int c2 = atomAdjacencyList.indexOfConstraint_;
if (c1 != c2)
{
+ int c2a2 = atomAdjacencyList.indexOfSecondConstrainedAtom_;
+ int sign = atomAdjacencyList.signFactor_;
int index = kernelParams_.numConstraintsThreads
* coupledConstraintsCountsHost.at(splitMap.at(c1))
+ splitMap.at(c1);
// Constraints, coupled through the second atom.
c2a1 = c1a2;
- for (unsigned j = 0; j < atomsAdjacencyList.at(c1a2).size(); j++)
+ for (const auto& atomAdjacencyList : atomsAdjacencyList[c1a2])
{
-
- std::tie(c2a2, c2, sign) = atomsAdjacencyList.at(c1a2).at(j);
+ int c2 = atomAdjacencyList.indexOfConstraint_;
if (c1 != c2)
{
+ int c2a2 = atomAdjacencyList.indexOfSecondConstrainedAtom_;
+ int sign = atomAdjacencyList.signFactor_;
int index = kernelParams_.numConstraintsThreads
* coupledConstraintsCountsHost.at(splitMap.at(c1))
+ splitMap.at(c1);
GpuApiCallBehavior::Sync, nullptr);
}
-void LincsCuda::setPbc(const t_pbc* pbc)
-{
- setPbcAiuc(pbc->ndim_ePBC, pbc->box, &kernelParams_.pbcAiuc);
-}
-
} // namespace gmx
*
* 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.
/* \brief Launch end-of-step GPU tasks: buffer clearing and rolling pruning.
*
- * TODO: eliminate the \p useGpuNonbonded and \p useGpuNonbonded when these are
+ * TODO: eliminate \p useGpuPmeOnThisRank when this is
* incorporated in DomainLifetimeWorkload.
*/
static void launchGpuEndOfStepTasks(nonbonded_verlet_t* nbv,
gmx_pme_t* pmedata,
gmx_enerdata_t* enerd,
const gmx::MdrunScheduleWorkload& runScheduleWork,
- bool useGpuNonbonded,
- bool useGpuPme,
+ bool useGpuPmeOnThisRank,
int64_t step,
gmx_wallcycle_t wcycle)
{
- if (useGpuNonbonded)
+ if (runScheduleWork.simulationWork.useGpuNonbonded)
{
/* Launch pruning before buffer clearing because the API overhead of the
* clear kernel launches can leave the GPU idle while it could be running
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
- if (useGpuPme)
+ if (useGpuPmeOnThisRank)
{
pme_gpu_reinit_computation(pmedata, wcycle);
}
}
wallcycle_stop(wcycle, ewcLAUNCH_GPU);
}
- }
- if (stepWork.doNeighborSearch)
- {
// Need to run after the GPU-offload bonded interaction lists
// are set up to be able to determine whether there is bonded work.
runScheduleWork->domainWork = setupDomainLifetimeWorkload(
wallcycle_start_nocount(wcycle, ewcNS);
wallcycle_sub_start(wcycle, ewcsNBS_SEARCH_LOCAL);
/* Note that with a GPU the launch overhead of the list transfer is not timed separately */
- nbv->constructPairlist(InteractionLocality::Local, &top->excls, step, nrnb);
+ nbv->constructPairlist(InteractionLocality::Local, top->excls, step, nrnb);
nbv->setupGpuShortRangeWork(fr->gpuBonded, InteractionLocality::Local);
wallcycle_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);
// Note: GPU update + DD without direct communication is not supported,
// a waitCoordinatesReadyOnHost() should be issued if it will be.
GMX_ASSERT(!simulationWork.useGpuUpdate,
- "GPU update is not supported with halo exchange");
+ "GPU update is not supported with CPU halo exchange");
dd_move_x(cr->dd, box, x.unpaddedArrayRef(), wcycle);
}
}
launchGpuEndOfStepTasks(nbv, fr->gpuBonded, fr->pmedata, enerd, *runScheduleWork,
- simulationWork.useGpuNonbonded, useGpuPmeOnThisRank, step, wcycle);
+ useGpuPmeOnThisRank, step, wcycle);
if (DOMAINDECOMP(cr))
{
*
* 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.
const bool useUpdateGroups = cr->dd ? ddUsesUpdateGroups(*cr->dd) : false;
useGpuForUpdate = decideWhetherToUseGpuForUpdate(
- devFlags.forceGpuUpdateDefault, useDomainDecomposition, useUpdateGroups, useGpuForPme,
- useGpuForNonbonded, updateTarget, gpusWereDetected, *inputrec, mtop, doEssentialDynamics,
- gmx_mtop_ftype_count(mtop, F_ORIRES) > 0, replExParams.exchangeInterval > 0, doRerun);
+ devFlags.forceGpuUpdateDefault, useDomainDecomposition, useUpdateGroups, pmeRunMode,
+ domdecOptions.numPmeRanks > 0, useGpuForNonbonded, updateTarget, gpusWereDetected,
+ *inputrec, mtop, doEssentialDynamics, gmx_mtop_ftype_count(mtop, F_ORIRES) > 0,
+ replExParams.exchangeInterval > 0, doRerun, mdlog);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
/* This call is not included in init_domain_decomposition mainly
* because fr->cginfo_mb is set later.
*/
- dd_init_bondeds(fplog, cr->dd, &mtop, vsite.get(), inputrec,
+ dd_init_bondeds(fplog, cr->dd, mtop, vsite.get(), inputrec,
domdecOptions.checkBondedInteractions, fr->cginfo_mb);
}
}
// 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)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
return gpusWereDetected && usingOurCpuForPmeOrEwald;
}
- bool decideWhetherToUseGpuForUpdate(const bool forceGpuUpdateDefault,
- const bool isDomainDecomposition,
- const bool useUpdateGroups,
- const bool useGpuForPme,
- const bool useGpuForNonbonded,
- const TaskTarget updateTarget,
- const bool gpusWereDetected,
- const t_inputrec& inputrec,
- const gmx_mtop_t& mtop,
- const bool useEssentialDynamics,
- const bool doOrientationRestraints,
- const bool useReplicaExchange,
- const bool doRerun)
+ bool decideWhetherToUseGpuForUpdate(const bool forceGpuUpdateDefault,
+ const bool isDomainDecomposition,
+ const bool useUpdateGroups,
+ const PmeRunMode pmeRunMode,
+ const bool havePmeOnlyRank,
+ const bool useGpuForNonbonded,
+ const TaskTarget updateTarget,
+ const bool gpusWereDetected,
+ const t_inputrec& inputrec,
+ const gmx_mtop_t& mtop,
+ const bool useEssentialDynamics,
+ const bool doOrientationRestraints,
+ const bool useReplicaExchange,
+ const bool doRerun,
+ const gmx::MDLogger& mdlog)
{
// '-update cpu' overrides the environment variable, '-update auto' does not
// Using the GPU-version of update if:
// 1. PME is on the GPU (there should be a copy of coordinates on GPU for PME spread), or
// 2. Non-bonded interactions are on the GPU.
- if (!(useGpuForPme || useGpuForNonbonded))
+ if (pmeRunMode == PmeRunMode::CPU && !useGpuForNonbonded)
{
errorMessage +=
"Either PME or short-ranged non-bonded interaction tasks must run on the GPU.\n";
}
+ // Since only direct GPU communications are supported with GPU update, PME should be fully offloaded in DD and PME only cases.
+ if (pmeRunMode != PmeRunMode::GPU && (isDomainDecomposition || havePmeOnlyRank))
+ {
+ errorMessage += "PME should run on GPU.\n";
+ }
if (!gpusWereDetected)
{
errorMessage += "Compatible GPUs must have been found.\n";
if (!errorMessage.empty())
{
- if (updateTarget == TaskTarget::Gpu)
+ if (updateTarget != TaskTarget::Gpu && forceGpuUpdateDefault)
+ {
+ GMX_LOG(mdlog.warning)
+ .asParagraph()
+ .appendText(
+ "Update task on the GPU was required, by the "
+ "GMX_FORCE_UPDATE_DEFAULT_GPU environment variable, but the following "
+ "condition(s) were not satisfied:");
+ GMX_LOG(mdlog.warning).asParagraph().appendText(errorMessage.c_str());
+ GMX_LOG(mdlog.warning).asParagraph().appendText("Will use CPU version of update.");
+ }
+ else if (updateTarget == TaskTarget::Gpu)
{
std::string prefix = gmx::formatString(
"Update task on the GPU was required,\n"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
struct gmx_hw_info_t;
struct gmx_mtop_t;
struct t_inputrec;
+ enum class PmeRunMode;
namespace gmx
{
+ class MDLogger;
+
//! Record where a compute task is targetted.
enum class TaskTarget : int
{
* \param[in] forceGpuUpdateDefault If update should run on GPU by default.
* \param[in] isDomainDecomposition Whether there more than one domain.
* \param[in] useUpdateGroups If the constraints can be split across domains.
- * \param[in] useGpuForPme Whether GPUs will be used for PME interactions.
+ * \param[in] pmeRunMode PME running mode: CPU, GPU or mixed.
+ * \param[in] havePmeOnlyRank If there is a PME-only rank in the simulation.
* \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
* \param[in] updateTarget User choice for running simulation on GPU.
* \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
* \param[in] doOrientationRestraints If orientation restraints are enabled.
* \param[in] useReplicaExchange If this is a REMD simulation.
* \param[in] doRerun It this is a rerun.
+ * \param[in] mdlog MD logger.
*
* \returns Whether complete simulation can be run on GPU.
* \throws std::bad_alloc If out of memory
* InconsistentInputError If the user requirements are inconsistent.
*/
- bool decideWhetherToUseGpuForUpdate(bool forceGpuUpdateDefault,
- bool isDomainDecomposition,
- bool useUpdateGroups,
- bool useGpuForPme,
- bool useGpuForNonbonded,
- TaskTarget updateTarget,
- bool gpusWereDetected,
- const t_inputrec& inputrec,
- const gmx_mtop_t& mtop,
- bool useEssentialDynamics,
- bool doOrientationRestraints,
- bool useReplicaExchange,
- bool doRerun);
+ bool decideWhetherToUseGpuForUpdate(bool forceGpuUpdateDefault,
+ bool isDomainDecomposition,
+ bool useUpdateGroups,
+ PmeRunMode pmeRunMode,
+ bool havePmeOnlyRank,
+ bool useGpuForNonbonded,
+ TaskTarget updateTarget,
+ bool gpusWereDetected,
+ const t_inputrec& inputrec,
+ const gmx_mtop_t& mtop,
+ bool useEssentialDynamics,
+ bool doOrientationRestraints,
+ bool useReplicaExchange,
+ bool doRerun,
+ const gmx::MDLogger& mdlog);
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+ /*! \internal \file
+ * \brief
+ * Defines gmx::ISerializer implementation for in-memory serialization.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \ingroup module_utility
+ */
#include "gmxpre.h"
#include "inmemoryserializer.h"
return endianessSwappedValue.value_;
}
- //! \brief Change the host-dependent endian settings to either Swap or DoNotSwap.
- //
- // \param endianSwapBehavior input swap behavior, might depend on host.
- //
- // \return Host-independent setting, either Swap or DoNotSwap.
+ /*! \brief Change the host-dependent endian settings to either Swap or DoNotSwap.
+ *
+ * \param endianSwapBehavior input swap behavior, might depend on host.
+ *
+ * \return Host-independent setting, either Swap or DoNotSwap. */
EndianSwapBehavior setEndianSwapBehaviorFromHost(EndianSwapBehavior endianSwapBehavior)
{
if (endianSwapBehavior == EndianSwapBehavior::SwapIfHostIsBigEndian)
/*
* 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.
checkSerializerValuesforEquality(endianessSwappedValues_, deserialisedValues);
}
+ TEST_F(InMemorySerializerTest, SizeIsCorrect)
+ {
+ InMemorySerializer serializer;
+ // These types all have well-defined widths in bytes,
+ // which we can test below.
+ serializer.doBool(&defaultValues_.boolValue_); // 1 bytes
+ serializer.doChar(&defaultValues_.charValue_); // 1 bytes
+ serializer.doInt32(&defaultValues_.int32Value_); // 4 bytes
+ serializer.doInt64(&defaultValues_.int64Value_); // 8 bytes
+ serializer.doFloat(&defaultValues_.floatValue_); // 4 bytes
+ serializer.doDouble(&defaultValues_.doubleValue_); // 8 bytes
+ std::vector<char> charBuffer = { 'a', 'b', 'c' };
+ serializer.doCharArray(charBuffer.data(), charBuffer.size()); // 3 bytes
+ serializer.doOpaque(charBuffer.data(), charBuffer.size()); // 3 bytes
+ std::vector<int32_t> int32Buffer = { 0x1BCDEF78, 0x654321FE };
+ serializer.doInt32Array(int32Buffer.data(), int32Buffer.size()); // 8 bytes
+ std::vector<int64_t> int64Buffer = { 0x1BCDEF78654321FE, 0x3726ABFEAB34716C };
+ serializer.doInt64Array(int64Buffer.data(), int64Buffer.size()); // 16 bytes
+ auto buffer = serializer.finishAndGetBuffer();
+ EXPECT_EQ(buffer.size(), 56);
+ }
+
} // namespace
} // namespace test
} // namespace gmx