Merge "Merge release-5-0 into master"
authorMark Abraham <mark.j.abraham@gmail.com>
Thu, 25 Jun 2015 16:57:44 +0000 (18:57 +0200)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Thu, 25 Jun 2015 16:57:44 +0000 (18:57 +0200)
27 files changed:
CMakeLists.txt
README
docs/install-guide/index.rst
docs/manual/analyse.tex
docs/user-guide/environment-variables.rst
src/gromacs/commandline/cmdlineprogramcontext.cpp
src/gromacs/fft/fft5d.cpp
src/gromacs/fileio/confio.c
src/gromacs/fileio/trxio.c
src/gromacs/gmxana/gmx_analyze.c
src/gromacs/gmxana/gmx_density.c
src/gromacs/gmxana/gmx_gyrate.c
src/gromacs/gmxana/gmx_hbond.c
src/gromacs/gmxana/gmx_rmsdist.c
src/gromacs/gmxana/gmx_trjconv.c
src/gromacs/gmxana/gstat.h
src/gromacs/gmxlib/copyrite.cpp
src/gromacs/gmxlib/gmx_detect_hardware.cpp
src/gromacs/gmxpreprocess/gen_ad.c
src/gromacs/gmxpreprocess/pdb2gmx.c
src/gromacs/gmxpreprocess/readir.c
src/gromacs/gmxpreprocess/topio.c
src/gromacs/utility/exceptions.h
src/gromacs/utility/init.cpp
src/gromacs/utility/path.h
src/programs/mdrun/mdrun.cpp
src/programs/mdrun/runner.cpp

index bb66472c6bc8ffd3a5541e262585defedbf0a457..3adae520c3627065717fc87fff8d73e6715100ed 100644 (file)
@@ -57,6 +57,9 @@ include(gmxVersionInfo)
 if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND UNIX)
     set(CMAKE_INSTALL_PREFIX "/usr/local/gromacs" CACHE STRING "Installation prefix (installation will need write permissions here)" FORCE)
 endif()
+if("${CMAKE_INSTALL_PREFIX}" STREQUAL "${CMAKE_BINARY_DIR}")
+    message(FATAL_ERROR "GROMACS cannot be installed into the build tree, choose a different location for CMAKE_INSTALL_PREFIX")
+endif()
 
 include(gmxBuildTypeReference)
 include(gmxBuildTypeProfile)
diff --git a/README b/README
index 6ac5c0b75f911018c9972fe555e24ab6933348de..f2e3b302b1eea1f2c3fb66cc96ed30770096f544 100644 (file)
--- a/README
+++ b/README
@@ -65,6 +65,13 @@ To help us fund development, we humbly ask that you cite the GROMACS papers:
   Bioinformatics 29 (2013) pp. 845-54
   DOI: 10.1093/bioinformatics/btt055
 
+* Tackling Exascale Software Challenges in Molecular Dynamics Simulations
+  with GROMACS
+  Szilárd Páll, Mark J. Abraham, Carsten Kutzner, Berk Hess, Erik Lindahl
+  In S. Markidis & E. Laure (Eds.), Solving Software Challenges for Exascale,
+  8759 (2015) pp. 3–27
+  DOI: 10.1007/978-3-319-15976-8_1
+
 There are a lot of cool features we'd like to include in future versions,
 but our resources are limited. All kinds of donations are welcome, both in 
 form of code, hardware and funding! Industrial users who choose to pay
index e2fbbf48cf08a8290b98b69cf97682a968b01e27..90412d52000da9de0025e68a31188dfedb6bd0ee 100644 (file)
@@ -58,7 +58,7 @@ appropriate value instead of ``xxx`` :
 * ``-DGMX_BUILD_MDRUN_ONLY=on`` for `building only mdrun`_, e.g. for compute cluster back-end nodes
 * ``-DGMX_DOUBLE=on`` to run |Gromacs| in double precision (slower, and not normally useful)
 * ``-DCMAKE_PREFIX_PATH=xxx`` to add a non-standard location for CMake to `search for libraries, headers or programs`_
-* ``-DCMAKE_INSTALL_PREFIX=xxx`` to install |Gromacs| to a non-standard location (default ``/usr/local/gromacs``)
+* ``-DCMAKE_INSTALL_PREFIX=xxx`` to install |Gromacs| to a `non-standard location`_ (default ``/usr/local/gromacs``)
 * ``-DBUILD_SHARED_LIBS=off`` to turn off the building of shared libraries to help with `static linking`_
 * ``-DGMX_FFT_LIBRARY=xxx`` to select whether to use ``fftw``, ``mkl`` or ``fftpack`` libraries for `FFT support`_
 * ``-DCMAKE_BUILD_TYPE=Debug`` to build |Gromacs| in debug mode
@@ -400,6 +400,22 @@ after each pass that does not produce errors.
 You cannot attempt to change compilers after the initial run of
 ``cmake``. If you need to change, clean up, and start again.
 
+.. _non-standard location:
+
+Where to install GROMACS
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+A key thing to consider is the setting of
+``CMAKE_INSTALL_PREFIX``. You will need to be able to write to this
+directory in order to install GROMACS later, this directory cannot
+be the same as the build tree, and if you change your
+mind later, changing it in the cache triggers a full re-build,
+unfortunately. So if you do not have super-user privileges on your
+machine, then you will need to choose a sensible location within your
+home directory for your GROMACS installation. Even if you do have
+super-user privileges, you should use them only for the installation
+phase, and never for configuring, building, or running GROMACS!
+
 .. _cmake options:
 
 Using CMake command-line options
