include(gmxBuildTypeTSAN)
include(gmxBuildTypeASAN)
include(gmxBuildTypeMSAN)
+include(gmxBuildTypeUBSAN)
include(gmxBuildTypeReleaseWithAssert)
if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel Reference RelWithAssert Profile TSAN ASAN MSAN." FORCE)
+ set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel Reference RelWithAssert Profile TSAN ASAN MSAN UBSAN." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
- "MinSizeRel" "RelWithDebInfo" "Reference" "RelWithAssert" "Profile" "TSAN" "ASAN" "MSAN")
+ "MinSizeRel" "RelWithDebInfo" "Reference" "RelWithAssert" "Profile" "TSAN" "ASAN" "MSAN" "UBSAN")
endif()
if(CMAKE_CONFIGURATION_TYPES)
# Add appropriate GROMACS-specific build types for the Visual
COMPILER_MAJOR_VERSION: 8
CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=ASAN"
+gromacs:clang-UBSAN:configure:
+ extends:
+ - .gromacs:base:configure
+ - .use-clang:base
+ - .rules:merge-requests
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
+ variables:
+ COMPILER_MAJOR_VERSION: 8
+ CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=UBSAN"
+
gromacs:gcc-8-cuda-10.1:release:configure:
extends:
- .gromacs:base:release:configure
needs:
- job: gromacs:clang-ASAN:configure
+gromacs:clang-UBSAN:build:
+ extends:
+ - .variables:default
+ - .gromacs:base:build
+ - .use-clang:base
+ - .use-ccache
+ - .rules:merge-requests
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
+ tags:
+ - k8s-scilifelab
+ needs:
+ - job: gromacs:clang-UBSAN:configure
+
gromacs:clang-static-analyzer:build:
extends:
- .variables:default
CTEST_RUN_MODE: "ExperimentalTest"
script:
- cd $BUILD_DIR
+ - export UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1:suppressions=$CI_PROJECT_DIR/admin/ubsan-suppressions.txt
# Needed to run MPI enabled code in the docker images, until we set up different users
- export OMPI_ALLOW_RUN_AS_ROOT=1
- export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
needs:
- job: gromacs:clang-ASAN:build
+gromacs:clang-UBSAN:test:
+ extends:
+ - .gromacs:base:test
+ - .use-clang:base
+ - .rules:merge-requests
+ image: gromacs/cmake-3.13.0-llvm-8-tsan:master
+ tags:
+ - k8s-scilifelab
+ needs:
+ - job: gromacs:clang-UBSAN:build
+
gromacs:clang-9-mpi:test:
extends:
- .gromacs:base:test
--- /dev/null
+# Add UBSAN suppressions here, with a leading comment about how and
+# why it is appropriate, and any circumstances about when it should be
+# removed.
+
+# This is only a problem when using the built-in XDR implementation of
+# xdr_vector. It supplies an extra argument needed for xdr_string
+# which is unused by other xdr_* primitives like xdr_float. The issue
+# is harmless and only active when not using a system XDR library.
+function:xdr_vector
--- /dev/null
+#
+# This file is part of the GROMACS molecular simulation package.
+#
+# Copyright (c) 2020, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
+#
+# GROMACS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1
+# of the License, or (at your option) any later version.
+#
+# GROMACS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GROMACS; if not, see
+# http://www.gnu.org/licenses, or write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# If you want to redistribute modifications to GROMACS, please
+# consider that scientific software is very special. Version
+# control is crucial - bugs must be traceable. We will be happy to
+# consider code for inclusion in the official distribution, but
+# derived work must not be called official GROMACS. Details are found
+# in the README & COPYING files - if they are missing, get the
+# official version at http://www.gromacs.org.
+#
+# To help us fund GROMACS development, we humbly ask that you cite
+# the research papers on the package. Check out http://www.gromacs.org.
+
+# Custom build type "UBSAN", to be used to run the
+# undefined behaviour memory checker.
+
+set(_flags "-O1 -g -fsanitize=undefined -fno-omit-frame-pointer")
+foreach(_language C CXX)
+ string(REPLACE "X" "+" _human_readable_language ${_language})
+ set(CMAKE_${_language}_FLAGS_UBSAN ${_flags} CACHE STRING "${_human_readable_language} flags for undefined behavior sanitizer" FORCE)
+ mark_as_advanced(CMAKE_${_language}_FLAGS_UBSAN)
+endforeach()
#define CMAKE_BUILD_TYPE_TSAN 8
#define CMAKE_BUILD_TYPE_ASAN 9
#define CMAKE_BUILD_TYPE_MSAN 10
+#define CMAKE_BUILD_TYPE_UBSAN 11
#cmakedefine CMAKE_BUILD_TYPE CMAKE_BUILD_TYPE_@CMAKE_BUILD_TYPE_UPPER@
/* Define relative path to OpenCL kernels */
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/paddedvector.h"
#include "gromacs/mdlib/forcerec.h"
+#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/enerdata.h"
#include "gromacs/mdtypes/forceoutput.h"
#include "gromacs/mdtypes/iforceprovider.h"
// Prepare a ForceProviderInput
t_mdatoms md;
std::vector<real> chargeA{ 1 };
- md.homenr = ssize(chargeA);
- md.chargeA = chargeA.data();
- CommrecHandle cr = init_commrec(MPI_COMM_WORLD);
+ md.homenr = ssize(chargeA);
+ md.chargeA = chargeA.data();
+ t_commrec cr;
matrix boxDummy = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
- ForceProviderInput forceProviderInput({}, md, 0.0, boxDummy, *cr);
+ ForceProviderInput forceProviderInput({}, md, 0.0, boxDummy, cr);
// Prepare a ForceProviderOutput
PaddedVector<RVec> f = { { 0, 0, 0 } };
*/
thread_work_t(const gmx_ffparams_t& ffparams) : idef(ffparams) {}
- InteractionDefinitions idef; /**< Partial local topology */
- std::unique_ptr<gmx::VsitePbc> vsitePbc; /**< vsite PBC structure */
- int nbonded; /**< The number of bondeds in this struct */
- ListOfLists<int> excl; /**< List of exclusions */
- int excl_count; /**< The total exclusion count for \p excl */
+ InteractionDefinitions idef; /**< Partial local topology */
+ std::unique_ptr<gmx::VsitePbc> vsitePbc = nullptr; /**< vsite PBC structure */
+ int nbonded = 0; /**< The number of bondeds in this struct */
+ ListOfLists<int> excl; /**< List of exclusions */
+ int excl_count = 0; /**< The total exclusion count for \p excl */
};
/*! \brief Struct for the reverse topology: links bonded interactions to atomsx */
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
// requires 64-bit systems.
static_assert(2 * sizeof(int) >= 8,
"XDR handling assumes that an int64_t can be stored in two ints");
- int imaj, imin;
- int ret;
- static const int64_t two_p32_m1 = 0xFFFFFFFF;
- int64_t imaj64, imin64;
+ static const uint64_t two_p32_m1 = 0xFFFFFFFF;
- imaj64 = ((*i) >> 32) & two_p32_m1;
- imin64 = (*i) & two_p32_m1;
- imaj = static_cast<int>(imaj64);
- imin = static_cast<int>(imin64);
- ret = xdr_int(xdrs, &imaj);
+ uint64_t imaj64 = ((*i) >> 32) & two_p32_m1;
+ uint64_t imin64 = (*i) & two_p32_m1;
+ int imaj = static_cast<int>(imaj64);
+ int imin = static_cast<int>(imin64);
+ int ret = xdr_int(xdrs, &imaj);
ret |= xdr_int(xdrs, &imin);
- *i = ((static_cast<int64_t>(imaj) << 32) | (static_cast<int64_t>(imin) & two_p32_m1));
+ *i = ((static_cast<uint64_t>(imaj) << 32) | (static_cast<uint64_t>(imin) & two_p32_m1));
return ret;
}
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2011,2014,2015,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2011,2014,2015,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
for (n = 0; (n <= nnb->nrex); n++)
{
/* Sort atoms in this list */
- qsort(nnb->a[i][n], nnb->nrexcl[i][n], sizeof(int), compare_int);
-
+ if (nnb->nrexcl[i][n] > 0)
+ {
+ qsort(nnb->a[i][n], nnb->nrexcl[i][n], sizeof(int), compare_int);
+ }
cnt = 0;
prev = -1;
for (j = 0; j < nnb->nrexcl[i][n]; j++)
itp_file_(nullptr),
mHmult_(0)
{
+ gmx::LoggerBuilder builder;
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Info, &gmx::TextOutputFile::standardOutput());
+ builder.addTargetStream(gmx::MDLogger::LogLevel::Warning, &gmx::TextOutputFile::standardError());
+ loggerOwner_ = std::make_unique<LoggerOwner>(builder.build());
}
// From ICommandLineOptionsModule
WaterType waterType_;
MergeType mergeType_;
- FILE* itp_file_;
- char forcefield_[STRLEN];
- char ffdir_[STRLEN];
- char* ffname_;
- char* watermodel_;
- std::vector<std::string> incls_;
- std::vector<t_mols> mols_;
- real mHmult_;
- std::unique_ptr<gmx::MDLogger> loggerPointer_;
+ FILE* itp_file_;
+ char forcefield_[STRLEN];
+ char ffdir_[STRLEN];
+ char* ffname_;
+ char* watermodel_;
+ std::vector<std::string> incls_;
+ std::vector<t_mols> mols_;
+ real mHmult_;
+ std::unique_ptr<LoggerOwner> loggerOwner_;
};
void pdb2gmx::initOptions(IOptionsContainer* options, ICommandLineOptionsModuleSettings* settings)
/* Force field selection, interactive or direct */
choose_ff(strcmp(ff_.c_str(), "select") == 0 ? nullptr : ff_.c_str(), forcefield_,
- sizeof(forcefield_), ffdir_, sizeof(ffdir_), *loggerPointer_);
+ sizeof(forcefield_), ffdir_, sizeof(ffdir_), loggerOwner_->logger());
if (strlen(forcefield_) > 0)
{
int this_chainstart;
int prev_chainstart;
- gmx::LoggerBuilder builder;
- builder.addTargetStream(gmx::MDLogger::LogLevel::Info, &gmx::TextOutputFile::standardOutput());
- builder.addTargetStream(gmx::MDLogger::LogLevel::Warning, &gmx::TextOutputFile::standardError());
- gmx::LoggerOwner logOwner(builder.build());
- loggerPointer_ = std::make_unique<gmx::MDLogger>(logOwner.logger());
- const gmx::MDLogger& logger = *loggerPointer_;
+ const gmx::MDLogger& logger = loggerOwner_->logger();
GMX_LOG(logger.info)
.asParagraph()
"Either specify the -ei option to mdrun, or do not use this checkpoint file.");
}
- initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
+ int* fep_state = MASTER(cr) ? &state_global->fep_state : nullptr;
+ gmx::ArrayRef<real> lambda = MASTER(cr) ? state_global->lambda : gmx::ArrayRef<real>();
+ initialize_lambdas(fplog, *ir, MASTER(cr), fep_state, lambda, lam0);
Update upd(*ir, deform);
const bool doSimulatedAnnealing = initSimulatedAnnealing(ir, &upd);
const bool useReplicaExchange = (replExParams.exchangeInterval > 0);
{
state_global->ngtc = 0;
}
- initialize_lambdas(fplog, *ir, MASTER(cr), &(state_global->fep_state), state_global->lambda, nullptr);
+ int* fep_state = MASTER(cr) ? &state_global->fep_state : nullptr;
+ gmx::ArrayRef<real> lambda = MASTER(cr) ? state_global->lambda : gmx::ArrayRef<real>();
+ initialize_lambdas(fplog, *ir, MASTER(cr), fep_state, lambda, nullptr);
if (ir->eI == eiNM)
{
}
/* Send IMD energies and positions, if bIMD is TRUE. */
- if (imdSession->run(count, TRUE, state_global->box,
+ if (imdSession->run(count, TRUE, MASTER(cr) ? state_global->box : nullptr,
MASTER(cr) ? state_global->x.rvec_array() : nullptr, 0)
&& MASTER(cr))
{
auto nonConstGlobalTopology = const_cast<gmx_mtop_t*>(top_global);
nonConstGlobalTopology->intermolecularExclusionGroup = genQmmmIndices(*top_global);
}
-
- initialize_lambdas(fplog, *ir, MASTER(cr), &state_global->fep_state, state_global->lambda, lam0);
+ int* fep_state = MASTER(cr) ? &state_global->fep_state : nullptr;
+ gmx::ArrayRef<real> lambda = MASTER(cr) ? state_global->lambda : gmx::ArrayRef<real>();
+ initialize_lambdas(fplog, *ir, MASTER(cr), fep_state, lambda, lam0);
const bool simulationsShareState = false;
gmx_mdoutf* outf = init_mdoutf(fplog, nfile, fnm, mdrunOptions, cr, outputProvider,
mdModulesNotifier, ir, top_global, oenv, wcycle,
snew(oriresdata, 1);
init_orires(fplog, &mtop, inputrec, cr, ms, globalState.get(), oriresdata);
- auto deform = prepareBoxDeformation(globalState->box, MASTER(cr) ? DDRole::Master : DDRole::Agent,
- PAR(cr) ? NumRanks::Multiple : NumRanks::Single,
- cr->mpi_comm_mygroup, *inputrec);
+ auto deform = prepareBoxDeformation(
+ globalState != nullptr ? globalState->box : box, MASTER(cr) ? DDRole::Master : DDRole::Agent,
+ PAR(cr) ? NumRanks::Multiple : NumRanks::Single, cr->mpi_comm_mygroup, *inputrec);
ObservablesHistory observablesHistory = {};
/* override nsteps with value set on the commandline */
override_nsteps_cmdline(mdlog, mdrunOptions.numStepsCommandline, inputrec);
- if (SIMMASTER(cr))
+ if (isSimulationMasterRank)
{
copy_mat(globalState->box, box);
}
/* we need to join all threads. The sub-threads join when they
exit this function, but the master thread needs to be told to
wait for that. */
- if (PAR(cr) && MASTER(cr))
+ if (MASTER(cr))
{
tMPI_Finalize();
}
MPI_Initialized(&mpiIsInitialized);
if (mpiIsInitialized)
{
- bool detectedDefaultAffinityMaskOnAllRanks;
- MPI_Allreduce(&detectedDefaultAffinityMask, &detectedDefaultAffinityMaskOnAllRanks, 1,
- MPI_C_BOOL, MPI_LAND, MPI_COMM_WORLD);
- detectedDefaultAffinityMask = detectedDefaultAffinityMaskOnAllRanks;
+ bool maskToReduce = detectedDefaultAffinityMask;
+ MPI_Allreduce(&maskToReduce, &detectedDefaultAffinityMask, 1, MPI_C_BOOL, MPI_LAND, MPI_COMM_WORLD);
}
#endif
}
/* Returns the j-zone range for pairlist construction for the give locality and i-zone */
-static Range<int> getJZoneRange(const gmx_domdec_zones_t& ddZones,
+static Range<int> getJZoneRange(const gmx_domdec_zones_t* ddZones,
const InteractionLocality locality,
const int iZone)
{
else if (iZone == 0)
{
/* Non-local: we need to avoid the local (zone 0 vs 0) interactions */
- return { 1, *ddZones.iZones[iZone].jZoneRange.end() };
+ return { 1, *ddZones->iZones[iZone].jZoneRange.end() };
}
else
{
/* Non-local with non-local i-zone: use all j-zones */
- return ddZones.iZones[iZone].jZoneRange;
+ return ddZones->iZones[iZone].jZoneRange;
}
}
}
}
- const gmx_domdec_zones_t& ddZones = *gridSet.domainSetup().zones;
+ const gmx_domdec_zones_t* ddZones = gridSet.domainSetup().zones;
+ GMX_ASSERT(locality_ == InteractionLocality::Local || ddZones != nullptr,
+ "Nonlocal interaction locality with null ddZones.");
const auto iZoneRange = getIZoneRange(gridSet.domainSetup(), locality_);
/* With GPU: generate progressively smaller lists for
* load balancing for local only or non-local with 2 zones.
*/
- progBal = (locality_ == InteractionLocality::Local || ddZones.n <= 2);
+ progBal = (locality_ == InteractionLocality::Local || ddZones->n <= 2);
#pragma omp parallel for num_threads(numLists) schedule(static)
for (int th = 0; th < numLists; th++)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2015,2017,2019, by the GROMACS development team, led by
+ * Copyright (c) 2015,2017,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "testutils/stringtest.h"
public:
void testFormatting(const std::string& text, gmx::HelpOutputFormat format, const char* id)
{
- gmx::HelpWriterContext context(nullptr, format);
+ FILE* fp = nullptr;
+ gmx::TextWriter writerStub(fp);
+ gmx::HelpWriterContext context(&writerStub, format);
std::string result = context.substituteMarkupAndWrapToString(settings_, text);
if (id == nullptr)
{
srenew(t->a, g->isize);
t->nalloc_a = g->isize;
}
- std::memcpy(t->a, g->index, g->isize * sizeof(*(t->a)));
+ if (t->nra > 0)
+ {
+ std::memcpy(t->a, g->index, g->isize * sizeof(*(t->a)));
+ }
}
/* Allocate memory for the block index. We don't know in advance
dest->b.nra = src->b.nra;
std::memcpy(dest->orgid, src->orgid, dest->b.nr * sizeof(*dest->orgid));
std::memcpy(dest->b.index, src->b.index, (dest->b.nr + 1) * sizeof(*dest->b.index));
- std::memcpy(dest->b.a, src->b.a, dest->b.nra * sizeof(*dest->b.a));
+ if (dest->b.nra > 0)
+ {
+ std::memcpy(dest->b.a, src->b.a, dest->b.nra * sizeof(*dest->b.a));
+ }
}
dest->mapb.nr = src->mapb.nr;
dest->mapb.nra = src->mapb.nra;
nparams = sel->u.expr.method->nparams;
orgparam = sel->u.expr.method->param;
snew(param, nparams);
- memcpy(param, orgparam, nparams * sizeof(gmx_ana_selparam_t));
+ if (nparams > 0)
+ {
+ memcpy(param, orgparam, nparams * sizeof(gmx_ana_selparam_t));
+ }
for (i = 0; i < nparams; ++i)
{
param[i].flags &= ~SPAR_SET;
while (j < g->isize)
{
/* Do a binary search of the strings. */
- void* ptr;
- ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
+ void* ptr = nullptr;
+ if (d->nas > 0)
+ {
+ ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
+ }
/* Check whether the value was found in the as list. */
if (ptr == nullptr)
{
constexpr ArrayRefIter(ArrayRefIter<std::remove_const_t<T2>> it) noexcept : it_(&*it)
{
}
-
+ constexpr T* data() const noexcept { return it_; }
constexpr T& operator*() const noexcept { return *it_; }
constexpr ArrayRefIter& operator+=(std::ptrdiff_t i) noexcept
{
return begin_[n];
}
//! Returns the first element.
- reference front() const { return *begin_; }
+ reference front() const { return *(begin_); }
//! Returns the first element.
reference back() const { return *(end_ - 1); }
//! Returns a raw pointer to the contents of the array.
- pointer data() const { return &*begin_; }
+ pointer data() const { return begin_.data(); }
/*! \brief
* Swaps referenced memory with the other object.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2018,2019, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018,2019,2020, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* This class is responsible of managing all memory allocated by LoggerBuilder
* that is needed for operation of the actual logger. Also the actual logger
- * instance is owned by this class. This allows keeing the actual logger simple
+ * instance is owned by this class. This allows keeping the actual logger simple
* and streamlined.
*
* This class supports move construction and assignment, which allows