string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type)
gmx_check_if_changed(_cuda_nvcc_executable_or_flags_changed CUDA_NVCC_EXECUTABLE CUDA_NVCC_FLAGS CUDA_NVCC_FLAGS_${_build_type})
-if(_cuda_nvcc_executable_or_flags_changed OR CUDA_HOST_COMPILER_CHANGED OR NOT GMX_NVCC_WORKS)
+# We would like to be helpful and reject the host compiler with a
+# clear error message at configure time, rather than let nvcc
+# later reject the host compiler as not supported when the first
+# CUDA source file is built. We've implemented that for current
+# nvcc running on Unix-like systems, but e.g. changes to nvcc
+# will further affect the limited portability of this checking
+# code. Set the CMake variable GMX_NVCC_WORKS on if you want to
+# bypass this check.
+if((_cuda_nvcc_executable_or_flags_changed OR CUDA_HOST_COMPILER_CHANGED OR NOT GMX_NVCC_WORKS) AND NOT WIN32)
message(STATUS "Check for working NVCC/C compiler combination")
execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} -ccbin ${CUDA_HOST_COMPILER} -c ${CUDA_NVCC_FLAGS} ${CUDA_NVCC_FLAGS_${_build_type}} ${CMAKE_SOURCE_DIR}/cmake/TestCUDA.cu
RESULT_VARIABLE _cuda_test_res
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012,2013,2014,2015,2018, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2018,2019, by the GROMACS development team, led by
# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
# and including many others, as listed in the AUTHORS file in the
# top-level source directory and at http://www.gromacs.org.
include_directories(SYSTEM ${OpenCL_INCLUDE_DIRS})
+# Ensure the OpenCL implementation is 64-bit, because we only support that;
+# Note that this can only be revised if the cl_mem size assumptions made
+# (originally in pme-gpu-types.h) are relieved.
+if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
+ message(FATAL_ERROR "The OpenCL implementation is only supported on 64-bit platforms.")
+endif()
+
set(GMX_OPENCL_NB_CLUSTER_SIZE 8 CACHE STRING "Cluster size used by nonbonded OpenCL kernel. Set to 4 for Intel GPUs.")
mark_as_advanced(GMX_OPENCL_NB_CLUSTER_SIZE)
# VSX uses the same function API as Altivec/VMX, so make sure we tune for the current CPU and not VMX.
# By putting these flags here rather than in the general compiler flags file we can safely assume
# that we are at least on Power7 since that is when VSX appeared.
+
+ # NOTE: Enabling instruction fusion on Power8/9 using -mpower8-fusion/-mpower9-fusion
+ # seems to produce buggy code (see #2747, #2746, #2734).
+ # Note that instruction fusion does have considerable performance benefits
+ # (up to 8% measured with gcc 8) if the issue is resolved the flag can be re-enabled.
gmx_run_cpu_detection(brand)
if(CPU_DETECTION_BRAND MATCHES "POWER7")
gmx_test_cflag(GNU_C_VSX_POWER7 "-mcpu=power7 -mtune=power7" ${TOOLCHAIN_C_FLAGS_VARIABLE})
gmx_test_cflag(GNU_CXX_VSX_POWER7 "-mcpu=power7 -mtune=power7" ${TOOLCHAIN_CXX_FLAGS_VARIABLE})
elseif(CPU_DETECTION_BRAND MATCHES "POWER8")
# Enable power8 vector extensions on such platforms.
- gmx_test_cflag(GNU_C_VSX_POWER8 "-mcpu=power8 -mpower8-vector -mpower8-fusion" ${TOOLCHAIN_C_FLAGS_VARIABLE})
- gmx_test_cflag(GNU_CXX_VSX_POWER8 "-mcpu=power8 -mpower8-vector -mpower8-fusion" ${TOOLCHAIN_CXX_FLAGS_VARIABLE})
+ gmx_test_cflag(GNU_C_VSX_POWER8 "-mcpu=power8 -mpower8-vector" ${TOOLCHAIN_C_FLAGS_VARIABLE})
+ gmx_test_cflag(GNU_CXX_VSX_POWER8 "-mcpu=power8 -mpower8-vector" ${TOOLCHAIN_CXX_FLAGS_VARIABLE})
elseif(CPU_DETECTION_BRAND MATCHES "POWER9")
# Enable power9 vector extensions on such platforms.
# TODO consider whether adding " -mpower9-vector -mpower9-fusion"
# This ID is used for the source code tarball.
# GMX_MANUAL_DOI_ID
# Same as above, but for the reference manual.
-# Setting and retrieving of those variables is handled in gmxCheckReleaseDOI.cmake
# They are collected into a single section below.
# The following variables are set based on these:
# GMX_VERSION String composed from GMX_VERSION_* numeric variables
release-notes/deprecated-functionality.rst
release-notes/portability.rst
release-notes/miscellaneous.rst
+ release-notes/2019/2019.2.rst
release-notes/2019/2019.1.rst
release-notes/2019/major/highlights.rst
release-notes/2019/major/features.rst
To make it possible to use other accelerators, |Gromacs| also includes
OpenCL_ support. The minimum OpenCL version required is
-|REQUIRED_OPENCL_MIN_VERSION|. The current OpenCL implementation is recommended for
+|REQUIRED_OPENCL_MIN_VERSION| and only 64-bit implementations are supported.
+The current OpenCL implementation is recommended for
use with GCN-based AMD GPUs, and on Linux we recommend the ROCm runtime.
Intel integrated GPUs are supported with the Neo drivers.
OpenCL is also supported with NVIDIA GPUs, but using
to the NVIDIA OpenCL runtime).
It is not possible to configure both CUDA and OpenCL
support in the same build of |Gromacs|, nor to support both
-Intel and other vendors' GPUs with OpenCL.
+Intel and other vendors' GPUs with OpenCL. A 64-bit implementation
+of OpenCL is required and therefore OpenCL is only supported on 64-bit platforms.
.. _mpi-support:
+.. _electric fields:
+
Electric fields
---------------
where :math:`E_0` is the field strength, the angular frequency
:math:`\omega = 2\pi c/\lambda`, :math:`t_0` is the time
-at of the peak in the field strength and :math:`\sigma` is the with of
+at of the peak in the field strength and :math:`\sigma` is the width of
the pulse. Special cases occur when :math:`\sigma` = 0 (non-pulsed
-field) and for :math:`\omega` is 0 (static field).
+field) and for :math:`\omega` is 0 (static field). See
+:mdp:`electric-field-x` for more details.
This simulated laser-pulse was applied to simulations of melting
ice \ :ref:`146 <refCaleman2008a>`. A pulsed electric field may look ike
did not affect the, usual, setup where charges or atom types are actually
perturbed.
-:issue: `2640`
+:issue:`2640`
Add constraint contribution to foreign Hamiltonian differences
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Hamiltonian values. This is important for free energy calculations,
such as BAR.
-:issue: `2703`
+:issue:`2703`
Add mass contribution to foreign Hamiltonian differences
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
For free energy calculations with perturbed masses, the kinetic energy
contribution was missing from the foreign Hamiltonian values.
-:issue: `2703`
+:issue:`2703`
Work around bugs with expanded ensemble runs
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
other integrators when nstexpanded was not a multiple of nstcalcenergy.
In these cases mdrun now sets nstcalcenergy to 1.
-:issue: `2714`
-:issue: `2718`
+:issue:`2714`
+:issue:`2718`
Checkpoint continuations require suitable .tpr files
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Use gmx grompp or gmx convert-tpr to make a .tpr file that expresses
the intent.
-:issue: `2717`
+:issue:`2717`
Fixes for ``gmx`` tools
^^^^^^^^^^^^^^^^^^^^^^^
PME grids with size along Z larger than 511 would make mdrun exit
with a cryptic CUDA error.
-:issue: `2779`
+:issue:`2779`
Fix LINCS accuracy with OpenMP when constraint triangles are present
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
when the last OpenMP thread has at least one such triangle. This would
cause a slight loss of accuracy in inhomogeneous systems.
-:issue: `2808`
+:issue:`2808`
Fix acceleration with ``cos-acceleration``
""""""""""""""""""""""""""""""""""""""""""
A factor of 2 was missing from the acceleration value, leading to incorrect
results when e.g. calculating viscosities.
-:issue: `2572`
+:issue:`2572`
Fix checkpoint restart of tpr with infinite step count
""""""""""""""""""""""""""""""""""""""""""""""""""""""
works correctly with .gro files, which was changed in 2016 release series so that
it would only write fixed-width columns.
-:issue: `2813`
-:issue: `2037`
+:issue:`2813`
+:issue:`2037`
Fixes to improve portability
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
the two coupling times involved are similar. Now grompp warns when ``tau-p``
is less than two times ``tau-t``.
-:issue: `2749`
+:issue:`2749`
Fixed efficiency issue with shell code minimization
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Code cleanup touching unnecessarily complex code created an efficiency
issue. Both the issue and some of the complexity are now fixed.
-:issue: `2705`
+:issue:`2705`
Added code generation support for NVIDIA Turing GPUs
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
GROMACS 2019.1 release notes
----------------------------
-This version was released on TODO, 2019. These release notes
+This version was released on February 15, 2019. These release notes
document the changes that have taken place in GROMACS since the
initial version 2019, to fix known issues. It also incorporates all
fixes made in version 2018.5 and earlier, which you can find described
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Fix error with 2D/3D dynamic load balancing
--------------------------------------------
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-With 2D or 3D domain decomposition with dynamics load balancing,
+With 2D or 3D domain decomposition with dynamic load balancing,
mdrun would exit with the error "The domain decomposition grid
-as shifted too much .." when a cell size was limited.
+has shifted too much .." when a cell size was limited.
+
+:issue:`2830`
+
+Fix incorrect LJ repulsion force switching on GPUs
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+When using a CUDA or OpenCL GPU, the coefficient for the second order
+term for the LJ repulsion in the force switching function, called 'A'
+in the manual, had the wrong sign. This lead to very small errors in
+the forces and the pressure. Note that the dispersion force switching
+was correct. Although the effect on individual atoms pairs was negligible,
+their combined effect on the pressure could lead to deformation of
+CHARMM membrane systems, where LJ force switching is regularly applied.
+
+:issue:`2845`
-:issue: `2830`
Fix segmentation fault in mdrun with domain decomposition
----------------------------------------------------------
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+:issue:`2813`
+
+Fix segmentation fault with energy minimization with the group scheme
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Using energy minimization in combination with the group cutoff scheme
+and domain decomposition could lead to a segmentation fault.
+
+:issue:`2813`
+
+Correct free-energy Delta H output with mass lambda's
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+When separate lambda parameters were used for perturbed mass
+free-energy contributions, these contributions were double counted
+in the Delta H output used for BAR calculations. Note that dH/dlambda
+was always correct
+
+:issue:`2703`
+:issue:`2849`
-:issue: `2813`
+Prevent mdrun -rerun from writing incorrect free-energy output
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Now mdrun -rerun exits with a fatal error when masses or constraints
+are perturbed. Their contributions to Hamiltonian differences and
+derivatives were incorrectly set to zero in version 2019.
+
+:issue:`2849`
Fix possible division by zero in enforced-rotation code
--------------------------------------------------------
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-:issue: `1431`
+:issue:`1431`
Fixes for ``gmx`` tools
^^^^^^^^^^^^^^^^^^^^^^^
Fix trjconv -ndec
----------------------------------------------------------
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
This only works for writing .xtc files. The code and documentation now
works correctly with .gro files, which was changed in 2016 release series so that
it would only write fixed-width columns.
-:issue: `2824`
-:issue: `2037`
+:issue:`2824`
+:issue:`2037`
+
+Fix using index file groups when .tpr file not supplied
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+Selections that use groups from a supplied index file can
+again be used even when a .tpr file is not supplied.
+
+:issue:`2847`
+
+Fix tune_pme
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+The tool did not work due to a file reading error that is fixed now.
+
+:issue:`2827`
Fixes that affect portability
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
With MSVC, disabled internal clFFT fallback used for OpenCL support
--------------------------------------------------------------------
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
GROMACS requires MSVC 2017, and the GROMACS OpenCL build requires
clFFT. If clFFT is found on the user's system, then all may be well,
but the version of clFFT bundled within GROMACS cannot be built
because only MSVC 2010 is supported by clFFT at this time. A
configure-time fatal error is now issued in this case.
-:issue: `2500`
+:issue:`2500`
+
+Explicitly require 64-bit platforms for OpenCL
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+A 64-bit OpenCL runtime is required by GROMACS.
+All known OpenCL implementations on 64-bit platforms are 64-bit
+(and there are no known 32-bit platforms with 64-bit OpenCL),
+hence we require a 64-bit platform at configure-time in OpenCL builds.
+A known unsupported 32-bit platform is ARMv7.
Miscellaneous
^^^^^^^^^^^^^
+
+Improved docs for applying electric fields
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
--- /dev/null
+GROMACS 2019.2 release notes
+----------------------------
+
+This version was released on TODO, 2019. These release notes
+document the changes that have taken place in GROMACS since the
+initial version 2019.1, to fix known issues. It also incorporates all
+fixes made in version 2018.5 and earlier, which you can find described
+in the :ref:`release-notes`.
+
+.. Note to developers!
+ Please use """"""" to underline the individual entries for fixed issues in the subfolders,
+ otherwise the formatting on the webpage is messed up.
+ Also, please use the syntax :issue:`number` to reference issues on redmine, without the
+ a space between the colon and number!
+
+Fixes where mdrun could behave incorrectly
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Fixes for ``gmx`` tools
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Fixes that affect portability
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Miscellaneous
+^^^^^^^^^^^^^
.. toctree::
:maxdepth: 1
+ 2019/2019.2
2019/2019.1
Major release
Electric fields
^^^^^^^^^^^^^^^
-.. mdp:: electric-field-x ; electric-field-y ; electric-field-z
+.. mdp:: electric-field-x
+.. mdp:: electric-field-y
+.. mdp:: electric-field-z
Here you can specify an electric field that optionally can be
alternating and pulsed. The general expression for the field
has the form of a gaussian laser pulse:
- E(t) = E0 exp ( -(t-t0)\ :sup:`2`/(2 sigma\ :sup:`2`) ) cos(omega (t-t0))
+ .. math:: E(t) = E_0 \exp\left[-\frac{(t-t_0)^2}{2\sigma^2}\right]\cos\left[\omega (t-t_0)\right]
For example, the four parameters for direction x are set in the
- three fields of ``electric-field-x`` (and similar for y and z)
- like
+ fields of :mdp:`electric-field-x` (and similar for ``electric-field-y``
+ and ``electric-field-z``) like
- electric-field-x = E0 omega t0 sigma
+ ``electric-field-x = E0 omega t0 sigma``
- In the special case that sigma = 0, the exponential term is omitted
- and only the cosine term is used. If also omega = 0 a static
- electric field is applied.
+ with units (respectively) V nm\ :sup:`-1`, ps\ :sup:`-1`, ps, ps.
- More details in Carl Caleman and David van der Spoel: Picosecond
- Melting of Ice by an Infrared Laser Pulse - A Simulation Study.
- Angew. Chem. Intl. Ed. 47 pp. 14 17-1420 (2008)
+ In the special case that ``sigma = 0``, the exponential term is omitted
+ and only the cosine term is used. If also ``omega = 0`` a static
+ electric field is applied.
+ Read more at :ref:`electric fields` and in ref. \ :ref:`146 <refCaleman2008a>`.
Mixed quantum/classical molecular dynamics
the lowest common SIMD instruction set (as these rely little on SIMD acceleration), but for best
performance :ref:`mdrun <gmx mdrun>` should be compiled separately for each machine.
+.. TODO add a note on AVX throttle and its impact on MPI-parallel and GPU accelerated runs
+
Process(-or) level parallelization via OpenMP
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
with the GPUs focused on the calculation of the NB.
#) With fast/modern GPUs and/or slow/old CPUs with few cores,
- it generally helps to have the GPU do PME. With very few/weak
- cores, it can help to have the GPU do bonded interactions also.
+ it generally helps to have the GPU do PME.
+
+#) Offloading bonded work to a GPU will often not improve simulation performance
+ as efficient CPU-based kernels can complete the bonded computation
+ before the GPU is done with other offloaded work. Therefore,
+ `gmx mdrun` will default to no bonded offload when PME is offloaded.
+ Typical cases where performance can be improvement with bonded offload are:
+ with significant bonded work (e.g. pure lipid or mostly polymer systems with little solvent),
+ with very few and/or slow CPU cores per GPU, or when the CPU does
+ other computation (e.g. PME, free energy).
#) It *is* possible to use multiple GPUs with PME offload
by letting e.g.
also the :ref:`known limitations <opencl-known-limitations>`.
Devices from the AMD GCN architectures (all series) are compatible
-and regularly tested; NVIDIA Fermi and later (compute capability 2.0)
+and regularly tested; NVIDIA Kepler and later (compute capability 3.0)
are known to work, but before doing production runs always make sure that the |Gromacs| tests
pass successfully on the hardware.
# source files, and issue warnings about that. Remove the use of
# -Wno-missing-prototypes here and above when the group scheme is
# removed.
-if (HAS_NO_MISSING_PROTO AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+if (HAS_NO_MISSING_PROTO AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
target_compile_options(libgromacs_generated PRIVATE "-Wno-missing-prototypes")
endif()
if (HAS_NO_MSVC_UNUSED)
const int movedValue = NSGRID_SIGNAL_MOVED_FAC*fr->ns->grid->ncells;
- if (ncg_home_old >= 0)
+ if (ncg_home_old >= 0 && !sort->sorted.empty())
{
+ GMX_RELEASE_ASSERT(sort->sorted.size() == static_cast<size_t>(ncg_home_old),
+ "The sorting buffer should contain the old home charge group indices");
+
std::vector<gmx_cgsort_t> &stationary = sort->stationary;
std::vector<gmx_cgsort_t> &moved = sort->moved;
wallcycle_sub_stop(wcycle, ewcsDD_GRID);
}
+ else
+ {
+ /* With the group scheme the sorting array is part of the DD state,
+ * but it just got out of sync, so mark as invalid by emptying it.
+ */
+ if (ir->cutoff_scheme == ecutsGROUP)
+ {
+ comm->sort->sorted.clear();
+ }
+ }
if (comm->useUpdateGroups)
{
addMessageIfNotSupported(const std::list<std::string> &errorReasons,
std::string *error)
{
- bool foundErrorReasons = errorReasons.empty();
- if (!foundErrorReasons && error)
+ bool isSupported = errorReasons.empty();
+ if (!isSupported && error)
{
std::string regressionTestMarker = "PME GPU does not support";
// this prefix is tested for in the regression tests script gmxtest.pl
- *error = regressionTestMarker + ": " + gmx::joinStrings(errorReasons, "; ") + ".";
+ *error = regressionTestMarker;
+ if (errorReasons.size() == 1)
+ {
+ *error += " " + errorReasons.back();
+ }
+ else
+ {
+ *error += ": " + gmx::joinStrings(errorReasons, "; ");
+ }
+ *error += ".";
}
- return foundErrorReasons;
+ return isSupported;
}
-bool pme_gpu_supports_build(const gmx_hw_info_t &hwinfo,
- std::string *error)
+bool pme_gpu_supports_build(std::string *error)
{
std::list<std::string> errorReasons;
if (GMX_DOUBLE)
{
- errorReasons.emplace_back("double precision");
+ errorReasons.emplace_back("a double-precision build");
}
if (GMX_GPU == GMX_GPU_NONE)
{
- errorReasons.emplace_back("non-GPU build of GROMACS");
+ errorReasons.emplace_back("a non-GPU build");
}
+ return addMessageIfNotSupported(errorReasons, error);
+}
+
+bool pme_gpu_supports_hardware(const gmx_hw_info_t &hwinfo,
+ std::string *error)
+{
+ std::list<std::string> errorReasons;
if (GMX_GPU == GMX_GPU_OPENCL)
{
if (!areAllGpuDevicesFromAmd(hwinfo.gpu_info))
{
- errorReasons.emplace_back("only AMD devices are supported");
+ errorReasons.emplace_back("non-AMD devices");
}
}
return addMessageIfNotSupported(errorReasons, error);
*
* 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, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* TODO: this partly duplicates an internal PME assert function
* pme_gpu_check_restrictions(), except that works with a
* formed gmx_pme_t structure. Should that one go away/work with inputrec?
+ *
+ * \param[out] error If non-null, the error message when PME is not supported on GPU.
+ *
+ * \returns true if PME can run on GPU on this build, false otherwise.
+ */
+bool pme_gpu_supports_build(std::string *error);
+
+/*! \brief Checks whether the detected (GPU) hardware allows to run PME on GPU.
*
* \param[in] hwinfo Information about the detected hardware
* \param[out] error If non-null, the error message when PME is not supported on GPU.
*
* \returns true if PME can run on GPU on this build, false otherwise.
*/
-bool pme_gpu_supports_build(const gmx_hw_info_t &hwinfo,
- std::string *error);
+bool pme_gpu_supports_hardware(const gmx_hw_info_t &hwinfo,
+ std::string *error);
/*! \brief Checks whether the input system allows to run PME on GPU.
* TODO: this partly duplicates an internal PME assert function
break;
case CodePath::GPU:
- implemented = (pme_gpu_supports_build(hwinfo, nullptr) &&
+ implemented = (pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(hwinfo, nullptr) &&
pme_gpu_supports_input(*inputRec, mtop, nullptr));
break;
hardwareContexts_.emplace_back(std::make_unique<TestHardwareContext>(CodePath::CPU, "", nullptr));
hardwareInfo_ = hardwareInit();
- if (!pme_gpu_supports_build(*hardwareInfo_, nullptr))
+ if (!pme_gpu_supports_build(nullptr) ||
+ !pme_gpu_supports_hardware(*hardwareInfo_, nullptr))
{
// PME can only run on the CPU, so don't make any more test contexts.
return;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{ efLOG, "-err", "bencherr", ffWRITE },
{ efTPR, "-so", "tuned", ffWRITE },
/* mdrun: */
- { efTPR, nullptr, nullptr, ffREAD },
+ { efTPR, "-s", nullptr, ffREAD },
{ efTRN, "-o", nullptr, ffWRITE },
{ efCOMPRESSED, "-x", nullptr, ffOPTWR },
{ efCPT, "-cpi", nullptr, ffOPTRD },
#include "gromacs/topology/symtab.h"
#include "gromacs/topology/topology.h"
#include "gromacs/trajectory/trajectoryframe.h"
-#include "gromacs/trajectoryanalysis/topologyinformation.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
-#include "gromacs/utility/unique_cptr.h"
using gmx::RVec;
{
clear_rvec(newBox_);
clear_rvec(deltaR_);
+ clear_mat(box_);
}
// From ITopologyProvider
- gmx_mtop_t *getTopology(bool /*required*/) override { return topInfo_.mtop(); }
+ gmx_mtop_t *getTopology(bool /*required*/) override { return &top_; }
int getAtomCount() override { return 0; }
// From ICommandLineOptionsModule
RotationType enumRot_;
Selection replaceSel_;
- TopologyInformation topInfo_;
+ gmx_mtop_t top_;
+ std::vector<RVec> x_;
+ matrix box_;
+ int ePBC_;
};
void InsertMolecules::initOptions(IOptionsContainer *options,
if (!inputConfFile_.empty())
{
+ bool bTprFileWasRead;
+ rvec *temporaryX = nullptr;
fprintf(stderr, "Reading solute configuration\n");
- topInfo_.fillFromInputFile(inputConfFile_);
- if (topInfo_.mtop()->natoms == 0)
+ readConfAndTopology(inputConfFile_.c_str(), &bTprFileWasRead, &top_,
+ &ePBC_, &temporaryX, nullptr, box_);
+ x_.assign(temporaryX, temporaryX + top_.natoms);
+ sfree(temporaryX);
+ if (top_.natoms == 0)
{
fprintf(stderr, "Note: no atoms in %s\n", inputConfFile_.c_str());
}
int InsertMolecules::run()
{
- const char *outputTitle = topInfo_.name();
- std::vector<RVec> xOutput;
- matrix box = {{ 0 }};
- if (topInfo_.hasTopology())
- {
- xOutput = copyOf(topInfo_.x());
- topInfo_.getBox(box);
- }
- else
- {
- xOutput.resize(topInfo_.mtop()->natoms);
- }
- auto atomsSolute = topInfo_.copyAtoms();
std::set<int> removableAtoms;
if (replaceSel_.isValid())
{
t_pbc pbc;
- set_pbc(&pbc, topInfo_.ePBC(), box);
+ set_pbc(&pbc, ePBC_, box_);
t_trxframe *fr;
snew(fr, 1);
- fr->natoms = topInfo_.mtop()->natoms;
+ fr->natoms = x_.size();
fr->bX = TRUE;
- fr->x = as_rvec_array(xOutput.data());
+ fr->x = as_rvec_array(x_.data());
selections_.evaluate(fr, &pbc);
sfree(fr);
removableAtoms.insert(replaceSel_.atomIndices().begin(),
// individual atoms.
}
- int ePBCForOutput = topInfo_.ePBC();
+ int ePBCForOutput = ePBC_;
if (bBox_)
{
ePBCForOutput = epbcXYZ;
- clear_mat(box);
- box[XX][XX] = newBox_[XX];
- box[YY][YY] = newBox_[YY];
- box[ZZ][ZZ] = newBox_[ZZ];
+ clear_mat(box_);
+ box_[XX][XX] = newBox_[XX];
+ box_[YY][YY] = newBox_[YY];
+ box_[ZZ][ZZ] = newBox_[ZZ];
}
- if (det(box) == 0)
+ if (det(box_) == 0)
{
gmx_fatal(FARGS, "Undefined solute box.\nCreate one with gmx editconf "
"or give explicit -box command line option");
}
- fprintf(stderr, "Reading molecule configuration\n");
- TopologyInformation topInfoForInsertedMolecule;
- topInfoForInsertedMolecule.fillFromInputFile(insertConfFile_);
- auto atomsInserted = topInfoForInsertedMolecule.atoms();
- std::vector<RVec> xInserted = copyOf(topInfoForInsertedMolecule.x());
-
- if (topInfoForInsertedMolecule.mtop()->natoms == 0)
- {
- gmx_fatal(FARGS, "No molecule in %s, please check your input",
- insertConfFile_.c_str());
- }
- if (outputTitle == nullptr)
- {
- outputTitle = topInfoForInsertedMolecule.name();
- }
- if (positionFile_.empty())
+ gmx_mtop_t topInserted;
+ t_atoms atomsInserted;
+ std::vector<RVec> xInserted;
{
- center_molecule(xInserted);
+ bool bTprFileWasRead;
+ int ePBC_dummy;
+ matrix box_dummy;
+ rvec *temporaryX;
+ readConfAndTopology(insertConfFile_.c_str(), &bTprFileWasRead, &topInserted,
+ &ePBC_dummy, &temporaryX, nullptr, box_dummy);
+ xInserted.assign(temporaryX, temporaryX + topInserted.natoms);
+ sfree(temporaryX);
+ atomsInserted = gmx_mtop_global_atoms(&topInserted);
+ if (atomsInserted.nr == 0)
+ {
+ gmx_fatal(FARGS, "No molecule in %s, please check your input",
+ insertConfFile_.c_str());
+ }
+ if (top_.name == nullptr)
+ {
+ top_.name = topInserted.name;
+ }
+ if (positionFile_.empty())
+ {
+ center_molecule(xInserted);
+ }
}
- auto symtabInserted = duplicateSymtab(&topInfo_.mtop()->symtab);
- const sfree_guard symtabInsertedGuard(symtabInserted);
+ t_atoms atoms = gmx_mtop_global_atoms(&top_);
+
/* add nmol_ins molecules of atoms_ins
in random orientation at random place */
insert_mols(nmolIns_, nmolTry_, seed_, defaultDistance_, scaleFactor_,
- atomsSolute.get(), symtabInserted, &xOutput, removableAtoms, *atomsInserted, xInserted,
- ePBCForOutput, box, positionFile_, deltaR_, enumRot_);
+ &atoms, &top_.symtab, &x_, removableAtoms, atomsInserted, xInserted,
+ ePBCForOutput, box_, positionFile_, deltaR_, enumRot_);
/* write new configuration to file confout */
fprintf(stderr, "Writing generated configuration to %s\n",
outputConfFile_.c_str());
- write_sto_conf(outputConfFile_.c_str(), outputTitle, atomsSolute.get(),
- as_rvec_array(xOutput.data()), nullptr, ePBCForOutput, box);
+ write_sto_conf(outputConfFile_.c_str(), *top_.name, &atoms,
+ as_rvec_array(x_.data()), nullptr, ePBCForOutput, box_);
/* print size of generated configuration */
fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
- atomsSolute->nr, atomsSolute->nres);
- done_symtab(symtabInserted);
+ atoms.nr, atoms.nres);
+
+ done_atom(&atoms);
+ done_atom(&atomsInserted);
+
return 0;
}
expand->nstexpanded = fep->nstdhdl;
/* if you don't specify nstexpanded when doing expanded ensemble free energy calcs, it is set to nstdhdl */
}
- if ((expand->nstexpanded < 0) && ir->bSimTemp)
- {
- expand->nstexpanded = 2*static_cast<int>(ir->opts.tau_t[0]/ir->delta_t);
- /* if you don't specify nstexpanded when doing expanded ensemble simulated tempering, it is set to
- 2*tau_t just to be careful so it's not to frequent */
- }
}
gmx_fatal(FARGS, "Can only have energy group pair tables in combination with user tables for VdW and/or Coulomb");
}
+ /* final check before going out of scope if simulated tempering variables
+ * need to be set to default values.
+ */
+ if ((ir->expandedvals->nstexpanded < 0) && ir->bSimTemp)
+ {
+ ir->expandedvals->nstexpanded = 2*static_cast<int>(ir->opts.tau_t[0]/ir->delta_t);
+ warning(wi, gmx::formatString("the value for nstexpanded was not specified for "
+ " expanded ensemble simulated tempering. It is set to 2*tau_t (%d) "
+ "by default, but it is recommended to set it to an explicit value!",
+ ir->expandedvals->nstexpanded));
+ }
for (i = 0; (i < grps->nr); i++)
{
sfree(gnames[i]);
#include "gromacs/topology/atomprop.h"
#include "gromacs/topology/atoms.h"
#include "gromacs/topology/atomsbuilder.h"
+#include "gromacs/topology/mtop_util.h"
#include "gromacs/topology/topology.h"
-#include "gromacs/trajectoryanalysis/topologyinformation.h"
#include "gromacs/utility/arraysize.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/futil.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/smalloc.h"
-#include "gromacs/utility/unique_cptr.h"
using gmx::RVec;
remover.removeMarkedAtoms(atoms);
}
-static void add_solv(const char *filename,
- const gmx::TopologyInformation &topInfo,
- t_atoms *atoms,
+static void add_solv(const char *filename, t_atoms *atoms,
+ t_symtab *symtab,
std::vector<RVec> *x, std::vector<RVec> *v,
- matrix box, AtomProperties *aps,
+ int ePBC, matrix box, AtomProperties *aps,
real defaultDistance, real scaleFactor,
real rshell, int max_sol)
{
- gmx::TopologyInformation topInfoSolvent;
- topInfoSolvent.fillFromInputFile(gmx::findLibraryFile(filename));
- auto atomsSolvent = topInfoSolvent.copyAtoms();
- std::vector<RVec> xSolvent, vSolvent;
- matrix boxSolvent = {{ 0 }};
- if (topInfoSolvent.hasTopology())
- {
- xSolvent = copyOf(topInfoSolvent.x());
- vSolvent = copyOf(topInfoSolvent.v());
- topInfoSolvent.getBox(boxSolvent);
- }
- else
- {
- xSolvent.resize(atomsSolvent->nr);
- vSolvent.resize(atomsSolvent->nr);
- }
+ gmx_mtop_t topSolvent;
+ std::vector<RVec> xSolvent, vSolvent;
+ matrix boxSolvent = {{ 0 }};
+ int ePBCSolvent;
+
+ fprintf(stderr, "Reading solvent configuration\n");
+ bool bTprFileWasRead;
+ rvec *temporaryX = nullptr, *temporaryV = nullptr;
+ readConfAndTopology(gmx::findLibraryFile(filename).c_str(), &bTprFileWasRead, &topSolvent,
+ &ePBCSolvent, &temporaryX, &temporaryV, boxSolvent);
+ t_atoms *atomsSolvent;
+ snew(atomsSolvent, 1);
+ *atomsSolvent = gmx_mtop_global_atoms(&topSolvent);
+ xSolvent.assign(temporaryX, temporaryX + topSolvent.natoms);
+ sfree(temporaryX);
+ vSolvent.assign(temporaryV, temporaryV + topSolvent.natoms);
+ sfree(temporaryV);
if (gmx::boxIsZero(boxSolvent))
{
gmx_fatal(FARGS, "No box information for solvent in %s, please use a properly formatted file\n",
const std::vector<real> exclusionDistances(
makeExclusionDistances(atoms, aps, defaultDistance, scaleFactor));
std::vector<real> exclusionDistances_solvt(
- makeExclusionDistances(atomsSolvent.get(), aps, defaultDistance, scaleFactor));
+ makeExclusionDistances(atomsSolvent, aps, defaultDistance, scaleFactor));
/* generate a new solvent configuration */
fprintf(stderr, "Generating solvent configuration\n");
t_pbc pbc;
- set_pbc(&pbc, topInfo.ePBC(), box);
+ set_pbc(&pbc, ePBC, box);
if (!gmx::boxesAreEqual(boxSolvent, box))
{
if (TRICLINIC(boxSolvent))
"You can try to pass the same box for -cp and -cs.");
}
/* apply pbc for solvent configuration for whole molecules */
- rm_res_pbc(atomsSolvent.get(), &xSolvent, boxSolvent);
- replicateSolventBox(atomsSolvent.get(), &xSolvent, &vSolvent, &exclusionDistances_solvt,
+ rm_res_pbc(atomsSolvent, &xSolvent, boxSolvent);
+ replicateSolventBox(atomsSolvent, &xSolvent, &vSolvent, &exclusionDistances_solvt,
boxSolvent, box);
- if (topInfo.ePBC() != epbcNONE)
+ if (ePBC != epbcNONE)
{
- removeSolventBoxOverlap(atomsSolvent.get(), &xSolvent, &vSolvent, &exclusionDistances_solvt, pbc);
+ removeSolventBoxOverlap(atomsSolvent, &xSolvent, &vSolvent, &exclusionDistances_solvt, pbc);
}
}
if (atoms->nr > 0)
{
if (rshell > 0.0)
{
- removeSolventOutsideShell(atomsSolvent.get(), &xSolvent, &vSolvent,
+ removeSolventOutsideShell(atomsSolvent, &xSolvent, &vSolvent,
&exclusionDistances_solvt, pbc, *x, rshell);
}
- removeSolventOverlappingWithSolute(atomsSolvent.get(), &xSolvent, &vSolvent,
+ removeSolventOverlappingWithSolute(atomsSolvent, &xSolvent, &vSolvent,
&exclusionDistances_solvt, pbc, *x,
exclusionDistances);
}
if (max_sol > 0 && atomsSolvent->nres > max_sol)
{
const int numberToRemove = atomsSolvent->nres - max_sol;
- removeExtraSolventMolecules(atomsSolvent.get(), &xSolvent, &vSolvent, numberToRemove);
+ removeExtraSolventMolecules(atomsSolvent, &xSolvent, &vSolvent, numberToRemove);
}
/* Sort the solvent mixture, not the protein... */
- t_atoms *newatoms = nullptr;
- t_atoms *sortedAtomsSolvent = atomsSolvent.get();
+ t_atoms *newatoms = nullptr;
+ // The sort_molecule function does something creative with the
+ // t_atoms pointers. We need to make sure we neither leak, nor
+ // double-free, so make a shallow pointer that is fine for it to
+ // change.
+ t_atoms *sortedAtomsSolvent = atomsSolvent;
sort_molecule(&sortedAtomsSolvent, &newatoms, &xSolvent, &vSolvent);
// Merge the two configurations.
v->insert(v->end(), vSolvent.begin(), vSolvent.end());
}
{
- gmx::AtomsBuilder builder(atoms, &topInfo.mtop()->symtab);
+ gmx::AtomsBuilder builder(atoms, symtab);
builder.mergeAtoms(*sortedAtomsSolvent);
}
fprintf(stderr, "Generated solvent containing %d atoms in %d residues\n",
- sortedAtomsSolvent->nr, sortedAtomsSolvent->nres);
+ atomsSolvent->nr, atomsSolvent->nres);
if (newatoms)
{
done_atom(newatoms);
sfree(newatoms);
}
+ if (atomsSolvent)
+ {
+ done_atom(atomsSolvent);
+ sfree(atomsSolvent);
+ }
}
static void update_top(t_atoms *atoms,
AtomProperties aps;
- gmx::TopologyInformation topInfo;
- std::vector<RVec> x, v;
- matrix box = {{ 0 }};
+ /* solute configuration data */
+ gmx_mtop_t top;
+ std::vector<RVec> x, v;
+ matrix box = {{ 0 }};
+ int ePBC = -1;
+ t_atoms *atoms;
+ snew(atoms, 1);
if (bProt)
{
/* Generate a solute configuration */
conf_prot = opt2fn("-cp", NFILE, fnm);
- topInfo.fillFromInputFile(conf_prot);
- x = copyOf(topInfo.x());
- if (bReadV)
- {
- v = copyOf(topInfo.v());
- }
- topInfo.getBox(box);
fprintf(stderr, "Reading solute configuration%s\n",
bReadV ? " and velocities" : "");
- if (bReadV && v.empty())
+ bool bTprFileWasRead;
+ rvec *temporaryX = nullptr, *temporaryV = nullptr;
+ readConfAndTopology(conf_prot, &bTprFileWasRead, &top,
+ &ePBC, &temporaryX, bReadV ? &temporaryV : nullptr, box);
+ *atoms = gmx_mtop_global_atoms(&top);
+ x.assign(temporaryX, temporaryX + top.natoms);
+ sfree(temporaryX);
+ if (temporaryV)
+ {
+ v.assign(temporaryV, temporaryV + top.natoms);
+ sfree(temporaryV);
+ }
+ else if (bReadV)
{
fprintf(stderr, "Note: no velocities found\n");
}
- if (topInfo.mtop()->natoms == 0)
+ if (atoms->nr == 0)
{
fprintf(stderr, "Note: no atoms in %s\n", conf_prot);
bProt = FALSE;
}
else
{
- firstSolventResidueIndex = topInfo.atoms()->nres;
+ firstSolventResidueIndex = atoms->nres;
}
}
- auto atoms = topInfo.copyAtoms();
- int ePBCForOutput = topInfo.ePBC();
+ int ePBCForOutput = ePBC;
if (bBox)
{
ePBCForOutput = epbcXYZ;
"or give explicit -box command line option");
}
- add_solv(solventFileName, topInfo, atoms.get(), &x, &v, box,
+ add_solv(solventFileName, atoms, &top.symtab, &x, &v, ePBCForOutput, box,
&aps, defaultDistance, scaleFactor, r_shell, max_sol);
/* write new configuration 1 to file confout */
confout = ftp2fn(efSTO, NFILE, fnm);
fprintf(stderr, "Writing generated configuration to %s\n", confout);
- const char *outputTitle = (bProt ? *topInfo.mtop()->name : "Generated by gmx solvate");
- write_sto_conf(confout, outputTitle, atoms.get(), as_rvec_array(x.data()),
+ const char *outputTitle = (bProt ? *top.name : "Generated by gmx solvate");
+ write_sto_conf(confout, outputTitle, atoms, as_rvec_array(x.data()),
!v.empty() ? as_rvec_array(v.data()) : nullptr, ePBCForOutput, box);
/* print size of generated configuration */
fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
atoms->nr, atoms->nres);
- update_top(atoms.get(), firstSolventResidueIndex, box, NFILE, fnm, &aps);
+ update_top(atoms, firstSolventResidueIndex, box, NFILE, fnm, &aps);
+
+ done_atom(atoms);
+ sfree(atoms);
output_env_done(oenv);
return 0;
return impl_->nflexcon;
}
+bool Constraints::havePerturbedConstraints() const
+{
+ const gmx_ffparams_t &ffparams = impl_->mtop.ffparams;
+
+ for (size_t i = 0; i < ffparams.functype.size(); i++)
+ {
+ if ((ffparams.functype[i] == F_CONSTR ||
+ ffparams.functype[i] == F_CONSTRNC) &&
+ ffparams.iparams[i].constr.dA != ffparams.iparams[i].constr.dB)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
//! Clears constraint quantities for atoms in nonlocal region.
static void clear_constraint_quantity_nonlocal(gmx_domdec_t *dd, rvec *q)
{
/*! \brief Returns the total number of flexible constraints in the system. */
int numFlexibleConstraints() const;
+ /*! \brief Returns whether the system contains perturbed constraints */
+ bool havePerturbedConstraints() const;
+
/*! \brief Set up all the local constraints for the domain.
*
* \todo Make this a callback that is called automatically
enerpart_lambda += dlam*enerd->term[F_DVDL_CONSTR];
}
- if (j == efptMASS)
+ if (j == efptMASS && !fepvals->separate_dvdl[j])
{
enerpart_lambda += dlam*enerd->term[F_DKDL];
}
}
/* launch local nonbonded work on GPU */
- wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_NONBONDED);
+ wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_NONBONDED);
do_nb_verlet(fr, ic, enerd, flags, Nbnxm::InteractionLocality::Local, enbvClearFNo,
step, nrnb, wcycle);
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_NONBONDED);
wallcycle_start(wcycle, ewcLAUNCH_GPU);
/* launch non-local nonbonded tasks on GPU */
- wallcycle_sub_start(wcycle, ewcsLAUNCH_GPU_NONBONDED);
+ wallcycle_sub_start_nocount(wcycle, ewcsLAUNCH_GPU_NONBONDED);
Nbnxm::gpu_copy_xq_to_gpu(nbv->gpu_nbv, nbv->nbat, Nbnxm::AtomLocality::NonLocal, ppForceWorkload->haveGpuBondedWork);
wallcycle_sub_stop(wcycle, ewcsLAUNCH_GPU_NONBONDED);
"be available in a different form in a future version of GROMACS, "
"e.g. gmx rerun -f.");
+ if (ir->efep != efepNO && (mdAtoms->mdatoms()->nMassPerturbed > 0 ||
+ (constr && constr->havePerturbedConstraints())))
+ {
+ gmx_fatal(FARGS, "Perturbed masses or constraints are not supported by rerun. "
+ "Either make a .tpr without mass and constraint perturbation, "
+ "or use GROMACS 2018.4, 2018.5 or later 2018 version.");
+ }
if (ir->bExpanded)
{
gmx_fatal(FARGS, "Expanded ensemble not supported by rerun.");
inputrec->cutoff_scheme == ecutsVERLET,
gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, GMX_THREAD_MPI),
hw_opt.nthreads_tmpi);
- auto canUseGpuForPme = pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
useGpuForPme = decideWhetherToUseGpusForPmeWithThreadMpi
(useGpuForNonbonded, pmeTarget, gpuIdsToUse, userGpuTaskAssignment,
- canUseGpuForPme, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
+ *hwinfo, *inputrec, mtop, hw_opt.nthreads_tmpi, domdecOptions.numPmeRanks);
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
usingVerletScheme,
gpuAccelerationOfNonbondedIsUseful(mdlog, inputrec, !GMX_THREAD_MPI),
gpusWereDetected);
- auto canUseGpuForPme = pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, mtop, nullptr);
useGpuForPme = decideWhetherToUseGpusForPme(useGpuForNonbonded, pmeTarget, userGpuTaskAssignment,
- canUseGpuForPme, cr->nnodes, domdecOptions.numPmeRanks,
+ *hwinfo, *inputrec, mtop,
+ cr->nnodes, domdecOptions.numPmeRanks,
gpusWereDetected);
auto canUseGpuForBonded = buildSupportsGpuBondeds(nullptr) && inputSupportsGpuBondeds(*inputrec, mtop, nullptr);
useGpuForBonded =
*F_invr +=
-c6*(disp_shift_V2 + disp_shift_V3*r_switch)*r_switch*r_switch*inv_r +
- c12*(-repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
+ c12*(repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
}
/*! Apply force switch, force-only version. */
*F_invr +=
-c6*(disp_shift_V2 + disp_shift_V3*r_switch)*r_switch*r_switch*inv_r +
- c12*(-repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
+ c12*(repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
*E_lj +=
c6*(disp_shift_F2 + disp_shift_F3*r_switch)*r_switch*r_switch*r_switch -
c12*(repu_shift_F2 + repu_shift_F3*r_switch)*r_switch*r_switch*r_switch;
*F_invr +=
-c6*(disp_shift_V2 + disp_shift_V3*r_switch)*r_switch*r_switch*inv_r +
- c12*(-repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
+ c12*(repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
}
/*! Apply force switch, force-only version. */
*F_invr +=
-c6*(disp_shift_V2 + disp_shift_V3*r_switch)*r_switch*r_switch*inv_r +
- c12*(-repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
+ c12*(repu_shift_V2 + repu_shift_V3*r_switch)*r_switch*r_switch*inv_r;
*E_lj +=
c6*(disp_shift_F2 + disp_shift_F3*r_switch)*r_switch*r_switch*r_switch -
c12*(repu_shift_F2 + repu_shift_F3*r_switch)*r_switch*r_switch*r_switch;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2015,2017,2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
}
+#ifdef __INTEL_COMPILER //Bug in (at least) 19u1 and 18u5 (03424712)
+ #pragma novector
+#endif
for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
{
// Subtract values from _reference_ memory (we will then test with mem0_, and compare)
#include <algorithm>
#include <string>
+#include "gromacs/ewald/pme.h"
#include "gromacs/hardware/cpuinfo.h"
#include "gromacs/hardware/detecthardware.h"
#include "gromacs/hardware/hardwaretopology.h"
const TaskTarget pmeTarget,
const std::vector<int> &gpuIdsToUse,
const std::vector<int> &userGpuTaskAssignment,
- const bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
const int numRanksPerSimulation,
const int numPmeRanksPerSimulation)
{
// First, exclude all cases where we can't run PME on GPUs.
if ((pmeTarget == TaskTarget::Cpu) ||
!useGpuForNonbonded ||
- !canUseGpuForPme)
+ !pme_gpu_supports_build(nullptr) ||
+ !pme_gpu_supports_hardware(hardwareInfo, nullptr) ||
+ !pme_gpu_supports_input(inputrec, mtop, nullptr))
{
// PME can't run on a GPU. If the user required that, we issue
// an error later.
bool decideWhetherToUseGpusForPme(const bool useGpuForNonbonded,
const TaskTarget pmeTarget,
const std::vector<int> &userGpuTaskAssignment,
- const bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
const int numRanksPerSimulation,
const int numPmeRanksPerSimulation,
const bool gpusWereDetected)
if (pmeTarget == TaskTarget::Gpu)
{
GMX_THROW(NotImplementedError
- ("The PME on the GPU is only supported when nonbonded interactions run on GPUs also."));
+ ("PME on GPUs is only supported when nonbonded interactions run on GPUs also."));
}
return false;
}
- if (!canUseGpuForPme)
+ std::string message;
+ if (!pme_gpu_supports_build(&message))
{
if (pmeTarget == TaskTarget::Gpu)
{
- // TODO Pass in the inputrec so we can give more help here?
GMX_THROW(NotImplementedError
- ("The input simulation did not use PME in a way that is supported on the GPU."));
+ ("Cannot compute PME interactions on a GPU, because " + message));
+ }
+ return false;
+ }
+ if (!pme_gpu_supports_hardware(hardwareInfo, &message))
+ {
+ if (pmeTarget == TaskTarget::Gpu)
+ {
+ GMX_THROW(NotImplementedError
+ ("Cannot compute PME interactions on a GPU, because " + message));
+ }
+ return false;
+ }
+ if (!pme_gpu_supports_input(inputrec, mtop, &message))
+ {
+ if (pmeTarget == TaskTarget::Gpu)
+ {
+ GMX_THROW(NotImplementedError
+ ("Cannot compute PME interactions on a GPU, because " + message));
}
return false;
}
// Specifying -gputasks requires specifying everything.
if (pmeTarget == TaskTarget::Auto)
{
- GMX_THROW(InconsistentInputError(formatString(g_specifyEverythingFormatString, "all of -nb, -pme, and -ntmpi")));
+ GMX_THROW(InconsistentInputError(formatString(g_specifyEverythingFormatString, "all of -nb, -pme, and -ntmpi"))); // TODO ntmpi?
}
return true;
#include <vector>
struct gmx_hw_info_t;
+struct gmx_mtop_t;
+struct t_inputrec;
enum class EmulateGpuNonbonded : bool;
* \param[in] pmeTarget The user's choice for mdrun -pme for where to assign long-ranged PME nonbonded interaction tasks.
* \param[in] gpuIdsToUse The compatible GPUs that the user permitted us to use.
* \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
- * \param[in] canUseGpuForPme Whether the form of PME chosen can run on a GPU
+ * \param[in] hardwareInfo Hardware information
+ * \param[in] inputrec The user input
+ * \param[in] mtop Global system topology
* \param[in] numRanksPerSimulation The number of ranks in each simulation.
* \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
*
TaskTarget pmeTarget,
const std::vector<int> &gpuIdsToUse,
const std::vector<int> &userGpuTaskAssignment,
- bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
int numRanksPerSimulation,
int numPmeRanksPerSimulation);
* \param[in] useGpuForNonbonded Whether GPUs will be used for nonbonded interactions.
* \param[in] pmeTarget The user's choice for mdrun -pme for where to assign long-ranged PME nonbonded interaction tasks.
* \param[in] userGpuTaskAssignment The user-specified assignment of GPU tasks to device IDs.
- * \param[in] canUseGpuForPme Whether the form of PME chosen can run on a GPU
+ * \param[in] hardwareInfo Hardware information
+ * \param[in] inputrec The user input
+ * \param[in] mtop Global system topology
* \param[in] numRanksPerSimulation The number of ranks in each simulation.
* \param[in] numPmeRanksPerSimulation The number of PME ranks in each simulation.
* \param[in] gpusWereDetected Whether compatible GPUs were detected on any node.
bool decideWhetherToUseGpusForPme(bool useGpuForNonbonded,
TaskTarget pmeTarget,
const std::vector<int> &userGpuTaskAssignment,
- bool canUseGpuForPme,
+ const gmx_hw_info_t &hardwareInfo,
+ const t_inputrec &inputrec,
+ const gmx_mtop_t &mtop,
int numRanksPerSimulation,
int numPmeRanksPerSimulation,
bool gpusWereDetected);
if (pmeOnGpu)
{
GMX_RELEASE_ASSERT((EEL_PME(inputrec->coulombtype) || EVDW_PME(inputrec->vdwtype)) &&
- pme_gpu_supports_build(*hwinfo, nullptr) && pme_gpu_supports_input(*inputrec, *mtop, nullptr),
+ pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(*hwinfo, nullptr) &&
+ pme_gpu_supports_input(*inputrec, *mtop, nullptr),
"PME can't be on GPUs unless we are using PME");
// PME on GPUs supports a single PME rank with PP running on the same or few other ranks.
--- /dev/null
+[ name_OW ]
+ 1 4 7 10 13 16 19 22 25 28 31 34 37 40 43
+ 46 49 52 55 58 61 64 67 70 73 76 79 82 85 88
+ 91 94 97 100 103 106 109 112 115 118 121 124 127 130 133
+ 136 139 142 145 148 151 154 157 160 163 166 169 172 175 178
+ 181 184 187 190 193 196 199 202 205 208 211 214 217 220 223
+ 226 229 232 235 238 241 244 247 250 253 256 259 262 265 268
+ 271 274 277 280 283 286 289 292 295 298 301 304 307 310 313
+ 316 319 322 325 328 331 334 337 340 343 346 349 352 355 358
+ 361 364 367 370 373 376 379 382 385 388 391 394 397 400 403
+ 406 409 412 415 418 421 424 427 430 433 436 439 442 445 448
+ 451 454 457 460 463 466 469 472 475 478 481 484 487 490 493
+ 496 499 502 505 508 511 514 517 520 523 526 529 532 535 538
+ 541 544 547 550 553 556 559 562 565 568 571 574 577 580 583
+ 586 589 592 595 598 601 604 607 610 613 616 619 622 625 628
+ 631 634 637 640 643 646
+
+[ not_name_OW ]
+ 2 3 5 6 8 9 11 12 14 15 17 18 20 21 23
+ 24 26 27 29 30 32 33 35 36 38 39 41 42 44 45
+ 47 48 50 51 53 54 56 57 59 60 62 63 65 66 68
+ 69 71 72 74 75 77 78 80 81 83 84 86 87 89 90
+ 92 93 95 96 98 99 101 102 104 105 107 108 110 111 113
+ 114 116 117 119 120 122 123 125 126 128 129 131 132 134 135
+ 137 138 140 141 143 144 146 147 149 150 152 153 155 156 158
+ 159 161 162 164 165 167 168 170 171 173 174 176 177 179 180
+ 182 183 185 186 188 189 191 192 194 195 197 198 200 201 203
+ 204 206 207 209 210 212 213 215 216 218 219 221 222 224 225
+ 227 228 230 231 233 234 236 237 239 240 242 243 245 246 248
+ 249 251 252 254 255 257 258 260 261 263 264 266 267 269 270
+ 272 273 275 276 278 279 281 282 284 285 287 288 290 291 293
+ 294 296 297 299 300 302 303 305 306 308 309 311 312 314 315
+ 317 318 320 321 323 324 326 327 329 330 332 333 335 336 338
+ 339 341 342 344 345 347 348 350 351 353 354 356 357 359 360
+ 362 363 365 366 368 369 371 372 374 375 377 378 380 381 383
+ 384 386 387 389 390 392 393 395 396 398 399 401 402 404 405
+ 407 408 410 411 413 414 416 417 419 420 422 423 425 426 428
+ 429 431 432 434 435 437 438 440 441 443 444 446 447 449 450
+ 452 453 455 456 458 459 461 462 464 465 467 468 470 471 473
+ 474 476 477 479 480 482 483 485 486 488 489 491 492 494 495
+ 497 498 500 501 503 504 506 507 509 510 512 513 515 516 518
+ 519 521 522 524 525 527 528 530 531 533 534 536 537 539 540
+ 542 543 545 546 548 549 551 552 554 555 557 558 560 561 563
+ 564 566 567 569 570 572 573 575 576 578 579 581 582 584 585
+ 587 588 590 591 593 594 596 597 599 600 602 603 605 606 608
+ 609 611 612 614 615 617 618 620 621 623 624 626 627 629 630
+ 632 633 635 636 638 639 641 642 644 645 647 648
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
runTest(CommandLine(cmdline));
}
+TEST_F(RdfModuleTest, SelectionsSolelyFromIndexFileWork)
+{
+ const char *const cmdline[] = {
+ "rdf",
+ "-bin", "0.05",
+ // Use selection that names a group in the index file
+ "-ref", "name_OW",
+ // Use selections that name groups in the index file
+ "-sel", "name_OW", "not_name_OW"
+ };
+ // Note not supplying a topology file to -s
+ setTrajectory("spc216.gro");
+ setInputFile("-n", "index.ndx");
+ setOutputFile("-o", ".xvg", NoTextMatch());
+ excludeDataset("pairdist");
+ runTest(CommandLine(cmdline));
+}
+
+TEST_F(RdfModuleTest, SelectionsFromBothTopologyFileAndIndexFileWork)
+{
+ const char *const cmdline[] = {
+ "rdf",
+ "-bin", "0.05",
+ // Use selection whose parsing requires topology file
+ "-ref", "name OW",
+ // Use selections that name groups in the index file
+ "-sel", "name_OW", "not_name_OW"
+ };
+ // Note supplying a topology file to -s
+ setTopology("spc216.gro");
+ setInputFile("-n", "index.ndx");
+ setOutputFile("-o", ".xvg", NoTextMatch());
+ excludeDataset("pairdist");
+ runTest(CommandLine(cmdline));
+}
+
TEST_F(RdfModuleTest, CalculatesSurf)
{
const char *const cmdline[] = {
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="CommandLine">rdf -bin 0.05 -ref 'name OW' -sel name_OW not_name_OW</String>
+ <OutputData Name="Data">
+ <AnalysisData Name="norm">
+ <DataFrame Name="Frame0">
+ <Real Name="X">0</Real>
+ <DataValues>
+ <Int Name="Count">3</Int>
+ <DataValue>
+ <Real Name="Value">216</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">33.455901630929986</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">66.911803261859973</Real>
+ </DataValue>
+ </DataValues>
+ </DataFrame>
+ </AnalysisData>
+ <AnalysisData Name="paircount">
+ <DataFrame Name="Frame0">
+ <Real Name="X">0</Real>
+ <DataValues>
+ <Int Name="Count">37</Int>
+ <Int Name="DataSet">0</Int>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">274</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">360</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">226</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">234</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">270</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">332</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">420</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">456</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">548</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">588</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">546</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">632</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">660</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">696</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">822</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">922</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1060</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1084</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1276</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1260</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1260</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1416</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1468</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1560</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1668</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1774</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1578</Real>
+ </DataValue>
+ </DataValues>
+ <DataValues>
+ <Int Name="Count">37</Int>
+ <Int Name="DataSet">1</Int>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">215</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">217</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">114</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">163</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">87</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">52</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">103</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">266</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">618</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">751</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">703</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">722</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">772</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">821</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">946</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1065</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1229</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1281</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1402</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1518</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1640</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1844</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2058</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2137</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2412</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2451</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2650</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2886</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2928</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3101</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3374</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3623</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3288</Real>
+ </DataValue>
+ </DataValues>
+ </DataFrame>
+ </AnalysisData>
+ </OutputData>
+ <OutputFiles Name="Files">
+ <File Name="-o"></File>
+ </OutputFiles>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="CommandLine">rdf -bin 0.05 -ref name_OW -sel name_OW not_name_OW</String>
+ <OutputData Name="Data">
+ <AnalysisData Name="norm">
+ <DataFrame Name="Frame0">
+ <Real Name="X">0</Real>
+ <DataValues>
+ <Int Name="Count">3</Int>
+ <DataValue>
+ <Real Name="Value">216</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">33.455901630929986</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">66.911803261859973</Real>
+ </DataValue>
+ </DataValues>
+ </DataFrame>
+ </AnalysisData>
+ <AnalysisData Name="paircount">
+ <DataFrame Name="Frame0">
+ <Real Name="X">0</Real>
+ <DataValues>
+ <Int Name="Count">37</Int>
+ <Int Name="DataSet">0</Int>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">274</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">360</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">226</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">234</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">270</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">332</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">420</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">456</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">548</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">588</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">546</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">632</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">660</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">696</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">822</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">922</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1060</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1084</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1276</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1260</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1260</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1416</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1468</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1560</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1668</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1774</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1578</Real>
+ </DataValue>
+ </DataValues>
+ <DataValues>
+ <Int Name="Count">37</Int>
+ <Int Name="DataSet">1</Int>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">215</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">217</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">0</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">114</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">163</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">87</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">52</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">103</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">266</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">618</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">751</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">703</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">722</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">772</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">821</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">946</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1065</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1229</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1281</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1402</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1518</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1640</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">1844</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2058</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2137</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2412</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2451</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2650</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2886</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">2928</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3101</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3374</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3623</Real>
+ </DataValue>
+ <DataValue>
+ <Real Name="Value">3288</Real>
+ </DataValue>
+ </DataValues>
+ </DataFrame>
+ </AnalysisData>
+ </OutputData>
+ <OutputFiles Name="Files">
+ <File Name="-o"></File>
+ </OutputFiles>
+</ReferenceData>
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2018, by the GROMACS development team, led by
+ * Copyright (c) 2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
TopologyInformation topInfo;
EXPECT_FALSE(topInfo.hasTopology());
EXPECT_FALSE(topInfo.hasFullTopology());
- ASSERT_TRUE(topInfo.mtop());
- EXPECT_EQ(0, topInfo.mtop()->natoms);
- EXPECT_FALSE(topInfo.expandedTopology());
+ EXPECT_EQ(nullptr, topInfo.mtop());
+ EXPECT_EQ(nullptr, topInfo.expandedTopology());
auto atoms1 = topInfo.copyAtoms();
EXPECT_TRUE(atoms1);
auto atoms2 = topInfo.copyAtoms();
{
TopologyInformation::TopologyInformation()
- : mtop_(std::make_unique<gmx_mtop_t>()),
- hasLoadedMtop_(false),
+ : hasLoadedMtop_(false),
expandedTopology_(nullptr),
atoms_ (nullptr),
bTop_(false), ePBC_(-1)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
continue;
}
auto modeTargetsPmeOnGpus = (mode.first.find("PmeOnGpu") != std::string::npos);
- if (modeTargetsPmeOnGpus && !pme_gpu_supports_build(*hardwareInfo_, nullptr))
+ if (modeTargetsPmeOnGpus &&
+ !(pme_gpu_supports_build(nullptr) &&
+ pme_gpu_supports_hardware(*hardwareInfo_, nullptr)))
{
// This run mode will cause a fatal error from mdrun when
// it finds an unsuitable device, which is not something