index d235e9c45491fc27a73f753b3453b2cde4365b85..42038f5c395206aa376902e8f8324ab1a20a1dd4 100644 (file)
@@ -724,7 +724,13 @@ R_g ~=~ \left({\frac{\sum_i \|{\bf r}_i\|^2 m_i}{\sum_i m_i}}\right)^{\half}
 \eeq
 where $m_i$ is the mass of atom $i$ and ${\bf r}_i$ the position of 
 atom $i$ with respect to the center of mass of the molecule. It is especially 
-useful to characterize polymer solutions and proteins.
+useful to characterize polymer solutions and proteins. The program will also
+provide the radius of gyration around the coordinate axis (or, optionally, principal axes)
+by only summing the radii components orthogonal to each axis, for instance
+\beq
+R_{g,x} ~=~ \left({\frac{\sum_i \left( r_{i,y}^2 + r_{i,z}^2 \right) m_i}{\sum_i m_i}}\right)^{\half}
+\label{eqn:rg}
+\eeq
 
 Sometimes it is interesting to plot the {\em distance} between two atoms,
 or the {\em minimum} distance between two groups of atoms
index 4581dff496399c717668081673097307ce604ed1..ba58e1781a2994ffdce05876ef62157df1630646 100644 (file)
@@ -212,10 +212,6 @@ Performance and Run Control
         when set to a floating-point value, overrides the default tolerance of
         1e-5 for force-field floating-point parameters.
 
-``GMX_MAX_MPI_THREADS``
-        sets the maximum number of MPI-threads that :ref:`gmx mdrun`
-        can use.
-
 ``GMX_MAXCONSTRWARN``
         if set to -1, :ref:`gmx mdrun` will
         not exit if it produces too many LINCS warnings.
