AVX2_128 extensions also supports AVX_256, so we enable such support
for the group-scheme kernels.
-Improved Ewald-style short-ranged interactions on Intel Skylake CPUs
-""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-These now default to use tabulated Ewald short-ranged interactions.
-
Detect AVX-512 FMA units to choose best SIMD
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Recent Intel x86 hardware can have multiple AVX-512 FMA units, and the
if (C->verbosity)
fprintf(msgfile, " fnorm = %18.8g\n", fnorm);
- if (!isfinite(fnorm)) {
+ if (!std::isfinite(fnorm)) {
S->outcome = 12; /* nan */
goto terminate;
} else if (fnorm <= LM_DWARF) {
} else {
xnorm = lm_enorm(n, x);
}
- if (!isfinite(xnorm)) {
+ if (!std::isfinite(xnorm)) {
S->outcome = 12; /* nan */
goto terminate;
}
/* Predict scaled reduction. */
pnorm = lm_enorm(n, wa3);
- if (!isfinite(pnorm)) {
+ if (!std::isfinite(pnorm)) {
S->outcome = 12; /* nan */
goto terminate;
}
wa3[i] -= fjac[j*m+i] * wa1[Pivot[j]];
}
temp1 = SQR(lm_enorm(n, wa3) / fnorm);
- if (!isfinite(temp1)) {
+ if (!std::isfinite(temp1)) {
S->outcome = 12; /* nan */
goto terminate;
}
if (S->userbreak)
goto terminate;
fnorm1 = lm_enorm(m, wf);
- if (!isfinite(fnorm1)) {
+ if (!std::isfinite(fnorm1)) {
S->outcome = 12; /* nan */
goto terminate;
}
for (i = 0; i < m; i++)
fvec[i] = wf[i];
xnorm = lm_enorm(n, wa2);
- if (!isfinite(xnorm)) {
+ if (!std::isfinite(xnorm)) {
S->outcome = 12; /* nan */
goto terminate;
}
const interaction_const_t *ic = fr->ic;
- ewtab = ic->tabq_coul_FDV0;
- ewtabscale = ic->tabq_scale;
- ewtabhalfspace = 0.5/ewtabscale;
+ if (ielec == GMX_NBKERNEL_ELEC_EWALD)
+ {
+ ewtab = ic->tabq_coul_FDV0;
+ ewtabscale = ic->tabq_scale;
+ ewtabhalfspace = 0.5/ewtabscale;
+ }
+ else
+ {
+ ewtab = nullptr;
+ ewtabhalfspace = ewtabscale = 0;
+ }
rcoulomb2 = ic->rcoulomb*ic->rcoulomb;
rvdw = ic->rvdw;
ki = pbc_rvec_sub(pbc, x[ai], x[aj], dx); /* 3 */
dr2 = iprod(dx, dx); /* 5 */
- dr = dr2*gmx::invsqrt(dr2); /* 10 */
+ dr = std::sqrt(dr2); /* 10 */
*dvdlambda += harmonic(forceparams[type].harmonic.krA,
forceparams[type].harmonic.krB,
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2012,2014,2015,2017, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015,2017,2018, 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 eb;
}
+void done_ebin(t_ebin *eb)
+{
+ for (int i = 0; i < eb->nener; i++)
+ {
+ sfree(eb->enm[i].name);
+ sfree(eb->enm[i].unit);
+ }
+ sfree(eb->e);
+ sfree(eb->e_sim);
+ sfree(eb->enm);
+}
+
int get_ebin_space(t_ebin *eb, int nener, const char *enm[], const char *unit)
{
int index;
return index;
}
-void add_ebin(t_ebin *eb, int index, int nener, real ener[], gmx_bool bSum)
+void add_ebin(t_ebin *eb, int index, int nener, const real ener[], gmx_bool bSum)
{
int i, m;
double e, invmm, diff;
int prmode, gmx_bool bPrHead)
{
int i, j, i0;
- real ee = 0;
int rc;
char buf[30];
rc = 0;
- if (index < 0)
+ if (index < 0 || index > eb->nener)
{
gmx_fatal(FARGS, "Invalid index in pr_ebin: %d", index);
}
- if (nener == -1)
+ int start = index;
+ if (nener > eb->nener)
{
- nener = eb->nener;
+ gmx_fatal(FARGS, "Invalid nener in pr_ebin: %d", nener);
}
- else
+ int end = eb->nener;
+ if (nener != -1)
{
- nener = index + nener;
+ end = index + nener;
}
- for (i = index; (i < nener) && rc >= 0; )
+ for (i = start; (i < end) && rc >= 0; )
{
if (bPrHead)
{
i0 = i;
- for (j = 0; (j < nperline) && (i < nener) && rc >= 0; j++, i++)
+ for (j = 0; (j < nperline) && (i < end) && rc >= 0; j++, i++)
{
if (strncmp(eb->enm[i].name, "Pres", 4) == 0)
{
i = i0;
}
- for (j = 0; (j < nperline) && (i < nener) && rc >= 0; j++, i++)
+ for (j = 0; (j < nperline) && (i < end) && rc >= 0; j++, i++)
{
switch (prmode)
{
- case eprNORMAL: ee = eb->e[i].e; break;
- case eprAVER: ee = eb->e_sim[i].esum/eb->nsum_sim; break;
+ case eprNORMAL:
+ rc = fprintf(fp, " %12.5e", eb->e[i].e);
+ break;
+ case eprAVER:
+ if (eb->nsum_sim > 0)
+ {
+ rc = fprintf(fp, " %12.5e", eb->e_sim[i].esum/eb->nsum_sim);
+ }
+ else
+ {
+ rc = fprintf(fp, " %-12s", "N/A");
+ }
+ break;
default: gmx_fatal(FARGS, "Invalid print mode %d in pr_ebin",
prmode);
}
- rc = fprintf(fp, " %12.5e", ee);
}
if (rc >= 0)
{
*
* Copyright (c) 1991-2000, University of Groningen, The Netherlands.
* Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2018, 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.
t_ebin *mk_ebin(void);
/* Create an energy bin */
+//! Empty the contents of \c eb.
+void done_ebin(t_ebin *eb);
+
int get_ebin_space(t_ebin *eb, int nener, const char *enm[], const char *unit);
/* Create space in the energy bin and register names.
* calls to add_ebin.
*/
-void add_ebin(t_ebin *eb, int index, int nener, real ener[], gmx_bool bSum);
+void add_ebin(t_ebin *eb, int index, int nener, const real ener[], gmx_bool bSum);
/* Add nener reals (eg. energies, box-lengths, pressures) to the
* energy bin at position index.
* If bSum is TRUE then the reals are also added to the sum
void reset_ebin_sums(t_ebin *eb);
/* Reset the average and fluctuation sums */
+/*! \brief Print the contents of some energy bins.
+ *
+ * We will print nperline entries on a text line (advisory <=
+ * 5). prmode may be any of the above listed enum values. tsteps is
+ * used only when eprAVER or eprRMS is set. If bPrHead than the
+ * header is printed.
+ *
+ * \c index and \c nener must be in [0, eb->nener), except that \c
+ * nener -1 is interpreted as eb->nener.
+ *
+ * \todo Callers should be refactored pass eb->nener, rather than
+ * us implement and rely on this special behaviour of -1. */
void pr_ebin(FILE *fp, t_ebin *eb, int index, int nener, int nperline,
int prmode, gmx_bool bPrHead);
-/* Print the contents of the energy bin. If nener = -1 ALL energies from
- * index to the end will be printed. We will print nperline entries on a text
- * line (advisory <= 5). prmode may be any of the above listed enum values.
- * tsteps is used only when eprAVER or eprRMS is set.
- * If bPrHead than the header is printed.
- */
#endif
gmx_fatal(FARGS, "Unsupported electrostatic interaction: %s", eel_names[ic->eeltype]);
break;
}
+ fr->nbkernel_elec_modifier = ic->coulomb_modifier;
/* Vdw: Translate from mdp settings to kernel format */
switch (ic->vdwtype)
gmx_fatal(FARGS, "Unsupported vdw interaction: %s", evdw_names[ic->vdwtype]);
break;
}
+ fr->nbkernel_vdw_modifier = ic->vdw_modifier;
if (ir->cutoff_scheme == ecutsGROUP)
{
"Step", "Time", gmx_step_str(steps, buf), time);
}
+// TODO It is too many responsibilities for this function to handle
+// both .edr and .log output for both per-time and time-average data.
void print_ebin(ener_file_t fp_ene, gmx_bool bEne, gmx_bool bDR, gmx_bool bOR,
FILE *log,
gmx_int64_t step, double time,
t_enxframe fr;
+ if (mode == eprAVER && md->ebin->nsum_sim <= 0)
+ {
+ if (log)
+ {
+ fprintf(log, "Not enough data recorded to report energy averages\n");
+ }
+ return;
+ }
+
switch (mode)
{
case eprNORMAL:
#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2014,2016,2017, by the GROMACS development team, led by
+# Copyright (c) 2014,2016,2017,2018, 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.
gmx_add_unit_test(MdlibUnitTest mdlib-test
calc_verletbuf.cpp
+ mdebin.cpp
settle.cpp
shake.cpp
simulationsignal.cpp)
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2018, 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.
+ */
+#include "gmxpre.h"
+
+#include "gromacs/mdlib/mdebin.h"
+
+#include <cstdio>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/utility/textreader.h"
+#include "gromacs/utility/unique_cptr.h"
+
+#include "testutils/refdata.h"
+#include "testutils/testasserts.h"
+#include "testutils/testfilemanager.h"
+
+namespace gmx
+{
+namespace test
+{
+namespace
+{
+
+//! Wraps fclose to discard the return value to use it as a deleter with gmx::unique_cptr.
+void fcloseWrapper(FILE *fp)
+{
+ fclose(fp);
+}
+
+class PrintEbin : public ::testing::Test
+{
+ public:
+ t_ebin ebin_;
+ unique_cptr<t_ebin, done_ebin> ebinGuard_;
+ t_mdebin mdebin_;
+
+ TestFileManager fileManager_;
+ // TODO This will be more elegant (and run faster) when we
+ // refactor the output routines to write to a stream
+ // interface, which can already be handled in-memory when
+ // running tests.
+ std::string logFilename_;
+ FILE *log_;
+ unique_cptr<FILE, fcloseWrapper> logFileGuard_;
+
+ TestReferenceData refData_;
+ TestReferenceChecker checker_;
+
+ PrintEbin() : ebin_ {0}, ebinGuard_(&ebin_), mdebin_ {0},
+ fileManager_(), logFilename_(fileManager_.getTemporaryFilePath(".log")),
+ log_(std::fopen(logFilename_.c_str(), "w")), logFileGuard_(log_),
+ refData_ {}, checker_(refData_.rootChecker())
+ {
+ mdebin_.ebin = &ebin_;
+ }
+};
+
+TEST_F(PrintEbin, print_ebin_HandlesEmptyAverages)
+{
+ ASSERT_NE(log_, nullptr);
+
+ // Test print_ebin
+ print_ebin(nullptr, false, false, false, log_,
+ 0, 0, eprAVER,
+ &mdebin_, nullptr, nullptr, nullptr, nullptr);
+
+ // We need to close the file before the contents are available.
+ logFileGuard_.reset(nullptr);
+
+ checker_.checkString(TextReader::readFileToString(logFilename_), "log");
+}
+
+// TODO Ideally we'd test for proper output of a normal t_mdebin, but
+// building one is a lot of work for limited value.
+
+TEST_F(PrintEbin, pr_ebin_HandlesAverages)
+{
+ ASSERT_NE(log_, nullptr);
+
+ // Set up the energy entries
+ const char *firstName[] = {"first"};
+ const char *secondName[] = {"second"};
+ int first = get_ebin_space(mdebin_.ebin, 1, firstName, nullptr);
+ int second = get_ebin_space(mdebin_.ebin, 1, secondName, nullptr);
+
+ // Put some data into the energy entries
+ const real timevalues[2][2] = { { 1.0, 10.0}, {2.0, 20.0} };
+ gmx_bool bSum = true;
+ for (const auto &values : timevalues)
+ {
+ add_ebin(mdebin_.ebin, first, 1, &values[0], bSum);
+ add_ebin(mdebin_.ebin, second, 1, &values[1], bSum);
+ ebin_increase_count(mdebin_.ebin, bSum);
+ }
+
+ // Test pr_ebin
+ pr_ebin(log_, &ebin_, 0, 2, 5, eprAVER, true);
+
+ // We need to close the file before the contents are available.
+ logFileGuard_.reset(nullptr);
+
+ checker_.checkString(TextReader::readFileToString(logFilename_), "log");
+}
+
+TEST_F(PrintEbin, pr_ebin_HandlesEmptyAverages)
+{
+ ASSERT_NE(log_, nullptr);
+
+ // Set up the energy entries
+ const char *firstName[] = {"first"};
+ const char *secondName[] = {"second"};
+ get_ebin_space(mdebin_.ebin, 1, firstName, nullptr);
+ get_ebin_space(mdebin_.ebin, 1, secondName, nullptr);
+
+ // Test pr_ebin
+ pr_ebin(log_, &ebin_, 0, 2, 5, eprAVER, true);
+
+ // We need to close the file before the contents are available.
+ logFileGuard_.reset(nullptr);
+
+ checker_.checkString(TextReader::readFileToString(logFilename_), "log");
+}
+
+} // namespace
+} // namespace
+} // namespace
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="log"> first second
+ 1.50000e+00 1.50000e+01
+</String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="log"> first second
+ N/A N/A
+</String>
+</ReferenceData>
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="log">Not enough data recorded to report energy averages
+</String>
+</ReferenceData>
/* We need to allocate one element extra, since we might use
* (unaligned) 4-wide SIMD loads to access rvec entries.
*/
- f.resize(top_global->natoms + 1);
+ f.resize(gmx::paddedRVecVectorSize(top_global->natoms));
/* Print to log file */
walltime_accounting_start(walltime_accounting);
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadUBySimdIntTranspose(const double *base, SimdDInt32 offset, Targs... Fargs)
+gatherLoadUBySimdIntTranspose(const double *base, SimdDInt32 offset, SimdDouble *v, Targs... Fargs)
{
- gatherLoadBySimdIntTranspose<align>(base, offset, Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, offset, v, Fargs ...);
}
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadTranspose(const double *base, const std::int32_t offset[], Targs... Fargs)
+gatherLoadTranspose(const double *base, const std::int32_t offset[], SimdDouble *v, Targs... Fargs)
{
- gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdDInt32Tag()), Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdDInt32Tag()), v, Fargs ...);
}
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadUTranspose(const double *base, const std::int32_t offset[], Targs... Fargs)
+gatherLoadUTranspose(const double *base, const std::int32_t offset[], SimdDouble *v, Targs... Fargs)
{
- gatherLoadTranspose<align>(base, offset, Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdDInt32Tag()), v, Fargs ...);
}
template <int align>
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadUBySimdIntTranspose(const float *base, SimdFInt32 offset, Targs... Fargs)
+gatherLoadUBySimdIntTranspose(const float *base, SimdFInt32 offset, SimdFloat *v, Targs... Fargs)
{
- gatherLoadBySimdIntTranspose<align>(base, offset, Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, offset, v, Fargs ...);
}
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadTranspose(const float *base, const std::int32_t offset[], Targs... Fargs)
+gatherLoadTranspose(const float *base, const std::int32_t offset[], SimdFloat *v, Targs... Fargs)
{
- gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdFInt32Tag()), Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdFInt32Tag()), v, Fargs ...);
}
template <int align, typename ... Targs>
static inline void gmx_simdcall
-gatherLoadUTranspose(const float *base, const std::int32_t offset[], Targs... Fargs)
+gatherLoadUTranspose(const float *base, const std::int32_t offset[], SimdFloat *v, Targs... Fargs)
{
- gatherLoadTranspose<align>(base, offset, Fargs ...);
+ gatherLoadBySimdIntTranspose<align>(base, simdLoad(offset, SimdFInt32Tag()), v, Fargs ...);
}
template <int align>
eprAVER, mdebin, fcd, groups, &(ir->opts), ir->awh);
}
}
-
+ done_ebin(mdebin->ebin);
done_mdoutf(outf);
if (bPMETune)
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018, 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.
helper.runSecondMdrun();
}
+TEST_F(MdrunTerminationTest, CheckpointRestartWorksWithNoAppend)
+{
+ CommandLine mdrunCaller;
+ mdrunCaller.append("mdrun");
+ TerminationHelper helper(&fileManager_, &mdrunCaller, &runner_);
+
+ organizeMdpFile(&runner_);
+ EXPECT_EQ(0, runner_.callGrompp());
+
+ helper.runFirstMdrun(runner_.cptFileName_);
+ helper.runSecondMdrunWithNoAppend();
+}
+
} // namespace
} // namespace
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018, 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.
ASSERT_EQ(0, runner_->callMdrun(secondPart));
}
+void TerminationHelper::runSecondMdrunWithNoAppend()
+{
+ CommandLine secondPart(*mdrunCaller_);
+ secondPart.addOption("-cpi", runner_->cptFileName_);
+ secondPart.addOption("-nsteps", 2);
+ secondPart.append("-noappend");
+ ASSERT_EQ(0, runner_->callMdrun(secondPart));
+}
+
} // namespace
} // namespace
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016, by the GROMACS development team, led by
+ * Copyright (c) 2016,2018, 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.
void runFirstMdrun(const std::string &expectedCptFileName);
//! Check that the restart works, but don't do any more MD steps.
void runSecondMdrun();
+ //! Check that the restart works without appending, but don't do any more MD steps.
+ void runSecondMdrunWithNoAppend();
protected:
//! Object to help call mdrun
CommandLine *mdrunCaller_;