index 66a93342aaf54258b174d36e9ca799c33e6d2e21..6563a4bf49a5603b64ce4f8c98b0b9241df73419 100644 (file)
@@ -256,7 +256,7 @@ std::string findInstallationPrefixPath(const std::string &binaryPath,
         // directory.
 #if (defined CMAKE_SOURCE_DIR && defined CMAKE_BINARY_DIR)
         std::string buildBinPath;
-#ifdef CMAKE_INTDIR
+#ifdef CMAKE_INTDIR /*In multi-configuration build systems the output subdirectory*/
         buildBinPath = Path::join(CMAKE_BINARY_DIR, "bin", CMAKE_INTDIR);
 #else
         buildBinPath = Path::join(CMAKE_BINARY_DIR, "bin");
index 93f518a85b680b9303b3a2ef236882474acebd7e..5cd3dfae97cc6cdab74c4c113b4f5e62e636a22a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2012,2013,2014,2015, 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.
@@ -452,7 +452,14 @@ fft5d_plan fft5d_plan_3d(int NG, int MG, int KG, MPI_Comm comm[2], int flags, t_
         fprintf(debug, "Running on %d threads\n", nthreads);
     }
 
-#ifdef GMX_FFT_FFTW3                                                            /*if not FFTW - then we don't do a 3d plan but instead use only 1D plans */
+#ifdef GMX_FFT_FFTW3
+    /* Don't add more stuff here! We have already had at least one bug because we are reimplementing
+     * the low-level FFT interface instead of using the Gromacs FFT module. If we need more
+     * generic functionality it is far better to extend the interface so we can use it for
+     * all FFT libraries instead of writing FFTW-specific code here.
+     */
+
+    /*if not FFTW - then we don't do a 3d plan but instead use only 1D plans */
     /* It is possible to use the 3d plan with OMP threads - but in that case it is not allowed to be called from
      * within a parallel region. For now deactivated. If it should be supported it has to made sure that
      * that the execute of the 3d plan is in a master/serial block (since it contains it own parallel region)
@@ -465,10 +472,9 @@ fft5d_plan fft5d_plan_3d(int NG, int MG, int KG, MPI_Comm comm[2], int flags, t_
         int inNG = NG, outMG = MG, outKG = KG;
 
         FFTW_LOCK;
-        if (!(flags&FFT5D_NOMEASURE))
-        {
-            fftwflags |= FFTW_MEASURE;
-        }
+
+        fftwflags |= (flags & FFT5D_NOMEASURE) ? FFTW_ESTIMATE : FFTW_MEASURE;
+
         if (flags&FFT5D_REALCOMPLEX)
         {
             if (!(flags&FFT5D_BACKWARD))        /*input pointer is not complex*/
index ef01aa45f771f253c55c0b94b7ee93e5ce333e86..c8a35d79cf6d19ab7eaf45eb710c8f5e39b792d4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -923,6 +923,7 @@ static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
                            rvec x[], rvec *v, matrix box)
 {
     char       name[6];
+    char       resname[6], oldresname[6];
     char       line[STRLEN+1], *ptr;
     char       buf[256];
     double     x1, y1, z1, x2, y2, z2;
@@ -953,6 +954,9 @@ static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
 
     bVel = FALSE;
 
+    resname[0]     = '\0';
+    oldresname[0]  = '\0';
+
     /* just pray the arrays are big enough */
     for (i = 0; (i < natoms); i++)
     {
@@ -1000,9 +1004,9 @@ static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
         memcpy(name, line, 5);
         name[5] = '\0';
         sscanf(name, "%d", &resnr);
-        memcpy(name, line+5, 5);
-        name[5] = '\0';
-        if (resnr != oldres)
+        sscanf(line+5, "%5s", resname);
+
+        if (resnr != oldres || strncmp(resname, oldresname, sizeof(resname)))
         {
             oldres = resnr;
             newres++;
@@ -1012,7 +1016,7 @@ static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
                           infile, natoms);
             }
             atoms->atom[i].resind = newres;
-            t_atoms_set_resinfo(atoms, i, symtab, name, resnr, ' ', 0, ' ');
+            t_atoms_set_resinfo(atoms, i, symtab, resname, resnr, ' ', 0, ' ');
         }
         else
         {
@@ -1023,6 +1027,9 @@ static gmx_bool get_w_conf(FILE *in, const char *infile, char *title,
         memcpy(name, line+10, 5);
         atoms->atomname[i] = put_symtab(symtab, name);
 
+        /* Copy resname to oldresname after we are done with the sanity check above */
+        strncpy(oldresname, resname, sizeof(oldresname));
+
         /* eventueel controle atomnumber met i+1 */
 
         /* coordinates (start after residue data) */
index 8e70f73716fc8a234b7446db8e5b2a2b27d31de4..084b9325c39bca352f479da88a805a0752e0f8f6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -78,7 +78,7 @@ struct t_trxstatus
     int                     nxframe;
     t_fileio               *fio;
     tng_trajectory_t        tng;
-    int                     NATOMS;
+    int                     natoms;
     double                  DT, BOX[3];
     gmx_bool                bReadBox;
     char                   *persistent_line; /* Persistent line for reading g96 trajectories */
@@ -238,7 +238,7 @@ float trx_get_time_of_final_frame(t_trxstatus *status)
         lasttime =
             xdr_xtc_get_last_frame_time(gmx_fio_getfp(stfio),
                                         gmx_fio_getxdr(stfio),
-                                        status->xframe->natoms, &bOK);
+                                        status->natoms, &bOK);
         if (!bOK)
         {
             gmx_fatal(FARGS, "Error reading last frame. Maybe seek not supported." );
@@ -1055,6 +1055,11 @@ int read_first_frame(const output_env_t oenv, t_trxstatus **status,
     }
     fr->t0 = fr->time;
 
+    /* We need the number of atoms for random-access XTC searching, even when
+     * we don't have access to the actual frame data.
+     */
+    (*status)->natoms = fr->natoms;
+
     return (fr->natoms > 0);
 }
 
index c4096954a20917b13641207acb32afd31eadfc9d..93ccf37dd635fd35a6f748091d4c9dd298542628 100644 (file)
@@ -713,8 +713,7 @@ static void estimate_error(const char *eefile, int nb_min, int resol, int n,
 }
 
 static void luzar_correl(int nn, real *time, int nset, real **val, real temp,
-                         gmx_bool bError, real fit_start, real smooth_tail_start,
-                         const output_env_t oenv)
+                         gmx_bool bError, real fit_start)
 {
     const real tol = 1e-8;
     real      *kt;
@@ -742,13 +741,13 @@ static void luzar_correl(int nn, real *time, int nset, real **val, real temp,
             fprintf(debug, "RMS difference in derivatives is %g\n", sqrt(d2/nn));
         }
         analyse_corr(nn, time, val[0], val[2], kt, NULL, NULL, NULL, fit_start,
-                     temp, smooth_tail_start, oenv);
+                     temp);
         sfree(kt);
     }
     else if (nset == 6)
     {
         analyse_corr(nn, time, val[0], val[2], val[4],
-                     val[1], val[3], val[5], fit_start, temp, smooth_tail_start, oenv);
+                     val[1], val[3], val[5], fit_start, temp);
     }
     else
     {
@@ -1173,7 +1172,7 @@ int gmx_analyze(int argc, char *argv[])
     static gmx_bool    bEESEF     = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE;
     static gmx_bool    bIntegrate = FALSE, bRegression = FALSE, bLuzar = FALSE, bLuzarError = FALSE;
     static int         nsets_in   = 1, d = 1, nb_min = 4, resol = 10, nBalExp = 4, nFitPoints = 100;
-    static real        temp       = 298.15, fit_start = 1, fit_end = 60, smooth_tail_start = -1, balTime = 0.2, diffusion = 5e-5, rcut = 0.35;
+    static real        temp       = 298.15, fit_start = 1, fit_end = 60, balTime = 0.2, diffusion = 5e-5, rcut = 0.35;
 
     /* must correspond to enum avbar* declared at beginning of file */
     static const char *avbar_opt[avbarNR+1] = {
@@ -1216,8 +1215,6 @@ int gmx_analyze(int argc, char *argv[])
           "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" },
         { "-fitend", FALSE, etREAL, {&fit_end},
           "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with [TT]-gem[tt]" },
-        { "-smooth", FALSE, etREAL, {&smooth_tail_start},
-          "If this value is >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: [MATH]y = A [EXP]-x/[GRK]tau[grk][exp][math]" },
         { "-nbmin",   FALSE, etINT, {&nb_min},
           "HIDDENMinimum number of blocks for block averaging" },
         { "-resol", FALSE, etINT, {&resol},
@@ -1488,7 +1485,7 @@ int gmx_analyze(int argc, char *argv[])
 
     if (bLuzar)
     {
-        luzar_correl(n, t, nset, val, temp, bXYdy, fit_start, smooth_tail_start, oenv);
+        luzar_correl(n, t, nset, val, temp, bXYdy, fit_start);
     }
 
     view_all(oenv, NFILE, fnm);
index fb452e963ffabea20eee41ea549a7f9c4db909c9..954e27cac8f4d2415fe2770f743b6345a1bd2e47 100644 (file)
@@ -158,7 +158,7 @@ void center_coords(t_atoms *atoms, atom_id *index_center, int ncenter,
         com[m] /= tmass;
     }
     calc_box_center(ecenterDEF, box, box_center);
-    rvec_sub(box_center, com, shift);
+    rvec_sub(com, box_center, shift);
 
     /* Important - while the center was calculated based on a group, we should move all atoms */
     for (i = 0; (i < atoms->nr); i++)
index 6c70944e368e1b0352d3a1fc2914575efb1d389a..7d02832330e89f3b5134636b74e31519318b313c 100644 (file)
@@ -173,12 +173,16 @@ void calc_gyro_z(rvec x[], matrix box,
     fprintf(out, "\n");
 }
 
+
 int gmx_gyrate(int argc, char *argv[])
 {
     const char     *desc[] = {
         "[THISMODULE] computes the radius of gyration of a molecule",
         "and the radii of gyration about the [IT]x[it]-, [IT]y[it]- and [IT]z[it]-axes,",
         "as a function of time. The atoms are explicitly mass weighted.[PAR]",
+        "The axis components corresponds to the mass-weighted root-mean-square",
+        "of the radii components orthogonal to each axis, for example:[PAR]",
+        "Rg(x) = sqrt((sum_i m_i (R_i(y)^2 + R_i(z)^2))/(sum_i m_i)).[PAR]",
         "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
         "for multiple molecules by splitting the analysis group in equally",
         "sized parts.[PAR]",
@@ -217,7 +221,7 @@ int gmx_gyrate(int argc, char *argv[])
     atom_id        *index;
     output_env_t    oenv;
     gmx_rmpbc_t     gpbc   = NULL;
-    const char     *leg[]  = { "Rg", "RgX", "RgY", "RgZ" };
+    const char     *leg[]  = { "Rg", "Rg\\sX\\N", "Rg\\sY\\N", "Rg\\sZ\\N" };
     const char     *legI[] = { "Itot", "I1", "I2", "I3" };
 #define NLEG asize(leg)
     t_filenm        fnm[] = {
@@ -281,17 +285,17 @@ int gmx_gyrate(int argc, char *argv[])
     if (bQ)
     {
         out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
-                       "Radius of Charge", "Time (ps)", "Rg (nm)", oenv);
+                       "Radius of Charge (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
     }
     else if (bMOI)
     {
         out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
-                       "Moments of inertia", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv);
+                       "Moments of inertia (total and around axes)", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv);
     }
     else
     {
         out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
-                       "Radius of gyration", "Time (ps)", "Rg (nm)", oenv);
+                       "Radius of gyration (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
     }
     if (bMOI)
     {
index 931824997119f833311f3dd071f9a47ec9a257cc..73b17d1a05180fd8f32226f48718799e035c281c 100644 (file)
@@ -2389,39 +2389,9 @@ static real compute_weighted_rates(int n, real t[], real ct[], real nt[],
     return chi2;
 }
 
-static void smooth_tail(int n, real t[], real c[], real sigma_c[], real start,
-                        const output_env_t oenv)
-{
-    FILE  *fp;
-    real   e_1;
-    double fitparm[4];
-    int    i;
-
-    e_1 = exp(-1);
-    for (i = 0; (i < n); i++)
-    {
-        if (c[i] < e_1)
-        {
-            break;
-        }
-    }
-    if (i < n)
-    {
-        fitparm[0] = t[i];
-    }
-    else
-    {
-        fitparm[0] = 10;
-    }
-    fitparm[1] = 0.95;
-    do_lmfit(n, c, sigma_c, 0, t, start, t[n-1], oenv, bDebugMode(),
-             effnEXP2, fitparm, 0, NULL);
-}
-
 void analyse_corr(int n, real t[], real ct[], real nt[], real kt[],
                   real sigma_ct[], real sigma_nt[], real sigma_kt[],
-                  real fit_start, real temp, real smooth_tail_start,
-                  const output_env_t oenv)
+                  real fit_start, real temp)
 {
     int        i0, i;
     real       k = 1, kp = 1, kow = 1;
@@ -2429,12 +2399,6 @@ void analyse_corr(int n, real t[], real ct[], real nt[], real kt[],
     double     tmp, sn2 = 0, sc2 = 0, sk2 = 0, scn = 0, sck = 0, snk = 0;
     gmx_bool   bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
 
-    if (smooth_tail_start >= 0)
-    {
-        smooth_tail(n, t, ct, sigma_ct, smooth_tail_start, oenv);
-        smooth_tail(n, t, nt, sigma_nt, smooth_tail_start, oenv);
-        smooth_tail(n, t, kt, sigma_kt, smooth_tail_start, oenv);
-    }
     for (i0 = 0; (i0 < n-2) && ((t[i0]-t[0]) < fit_start); i0++)
     {
         ;
@@ -2593,7 +2557,7 @@ static void normalizeACF(real *ct, real *gt, int nhb, int len)
  */
 static void do_hbac(const char *fn, t_hbdata *hb,
                     int nDump, gmx_bool bMerge, gmx_bool bContact, real fit_start,
-                    real temp, gmx_bool R2, real smooth_tail_start, const output_env_t oenv,
+                    real temp, gmx_bool R2, const output_env_t oenv,
                     const char *gemType, int nThreads,
                     const int NN, const gmx_bool bBallistic, const gmx_bool bGemFit)
 {
@@ -3290,7 +3254,7 @@ static void do_hbac(const char *fn, t_hbdata *hb,
             xvgrclose(fp);
 
             analyse_corr(nn, hb->time, ct, ght, kt, NULL, NULL, NULL,
-                         fit_start, temp, smooth_tail_start, oenv);
+                         fit_start, temp);
 
             do_view(oenv, fn, NULL);
             sfree(rhbex);
@@ -3610,7 +3574,7 @@ int gmx_hbond(int argc, char *argv[])
     };
 
     static real        acut     = 30, abin = 1, rcut = 0.35, r2cut = 0, rbin = 0.005, rshell = -1;
-    static real        maxnhb   = 0, fit_start = 1, fit_end = 60, temp = 298.15, smooth_tail_start = -1, D = -1;
+    static real        maxnhb   = 0, fit_start = 1, fit_end = 60, temp = 298.15, D = -1;
     static gmx_bool    bNitAcc  = TRUE, bDA = TRUE, bMerge = TRUE;
     static int         nDump    = 0, nFitPoints = 100;
     static int         nThreads = 0, nBalExp = 4;
@@ -3646,8 +3610,6 @@ int gmx_hbond(int argc, char *argv[])
           "Time (ps) to which to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation (only with [TT]-gemfit[tt])" },
         { "-temp",  FALSE, etREAL, {&temp},
           "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
-        { "-smooth", FALSE, etREAL, {&smooth_tail_start},
-          "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/[GRK]tau[grk])" },
         { "-dump",  FALSE, etINT, {&nDump},
           "Dump the first N hydrogen bond ACFs in a single [REF].xvg[ref] file for debugging" },
         { "-max_hb", FALSE, etREAL, {&maxnhb},
@@ -4645,7 +4607,7 @@ int gmx_hbond(int argc, char *argv[])
             }
             gemstring = gmx_strdup(gemType[hb->per->gemtype]);
             do_hbac(opt2fn("-ac", NFILE, fnm), hb, nDump,
-                    bMerge, bContact, fit_start, temp, r2cut > 0, smooth_tail_start, oenv,
+                    bMerge, bContact, fit_start, temp, r2cut > 0, oenv,
                     gemstring, nThreads, NN, bBallistic, bGemFit);
         }
         if (opt2bSet("-life", NFILE, fnm))
index 6b0a5014e55f246a2f9b60500a78ccb22cae2add..ea2fff5a00d969f13a6fc6289498138c19552b2c 100644 (file)
@@ -802,7 +802,7 @@ int gmx_rmsdist(int argc, char *argv[])
 
     close_trj(status);
 
-    calc_rms(isize, teller, dtot, dtot2, mean, &meanmax, rms, &rmsmax, rmsc, &rmscmax);
+    calc_rms(isize, teller, dtot, dtot2, rms, &rmsmax, rmsc, &rmscmax, mean, &meanmax);
     fprintf(stderr, "rmsmax = %g, rmscmax = %g\n", rmsmax, rmscmax);
 
     if (bNMR)
index 1bd02fe2d91e8b6a5671b52767d82394e51ece8c..26ba84944cdd64e9027bec5522a70f9284bff803 100644 (file)
@@ -716,7 +716,8 @@ int gmx_trjconv(int argc, char *argv[])
         "trajectories must be concatenated without having double frames.[PAR]",
 
         "Option [TT]-dump[tt] can be used to extract a frame at or near",
-        "one specific time from your trajectory.[PAR]",
+        "one specific time from your trajectory, but only works reliably",
+        "if the time interval between frames is uniform.[PAR]",
 
         "Option [TT]-drop[tt] reads an [REF].xvg[ref] file with times and values.",
         "When options [TT]-dropunder[tt] and/or [TT]-dropover[tt] are set,",
index ac08579eb501cb5640387cc00a67a3b0fba0a0f3..74f293f5f73fdc37253c7294d003fbc6c0e27fbd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -253,8 +253,7 @@ void print_one (const output_env_t oenv, const char *base,
 /* Routines from g_hbond */
 void analyse_corr(int n, real t[], real ct[], real nt[], real kt[],
                   real sigma_ct[], real sigma_nt[], real sigma_kt[],
-                  real fit_start, real temp, real smooth_tail_start,
-                  const output_env_t oenv);
+                  real fit_start, real temp);
 
 void compute_derivative(int nn, real x[], real y[], real dydx[]);
 
index 642f56c84ca600d0a4bcf8e9d72c7c033d3d6aef..b22124377dc68ce31bacdfd5001f4be14a2ab8ca 100644 (file)
@@ -595,7 +595,17 @@ void please_cite(FILE *fp, const char *key)
           "N. Goga and A. J. Rzepiela and A. H. de Vries and S. J. Marrink and H. J. C. Berendsen",
           "Efficient Algorithms for Langevin and DPD Dynamics",
           "J. Chem. Theory Comput.",
-          8, 2012, "3637--3649"}
+          8, 2012, "3637--3649"},
+        { "Pronk2013",
+          "S. Pronk, S. Páll, R. Schulz, P. Larsson, P. Bjelkmar, R. Apostolov, M. R. Shirts, J. C. Smith, P. M. Kasson, D. van der Spoel, B. Hess, and E. Lindahl",
+          "GROMACS 4.5: a high-throughput and highly parallel open source molecular simulation toolkit",
+          "Bioinformatics",
+          29, 2013, "845-54"},
+        { "Pall2015",
+          "S. Páll, M. J. Abraham, C. Kutzner, B. Hess, E. Lindahl",
+          "Tackling Exascale Software Challenges in Molecular Dynamics Simulations with GROMACS",
+          "In S. Markidis & E. Laure (Eds.), Solving Software Challenges for Exascale",
+          8759, 2015, "3–27" }
     };
 #define NSTR (int)asize(citedb)
 
index 711e83e6742579a6cb11d41b3c01e8fff8c89f38..96ea3c3db17b10c0d3a6d24fe914a94e730d061b 100644 (file)
@@ -279,7 +279,7 @@ void gmx_check_hw_runconf_consistency(FILE                *fplog,
 {
     int      npppn;
     char     th_or_proc[STRLEN], th_or_proc_plural[STRLEN], pernode[STRLEN];
-    gmx_bool btMPI, bMPI, bMaxMpiThreadsSet, bNthreadsAuto, bEmulateGPU;
+    gmx_bool btMPI, bMPI, bNthreadsAuto, bEmulateGPU;
 
     assert(hwinfo);
     assert(cr);
@@ -310,7 +310,6 @@ void gmx_check_hw_runconf_consistency(FILE                *fplog,
     /* GPU emulation detection is done later, but we need here as well
      * -- uncool, but there's no elegant workaround */
     bEmulateGPU       = (getenv("GMX_EMULATE_GPU") != NULL);
-    bMaxMpiThreadsSet = (getenv("GMX_MAX_MPI_THREADS") != NULL);
 
     if (hwinfo->gpu_info.n_dev_compatible > 0)
     {
@@ -381,10 +380,10 @@ void gmx_check_hw_runconf_consistency(FILE                *fplog,
                    could automatically start. */
                 gmx_fatal(FARGS,
                           "%d GPU%s provided, but only %d PP thread-MPI thread%s coud be started.\n"
-                          "%s requires one PP tread-MPI thread per GPU; use fewer GPUs%s.",
+                          "%s requires one PP tread-MPI thread per GPU; use fewer GPUs.",
                           ngpu_use, gpu_use_plural,
                           npppn, th_or_proc_plural,
-                          ShortProgram(), bMaxMpiThreadsSet ? "\nor allow more threads to be used" : "");
+                          ShortProgram());
             }
 
             if (!hw_opt->gpu_opt.bUserSet && npppn < ngpu_comp)
@@ -393,12 +392,11 @@ void gmx_check_hw_runconf_consistency(FILE                *fplog,
                    limited the number GPUs used. */
                 md_print_warn(cr, fplog,
                               "NOTE: %d GPU%s were detected, but only %d PP thread-MPI thread%s can be started.\n"
-                              "      %s can use one GPU per PP tread-MPI thread, so only %d GPU%s will be used.%s\n",
+                              "      %s can use one GPU per PP tread-MPI thread, so only %d GPU%s will be used.\n",
                               ngpu_comp, gpu_comp_plural,
                               npppn, th_or_proc_plural,
                               ShortProgram(), npppn,
-                              npppn > 1 ? "s" : "",
-                              bMaxMpiThreadsSet ? "\n      Also, you can allow more threads to be used by increasing GMX_MAX_MPI_THREADS" : "");
+                              npppn > 1 ? "s" : "");
             }
         }
 
index 61dc0f9cd71054b75324978d805b6e2249525407..1b7a0b9c5e3f68f57527db29decb909ac2973afd 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -1038,102 +1038,105 @@ void gen_pad(t_nextnb *nnb, t_atoms *atoms, t_restp rtp[],
         }
     }
 
-    /* The above approach is great in that we double-check that e.g. an angle
-     * really corresponds to three atoms connected by bonds, but this is not
-     * generally true. Go through the angle and dihedral hackblocks to add
-     * entries that we have not yet marked as matched when going through bonds.
-     */
-    for (i = 0; i < atoms->nres; i++)
+    if (hb)
     {
-        /* Add remaining angles from hackblock */
-        hbang = &hb[i].rb[ebtsANGLES];
-        for (j = 0; j < hbang->nb; j++)
+        /* The above approach is great in that we double-check that e.g. an angle
+         * really corresponds to three atoms connected by bonds, but this is not
+         * generally true. Go through the angle and dihedral hackblocks to add
+         * entries that we have not yet marked as matched when going through bonds.
+         */
+        for (i = 0; i < atoms->nres; i++)
         {
-            if (hbang->b[j].match == TRUE)
-            {
-                /* We already used this entry, continue to the next */
-                continue;
-            }
-            /* Hm - entry not used, let's see if we can find all atoms */
-            if (nang == maxang)
-            {
-                maxang += ninc;
-                srenew(ang, maxang);
-            }
-            bFound = TRUE;
-            for (k = 0; k < 3 && bFound; k++)
+            /* Add remaining angles from hackblock */
+            hbang = &hb[i].rb[ebtsANGLES];
+            for (j = 0; j < hbang->nb; j++)
             {
-                p   = hbang->b[j].a[k];
-                res = i;
-                if (p[0] == '-')
+                if (hbang->b[j].match == TRUE)
                 {
-                    p++;
-                    res--;
+                    /* We already used this entry, continue to the next */
+                    continue;
                 }
-                else if (p[0] == '+')
+                /* Hm - entry not used, let's see if we can find all atoms */
+                if (nang == maxang)
                 {
-                    p++;
-                    res++;
+                    maxang += ninc;
+                    srenew(ang, maxang);
                 }
-                ang[nang].a[k] = search_res_atom(p, res, atoms, "angle", TRUE);
-                bFound         = (ang[nang].a[k] != NO_ATID);
-            }
-            ang[nang].C0 = NOTSET;
-            ang[nang].C1 = NOTSET;
+                bFound = TRUE;
+                for (k = 0; k < 3 && bFound; k++)
+                {
+                    p   = hbang->b[j].a[k];
+                    res = i;
+                    if (p[0] == '-')
+                    {
+                        p++;
+                        res--;
+                    }
+                    else if (p[0] == '+')
+                    {
+                        p++;
+                        res++;
+                    }
+                    ang[nang].a[k] = search_res_atom(p, res, atoms, "angle", TRUE);
+                    bFound         = (ang[nang].a[k] != NO_ATID);
+                }
+                ang[nang].C0 = NOTSET;
+                ang[nang].C1 = NOTSET;
 
-            if (bFound)
-            {
-                set_p_string(&(ang[nang]), hbang->b[j].s);
-                hbang->b[j].match = TRUE;
-                /* Incrementing nang means we save this angle */
-                nang++;
+                if (bFound)
+                {
+                    set_p_string(&(ang[nang]), hbang->b[j].s);
+                    hbang->b[j].match = TRUE;
+                    /* Incrementing nang means we save this angle */
+                    nang++;
+                }
             }
-        }
 
-        /* Add remaining dihedrals from hackblock */
-        hbdih = &hb[i].rb[ebtsPDIHS];
-        for (j = 0; j < hbdih->nb; j++)
-        {
-            if (hbdih->b[j].match == TRUE)
-            {
-                /* We already used this entry, continue to the next */
-                continue;
-            }
-            /* Hm - entry not used, let's see if we can find all atoms */
-            if (ndih == maxdih)
-            {
-                maxdih += ninc;
-                srenew(dih, maxdih);
-            }
-            bFound = TRUE;
-            for (k = 0; k < 4 && bFound; k++)
+            /* Add remaining dihedrals from hackblock */
+            hbdih = &hb[i].rb[ebtsPDIHS];
+            for (j = 0; j < hbdih->nb; j++)
             {
-                p   = hbdih->b[j].a[k];
-                res = i;
-                if (p[0] == '-')
+                if (hbdih->b[j].match == TRUE)
                 {
-                    p++;
-                    res--;
+                    /* We already used this entry, continue to the next */
+                    continue;
                 }
-                else if (p[0] == '+')
+                /* Hm - entry not used, let's see if we can find all atoms */
+                if (ndih == maxdih)
                 {
-                    p++;
-                    res++;
+                    maxdih += ninc;
+                    srenew(dih, maxdih);
+                }
+                bFound = TRUE;
+                for (k = 0; k < 4 && bFound; k++)
+                {
+                    p   = hbdih->b[j].a[k];
+                    res = i;
+                    if (p[0] == '-')
+                    {
+                        p++;
+                        res--;
+                    }
+                    else if (p[0] == '+')
+                    {
+                        p++;
+                        res++;
+                    }
+                    dih[ndih].a[k] = search_res_atom(p, res, atoms, "dihedral", TRUE);
+                    bFound         = (dih[ndih].a[k] != NO_ATID);
+                }
+                for (m = 0; m < MAXFORCEPARAM; m++)
+                {
+                    dih[ndih].c[m] = NOTSET;
                 }
-                dih[ndih].a[k] = search_res_atom(p, res, atoms, "dihedral", TRUE);
-                bFound         = (dih[ndih].a[k] != NO_ATID);
-            }
-            for (m = 0; m < MAXFORCEPARAM; m++)
-            {
-                dih[ndih].c[m] = NOTSET;
-            }
 
-            if (bFound)
-            {
-                set_p_string(&(dih[ndih]), hbdih->b[j].s);
-                hbdih->b[j].match = TRUE;
-                /* Incrementing ndih means we save this dihedral */
-                ndih++;
+                if (bFound)
+                {
+                    set_p_string(&(dih[ndih]), hbdih->b[j].s);
+                    hbdih->b[j].match = TRUE;
+                    /* Incrementing ndih means we save this dihedral */
+                    ndih++;
+                }
             }
         }
     }
index 95215c89f6653778caa8fdd8d0ef666a3bb0a059..242aaf65e08ec587661d8acc684dcaaccd5348cb 100644 (file)
 #include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/smalloc.h"
 
+#define RTP_MAXCHAR 5
 typedef struct {
-    char gmx[6];
-    char main[6];
-    char nter[6];
-    char cter[6];
-    char bter[6];
+    char gmx[RTP_MAXCHAR+2];
+    char main[RTP_MAXCHAR+2];
+    char nter[RTP_MAXCHAR+2];
+    char cter[RTP_MAXCHAR+2];
+    char bter[RTP_MAXCHAR+2];
 } rtprename_t;
 
 
@@ -221,8 +222,25 @@ static void read_rtprename(const char *fname, FILE *fp,
     while (get_a_line(fp, line, STRLEN))
     {
         srenew(rr, n+1);
-        nc = sscanf(line, "%s %s %s %s %s %s",
-                    rr[n].gmx, rr[n].main, rr[n].nter, rr[n].cter, rr[n].bter, buf);
+        /* line is NULL-terminated and length<STRLEN, so final arg cannot overflow.
+         * For other args, we read up to 6 chars (so we can detect if the length is > 5).
+         * Note that the buffer length has been increased to 7 to allow this,
+         * so we just need to make sure the strings have zero-length initially.
+         */
+        rr[n].gmx[0]  = '\0';
+        rr[n].main[0] = '\0';
+        rr[n].nter[0] = '\0';
+        rr[n].cter[0] = '\0';
+        rr[n].bter[0] = '\0';
+        nc            = sscanf(line, "%6s %6s %6s %6s %6s %s",
+                               rr[n].gmx, rr[n].main, rr[n].nter, rr[n].cter, rr[n].bter, buf);
+        if (strlen(rr[n].gmx) > RTP_MAXCHAR || strlen(rr[n].main) > RTP_MAXCHAR ||
+            strlen(rr[n].nter) > RTP_MAXCHAR || strlen(rr[n].cter) > RTP_MAXCHAR || strlen(rr[n].bter) > RTP_MAXCHAR)
+        {
+            gmx_fatal(FARGS, "Residue renaming database '%s' has strings longer than %d chars in first 5 columns:\n%s",
+                      fname, RTP_MAXCHAR, line);
+        }
+
         if (ncol == 0)
         {
             if (nc != 2 && nc != 5)
index 3f3e233de560482151e53e59a97482c7062fec34..cb01302bd2fe5a839f1e64954813785344e0de79 100644 (file)
@@ -1080,6 +1080,14 @@ void check_ir(const char *mdparin, t_inputrec *ir, t_gromppopts *opts,
         ir->epsilon_r  = 1.0;
     }
 
+    if (ir->epsilon_r == 0)
+    {
+        sprintf(err_buf,
+                "It is pointless to use long-range or Generalized Born electrostatics with infinite relative permittivity."
+                "Since you are effectively turning of electrostatics, a plain cutoff will be much faster.");
+        CHECK(EEL_FULL(ir->coulombtype) || ir->implicit_solvent == eisGBSA);
+    }
+
     if (getenv("GMX_DO_GALACTIC_DYNAMICS") == NULL)
     {
         sprintf(err_buf, "epsilon-r must be >= 0 instead of %g\n", ir->epsilon_r);
index e09518e8b270c2fc12fb6c2f1d9a3aa7bfb138b6..7a3fe0033fdecc1dc69778ace3dfc76bc7daf30b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -889,6 +889,10 @@ static char **read_topol(const char *infile, const char *outfile,
                             push_bond(d, plist, mi0->plist, &(mi0->atoms), atype, pline, FALSE,
                                       bGenPairs, *fudgeQQ, bZero, &bWarn_copy_A_B, wi);
                             break;
+                        case d_pairs_nb:
+                            push_bond(d, plist, mi0->plist, &(mi0->atoms), atype, pline, FALSE,
+                                      FALSE, 1.0, bZero, &bWarn_copy_A_B, wi);
+                            break;
 
                         case d_vsites2:
                         case d_vsites3:
index 36fdaceb7d567a6916087b2564887ef9029d6222..40d723b8f516190447e1de215306c071d46d9a0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015, 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.
index a33ada5df0976bde44d282ac8460cb32ae6fc074..c8d3f0f4963e135a8e92424879a874933405c4a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, 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.
@@ -46,6 +46,7 @@
 #include "config.h"
 
 #include "gromacs/utility/basedefinitions.h"
+#include "gromacs/utility/fatalerror.h"
 #include "gromacs/utility/gmxassert.h"
 #ifdef GMX_LIB_MPI
 #include "gromacs/utility/gmxmpi.h"
@@ -81,9 +82,38 @@ void init(int *argc, char ***argv)
     else
     {
 #ifdef GMX_FAHCORE
-        (void) fah_MPI_Init(argc, argv);
+        fah_MPI_Init(argc, argv);
 #else
-        (void) MPI_Init(argc, argv);
+#    ifdef GMX_OPENMP
+        /* Formally we need to use MPI_Init_thread and ask for MPI_THREAD_FUNNELED
+         * level of thread support when using OpenMP. However, in practice we
+         * have never seen any problems with just using MPI_Init(), and some MPI
+         * versions that only return MPI_THREAD_SINGLE as their support level
+         * still return an OK initialization code when we request MPI_THREAD_FUNNELED.
+         *
+         * To avoid requiring users to recompile and install new libraries for something
+         * that probably isn't a problem, we don't make a fuss about it (no warning)
+         * if MPI_Init_thread() returns ok. If it does not return OK we
+         * call a second init call without thread support, but since the library
+         * apparently tried to prevent this we do issue a warning in this case.
+         *
+         * support, and if that doesn't work we simply use the simple MPI_Init().
+         * Note that MPICH does not allow us to call MPI_Query_thread() before
+         * we have initialized the library, and calling MPI_Init twice could
+         * be a bit fragile. However, some implementations also advice against
+         * doing anything else after calling MPI_Finalize, so at the end of the
+         * day we'll have to cross our fingers...
+         */
+        int provided, rc;
+        rc = MPI_Init_thread(argc, argv, MPI_THREAD_FUNNELED, &provided);
+        if (rc != 0 && provided < MPI_THREAD_FUNNELED)
+        {
+            gmx_warning("GROMACS was compiled with OpenMP support, but there is no thread support in the MPI library. Keep your fingers crossed.");
+            MPI_Init(argc, argv);
+        }
+#    else
+        MPI_Init(argc, argv);
+#    endif
 #endif
     }
     // Bump the counter to record this initialization event
index 4fd6bf97acdec12f96821e0cc97c0ad42624796e..ef2b3e884879ca7c7ecbc8ea4f282037379b8911 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2011,2012,2013,2014,2015, 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.
index b5fd731267dbafca004db2b71abaf79d924e48e6..00a8be18259e1cddf818003b6ca1f90e31165579 100644 (file)
@@ -486,14 +486,14 @@ int gmx_mdrun(int argc, char *argv[])
         gmx_fatal(FARGS, "Replica exchange number of exchanges needs to be positive");
     }
 
-    if (nmultisim > 1)
+    if (nmultisim >= 1)
     {
 #ifndef GMX_THREAD_MPI
         gmx_bool bParFn = (multidir == NULL);
         init_multisystem(cr, nmultisim, multidir, NFILE, fnm, bParFn);
 #else
-        gmx_fatal(FARGS, "mdrun -multi is not supported with the thread library. "
-                  "Please compile GROMACS with MPI support");
+        gmx_fatal(FARGS, "mdrun -multi or -multidir are not supported with the thread-MPI library. "
+                  "Please compile GROMACS with a proper external MPI library.");
 #endif
     }
 
index d88c5cd656b7742142896f0247cb1082e4455064..ff1ac26cc708c10be23825887f86c63ee972c27a 100644 (file)
@@ -668,6 +668,8 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
     if (fplog != NULL)
     {
         /* Print references after all software/hardware printing */
+        please_cite(fplog, "Pall2015");
+        please_cite(fplog, "Pronk2013");
         please_cite(fplog, "Hess2008b");
         please_cite(fplog, "Spoel2005a");
         please_cite(fplog, "Lindahl2001a");