Merge branch release-2016
authorMark Abraham <mark.j.abraham@gmail.com>
Tue, 14 Mar 2017 14:40:05 +0000 (15:40 +0100)
committerMark Abraham <mark.j.abraham@gmail.com>
Tue, 14 Mar 2017 14:40:05 +0000 (15:40 +0100)
Change-Id: I14f7cd22447b8a76110d8b41487666eb49835835

30 files changed:
cmake/gmxManageSimd.cmake
docs/dev-manual/jenkins.rst
docs/install-guide/index.rst
docs/user-guide/mdrun-performance.rst
src/contrib/fftw/CMakeLists.txt
src/gromacs/gmxana/gmx_do_dssp.cpp
src/gromacs/gmxana/gmx_mindist.cpp
src/gromacs/gmxana/gmx_traj.cpp
src/gromacs/gmxana/gmx_trjconv.cpp
src/gromacs/gmxana/gmx_tune_pme.cpp
src/gromacs/gmxpreprocess/readir.cpp
src/gromacs/gmxpreprocess/solvate.cpp
src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_box_Works.xml [new file with mode: 0644]
src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_Works.xml [new file with mode: 0644]
src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_p_Works.xml [new file with mode: 0644]
src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_shell_Works.xml [new file with mode: 0644]
src/gromacs/gmxpreprocess/tests/solvate.cpp
src/gromacs/listed-forces/pairs.cpp
src/gromacs/mdlib/sim_util.cpp
src/gromacs/simd/impl_ibm_vsx/impl_ibm_vsx_general.h
src/gromacs/simd/impl_ibm_vsx/impl_ibm_vsx_simd4_float.h
src/gromacs/simd/impl_ibm_vsx/impl_ibm_vsx_simd_double.h
src/gromacs/simd/impl_ibm_vsx/impl_ibm_vsx_simd_float.h
src/gromacs/simd/impl_ibm_vsx/impl_ibm_vsx_util_float.h
src/gromacs/simd/tests/simd_math.cpp
src/gromacs/utility/binaryinformation.cpp
src/programs/mdrun/md.cpp
src/testutils/CMakeLists.txt
src/testutils/conftest.cpp [new file with mode: 0644]
src/testutils/conftest.h [new file with mode: 0644]

index b862a71cd61344571c3dc699903248cc19164bb6..85249369cf682805ce64ed2faec38d8b87a76937 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016,2017, 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.
@@ -72,6 +72,11 @@ macro(prepare_power_vsx_toolchain TOOLCHAIN_C_FLAGS_VARIABLE TOOLCHAIN_CXX_FLAGS
             message(FATAL_ERROR "Using VSX SIMD in double precision with GCC requires GCC-4.9 or later.")
         endif()
     endif()
+    if(${CMAKE_CXX_COMPILER_ID} MATCHES "XL" OR ${CMAKE_C_COMPILER_ID} MATCHES "XL")
+        if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "13.1.5" OR CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.5")
+            message(FATAL_ERROR "Using VSX SIMD requires XL compiler version 13.1.5 or later.")
+        endif()
+    endif()
 endmacro()
 
 # Issue a fatal error with an appropriate message, when the toolchain
@@ -410,7 +415,12 @@ elseif(GMX_SIMD STREQUAL "IBM_VSX")
         SIMD_${GMX_SIMD}_C_FLAGS SIMD_${GMX_SIMD}_CXX_FLAGS
         "-mvsx" "-maltivec -mabi=altivec" "-qarch=auto -qaltivec")
 
-    if(NOT SIMD_${GMX_SIMD}_C_FLAGS OR NOT SIMD_${GMX_SIMD}_CXX_FLAGS)
+    # Usually we check also for the C compiler here, but a C compiler
+    # is not required for SIMD support on this platform. cmake through
+    # at least version 3.7 cannot pass this check with the C compiler
+    # in the latest xlc 13.1.5, but the C++ compiler has different
+    # behaviour and is OK. See Redmine #2102.
+    if(NOT SIMD_${GMX_SIMD}_CXX_FLAGS)
         gmx_give_fatal_error_when_simd_support_not_found("IBM VSX" "disable SIMD support (slower)" "${SUGGEST_BINUTILS_UPDATE}")
     endif()
 
@@ -468,11 +478,16 @@ endif()
 # rather than actual vector data. For now we disable __vectorcall with clang
 # when using the reference build.
 # 
+# xlc 13.1.5 does not seem recognize any attribute, and warns about invalid ones
+# so we avoid searching for any.
+#
 if(NOT DEFINED GMX_SIMD_CALLING_CONVENTION)
     if(GMX_TARGET_BGQ)
         set(CALLCONV_LIST " ")
     elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND GMX_SIMD STREQUAL "REFERENCE")
         set(CALLCONV_LIST __regcall " ")
+   elseif(CMAKE_CXX_COMPILER_ID MATCHES "XL")
+        set(CALLCONV_LIST " ")
     else()
         set(CALLCONV_LIST __vectorcall __regcall " ")
     endif()
index 40308988eeb52bdb74f7391c99d4138ff5e4756d..5bdb9f0b7af3d284d63194414f746c4a498ac701 100644 (file)
@@ -71,9 +71,18 @@ configuration should be more static.
 clang static analysis
 ^^^^^^^^^^^^^^^^^^^^^
 
-The exact build sequence and the CMake configuration used is in
-:file:`admin/builds/clang-analysis.py`.  This file also specifies the clang
-version used for the analysis.
+The file :file:`admin/builds/clang-analyzer.py` specifies the exact build
+sequence and the CMake cache variables used for clang static analysis.  This
+file also specifies the clang version used for the analysis, as well as the C++
+compiler used (``clang-static-analyzer-<version>``).
+
+To run the analysis outside Jenkins, you should run both ``cmake`` and ``make``
+under ``scan-build`` command using the same CMake cache variables as in the
+build script. When you do the initial CMake configuration with ``scan-build``,
+it sets the C++ compiler to the analyzer. Note that using ``scan-build`` like
+this will also analyze C code, but Jenkins ignores C code for analysis. This
+can result in extra warnings, which can be suppressed by manually setting
+CMAKE_C_COMPILER to a value other than Clang static analyzer.
 
 cppcheck
 ^^^^^^^^
index 9fc01b432e03b38570d5663cf36777408a9f0f88..09950835793bd507346058a0194a5fd7e608f8eb 100644 (file)
@@ -102,10 +102,12 @@ frequently provides the best performance.
 You should strive to use the most recent version of your
 compiler. Since we require full C++11 support the minimum supported
 compiler versions are
+
 * GNU (gcc) 4.8.1
 * Intel (icc) 15.0
 * LLVM (clang) 3.3
 * Microsoft (MSVC) 2015
+
 Other compilers may work (Cray, Pathscale, older clang) but do
 not offer competitive performance. We recommend against PGI because
 the performance with C++ is very bad.
index 405a6096acc4993b0fefd07ebba251c5f76850bf..80f9e55a37cca134e51cab2a7b6b3816fbf8b3e7 100644 (file)
@@ -709,8 +709,12 @@ Running the OpenCL version of mdrun
 -----------------------------------
 
 The current version works with GCN-based AMD GPUs, and NVIDIA CUDA
-GPUs. Make sure that you have the latest drivers installed. The
-minimum OpenCL version required is |REQUIRED_OPENCL_MIN_VERSION|. See
+GPUs. Make sure that you have the latest drivers installed. For AMD GPUs,
+Mesa version 17.0 or newer with LLVM 4.0 or newer is supported in addition
+to the proprietary driver. For NVIDIA GPUs, using the proprietary driver is
+required as the open source nouveau driver (available in Mesa) does not
+provide the OpenCL support.
+The minimum OpenCL version required is |REQUIRED_OPENCL_MIN_VERSION|. See
 also the :ref:`known limitations <opencl-known-limitations>`.
 
 Devices from the AMD GCN architectures (all series) and NVIDIA Fermi
index 5c061659c44a8d5e1f2699921b9dcfcf68f6a44d..8432df588fdb37a8b36c8125605184d0d28091d3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2012,2013,2014,2015,2016,2017, 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.
@@ -73,7 +73,12 @@ elseif(${GMX_SIMD} MATCHES "^(AVX)")
     # Support for --enable-avx2 was only added in 3.3.5, but
     # configuring with it is at worst a warning, even on an earlier
     # version.
+if((CMAKE_COMPILER_IS_GNUCC AND (C_COMPILER_VERSION VERSION_GREATER 4.9 OR CXX_COMPILER_VERSION VERSION_GREATER 4.9)) OR
+   (CMAKE_C_COMPILER_ID MATCHES "Clang" AND (C_COMPILER_VERSION VERSION_GREATER 3.9 OR CXX_COMPILER_VERSION VERSION_GREATER 3.9)))
     set(_fftw_simd_support_level --enable-sse2;--enable-avx;--enable-avx2;--enable-avx512)
+elseif()
+    set(_fftw_simd_support_level --enable-sse2;--enable-avx;--enable-avx2)
+endif()
 elseif(${GMX_SIMD} MATCHES "^(VSX)")
     set(_fftw_simd_support_level --enable-vsx)
 endif()
index f10286b1421f4aca09f8271330d981829943ab06..c7e1210b36fc0c4043aa1560d8d2ef4bb018351a 100644 (file)
@@ -423,8 +423,8 @@ void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string,
     }
     fprintf(fp, "\n");
 
-    /* now print percentages */
-    fprintf(fp, "%-8s %5.2f", "# SS %", total_count / static_cast<real>(mat->nx * mat->ny));
+    /* now print probabilities */
+    fprintf(fp, "%-8s %5.2f", "# SS pr.", total_count / static_cast<real>(mat->nx * mat->ny));
     for (s = 0; s < static_cast<size_t>(mat->nmap); s++)
     {
         fprintf(fp, " %5.2f", total[s] / static_cast<real>(mat->nx * mat->ny));
index f19124b1f25d2ca07954d3e2977d551e602f6480..1229511dd733fc2feb22c3d1511828645efd3db6 100644 (file)
@@ -413,15 +413,16 @@ void dist_plot(const char *fn, const char *afile, const char *dfile,
         sprintf(buf, "%simum Distance", bMin ? "Min" : "Max");
         respertime = xvgropen(rfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv);
         xvgr_legend(respertime, ng-1, (const char**)leg, oenv);
-        if (bPrintResName)
+        if (bPrintResName && output_env_get_print_xvgr_codes(oenv) )
         {
             fprintf(respertime, "# ");
+
+            for (j = 0; j < nres; j++)
+            {
+                fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind);
+            }
+            fprintf(respertime, "\n");
         }
-        for (j = 0; j < nres; j++)
-        {
-            fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind);
-        }
-        fprintf(respertime, "\n");
 
     }
 
index 0d273adb5f6c731a9cb00086fe58c1f66e634121..445f8148be1f0f69e2f896adc17995c3b210b6b2 100644 (file)
@@ -461,7 +461,7 @@ static void write_pdb_bfac(const char *fname, const char *xname,
             svmul(scale, sum[index[i]], sum[index[i]]);
         }
 
-        fp = xvgropen(xname, title, "Atom", "", oenv);
+        fp = xvgropen(xname, title, "Atom", "Spatial component", oenv);
         for (i = 0; i < isize; i++)
         {
             fprintf(fp, "%-5d  %10.3f  %10.3f  %10.3f\n", 1+i,
index 92cae1eff5250383ca1415d2b0ae8013591ad5e9..92c192830d97015a21247d12f83dc094dca83748 100644 (file)
@@ -665,10 +665,6 @@ int gmx_trjconv(int argc, char *argv[])
         "   results if you in fact have a cluster. Luckily that can be checked",
         "   afterwards using a trajectory viewer. Note also that if your molecules",
         "   are broken this will not work either.",
-        "",
-        "   The separate option [TT]-clustercenter[tt] can be used to specify an",
-        "   approximate center for the cluster. This is useful e.g. if you have",
-        "   two big vesicles, and you want to maintain their relative positions.",
         " * [TT]whole[tt] only makes broken molecules whole.",
         "",
 
index ed14fbc0c8f978ce2f154d524ecb401cc92a12a0..e93b4298f126d99691910d60e3368feb9431b5bd 100644 (file)
@@ -660,17 +660,17 @@ static void check_mdrun_works(gmx_bool    bThreads,
      * gmx_print_version_info() in the GMX_MPI section */
     const char match_mpi[]     = "MPI library:        MPI";
     const char match_mdrun[]   = "Executable: ";
-    const char match_gpu[]     = "GPU support:        enabled";
+    const char match_nogpu[]   = "GPU support:        disabled";
     gmx_bool   bMdrun          = FALSE;
     gmx_bool   bMPI            = FALSE;
-    gmx_bool   bHaveGpuSupport = FALSE;
+    gmx_bool   bHaveGpuSupport = TRUE;
 
     /* Run a small test to see whether mpirun + mdrun work  */
     fprintf(stdout, "Making sure that mdrun can be executed. ");
     if (bThreads)
     {
         snew(command, std::strlen(cmd_mdrun) + std::strlen(cmd_np) + std::strlen(filename) + 50);
-        sprintf(command, "%s%s-version -maxh 0.001 1> %s 2>&1", cmd_mdrun, cmd_np, filename);
+        sprintf(command, "%s%s -version -maxh 0.001 1> %s 2>&1", cmd_mdrun, cmd_np, filename);
     }
     else
     {
@@ -703,9 +703,9 @@ static void check_mdrun_works(gmx_bool    bThreads,
             {
                 bMPI = TRUE;
             }
-            if (str_starts(line, match_gpu) )
+            if (str_starts(line, match_nogpu) )
             {
-                bHaveGpuSupport = TRUE;
+                bHaveGpuSupport = FALSE;
             }
         }
     }
index bb8e44bb2cb5ed001bb3d861100118eb0a8ec6ce..c90f0dfec62723e0ea3f961dc049e2447786b3e0 100644 (file)
@@ -811,7 +811,7 @@ void check_ir(const char *mdparin, t_inputrec *ir, t_gromppopts *opts,
         if (expand->nstTij > 0)
         {
             sprintf(err_buf, "nstlog must be non-zero");
-            CHECK(ir->nstlog != 0);
+            CHECK(ir->nstlog == 0);
             sprintf(err_buf, "nst-transition-matrix (%d) must be an integer multiple of nstlog (%d)",
                     expand->nstTij, ir->nstlog);
             CHECK((expand->nstTij % ir->nstlog) != 0);
index 67e264e85457ba3efbab75d9ec86b9c5929698f0..f8d979085bf2f18285f55f0c1d9c54e0feaf89ca 100644 (file)
@@ -491,50 +491,86 @@ static void removeSolventBoxOverlap(t_atoms *atoms, std::vector<RVec> *x,
 }
 
 /*! \brief
- * Removes solvent molecules that overlap with the solute, and optionally also
- * those that are outside a given shell radius from the solute.
+ * Remove all solvent molecules outside a give radius from the solute.
  *
- * \param[in,out] atoms      Solvent atoms.
- * \param[in,out] x          Solvent positions.
- * \param[in,out] v          Solvent velocities (can be empty).
- * \param[in,out] r          Solvent exclusion radii.
- * \param[in]     pbc        PBC information.
- * \param[in]     x_solute   Solute positions.
- * \param[in]     r_solute   Solute exclusion radii.
- * \param[in]     rshell     If >0, only keep solvent atoms within a shell of
- *     this size from the solute.
+ * \param[in,out] atoms     Solvent atoms.
+ * \param[in,out] x_solvent Solvent positions.
+ * \param[in,out] v_solvent Solvent velocities.
+ * \param[in,out] r         Atomic exclusion radii.
+ * \param[in]     pbc       PBC information.
+ * \param[in]     x_solute  Solute positions.
+ * \param[in]     rshell    The radius outside the solute molecule.
  */
-static void removeSoluteOverlap(t_atoms *atoms, std::vector<RVec> *x,
-                                std::vector<RVec> *v, std::vector<real> *r,
-                                const t_pbc &pbc,
-                                const std::vector<RVec> &x_solute,
-                                const std::vector<real> &r_solute,
-                                real rshell)
+static void removeSolventOutsideShell(t_atoms                 *atoms,
+                                      std::vector<RVec>       *x_solvent,
+                                      std::vector<RVec>       *v_solvent,
+                                      std::vector<real>       *r,
+                                      const t_pbc             &pbc,
+                                      const std::vector<RVec> &x_solute,
+                                      real                     rshell)
 {
-    const real                          maxRadius1
-        = *std::max_element(r->begin(), r->end());
-    const real                          maxRadius2
-        = *std::max_element(r_solute.begin(), r_solute.end());
-
     gmx::AtomsRemover                   remover(*atoms);
-    // If rshell is >0, the neighborhood search looks at all pairs
-    // within rshell, and unmarks those that are within the cutoff.
-    // This line marks everything, so that solvent outside rshell remains
-    // marked after the loop.
-    // Without rshell, the neighborhood search only marks the overlapping
-    // solvent atoms, and all others are left alone.
-    if (rshell > 0.0)
+    gmx::AnalysisNeighborhood           nb;
+    nb.setCutoff(rshell);
+    gmx::AnalysisNeighborhoodPositions  posSolute(x_solute);
+    gmx::AnalysisNeighborhoodSearch     search     = nb.initSearch(&pbc, posSolute);
+    gmx::AnalysisNeighborhoodPositions  pos(*x_solvent);
+    gmx::AnalysisNeighborhoodPairSearch pairSearch = search.startPairSearch(pos);
+    gmx::AnalysisNeighborhoodPair       pair;
+
+    // Remove everything
+    remover.markAll();
+    // Now put back those within the shell without checking for overlap
+    while (pairSearch.findNextPair(&pair))
     {
-        remover.markAll();
+        remover.markResidue(*atoms, pair.testIndex(), false);
+        pairSearch.skipRemainingPairsForTestPosition();
     }
+    remover.removeMarkedElements(x_solvent);
+    if (!v_solvent->empty())
+    {
+        remover.removeMarkedElements(v_solvent);
+    }
+    remover.removeMarkedElements(r);
+    const int originalAtomCount = atoms->nr;
+    remover.removeMarkedAtoms(atoms);
+    fprintf(stderr, "Removed %d solvent atoms more than %f nm from solute.\n",
+            originalAtomCount - atoms->nr, rshell);
+}
+
+/*! \brief
+ * Removes solvent molecules that overlap with the solute.
+ *
+ * \param[in,out] atoms    Solvent atoms.
+ * \param[in,out] x        Solvent positions.
+ * \param[in,out] v        Solvent velocities (can be empty).
+ * \param[in,out] r        Solvent exclusion radii.
+ * \param[in]     pbc      PBC information.
+ * \param[in]     x_solute Solute positions.
+ * \param[in]     r_solute Solute exclusion radii.
+ */
+static void removeSolventOverlappingWithSolute(t_atoms                 *atoms,
+                                               std::vector<RVec>       *x,
+                                               std::vector<RVec>       *v,
+                                               std::vector<real>       *r,
+                                               const t_pbc             &pbc,
+                                               const std::vector<RVec> &x_solute,
+                                               const std::vector<real> &r_solute)
+{
+    gmx::AtomsRemover             remover(*atoms);
+    const real                    maxRadius1
+        = *std::max_element(r->begin(), r->end());
+    const real                    maxRadius2
+        = *std::max_element(r_solute.begin(), r_solute.end());
 
+    // Now check for overlap.
     gmx::AnalysisNeighborhood           nb;
-    nb.setCutoff(std::max(maxRadius1 + maxRadius2, rshell));
+    gmx::AnalysisNeighborhoodPair       pair;
+    nb.setCutoff(maxRadius1 + maxRadius2);
     gmx::AnalysisNeighborhoodPositions  posSolute(x_solute);
     gmx::AnalysisNeighborhoodSearch     search     = nb.initSearch(&pbc, posSolute);
     gmx::AnalysisNeighborhoodPositions  pos(*x);
     gmx::AnalysisNeighborhoodPairSearch pairSearch = search.startPairSearch(pos);
-    gmx::AnalysisNeighborhoodPair       pair;
     while (pairSearch.findNextPair(&pair))
     {
         if (remover.isMarked(pair.testIndex()))
@@ -647,8 +683,14 @@ static void add_solv(const char *fn, t_topology *top,
     }
     if (top->atoms.nr > 0)
     {
-        removeSoluteOverlap(atoms_solvt, &x_solvt, &v_solvt, &exclusionDistances_solvt, pbc,
-                            *x, exclusionDistances, rshell);
+        if (rshell > 0.0)
+        {
+            removeSolventOutsideShell(atoms_solvt, &x_solvt,  &v_solvt,
+                                      &exclusionDistances_solvt, pbc, *x, rshell);
+        }
+        removeSolventOverlappingWithSolute(atoms_solvt, &x_solvt, &v_solvt,
+                                           &exclusionDistances_solvt, pbc, *x,
+                                           exclusionDistances);
     }
 
     if (max_sol > 0 && atoms_solvt->nres > max_sol)
diff --git a/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_box_Works.xml b/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_box_Works.xml
new file mode 100644 (file)
index 0000000..8bd8870
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <OutputFiles Name="Files">
+    <File Name="-o">
+      <GroFile Name="Header">
+        <String Name="Title">Generated by gmx solvate</String>
+        <Int Name="Number of atoms">141</Int>
+      </GroFile>
+    </File>
+  </OutputFiles>
+</ReferenceData>
diff --git a/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_Works.xml b/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_Works.xml
new file mode 100644 (file)
index 0000000..b38a36e
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <OutputFiles Name="Files">
+    <File Name="-o">
+      <GroFile Name="Header">
+        <String Name="Title">Test system for solvate/insert-molecules</String>
+        <Int Name="Number of atoms">2664</Int>
+      </GroFile>
+    </File>
+  </OutputFiles>
+</ReferenceData>
diff --git a/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_p_Works.xml b/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_cs_cp_p_Works.xml
new file mode 100644 (file)
index 0000000..b38a36e
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <OutputFiles Name="Files">
+    <File Name="-o">
+      <GroFile Name="Header">
+        <String Name="Title">Test system for solvate/insert-molecules</String>
+        <Int Name="Number of atoms">2664</Int>
+      </GroFile>
+    </File>
+  </OutputFiles>
+</ReferenceData>
diff --git a/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_shell_Works.xml b/src/gromacs/gmxpreprocess/tests/refdata/SolvateTest_shell_Works.xml
new file mode 100644 (file)
index 0000000..f3cdafb
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <OutputFiles Name="Files">
+    <File Name="-o">
+      <GroFile Name="Header">
+        <String Name="Title">Test system for solvate/insert-molecules</String>
+        <Int Name="Number of atoms">762</Int>
+      </GroFile>
+    </File>
+  </OutputFiles>
+</ReferenceData>
index 445e184f75f293e6f5c399bdeb84cdc167112b21..f1858fc9b538b1b2f596c46eafcb03f1f8da0746 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2017, 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/gmxpreprocess/solvate.h"
 
 #include "gromacs/utility/futil.h"
+#include "gromacs/utility/textreader.h"
 
 #include "testutils/cmdlinetest.h"
+#include "testutils/conftest.h"
+#include "testutils/refdata.h"
 #include "testutils/testfilemanager.h"
 #include "testutils/textblockmatchers.h"
 
@@ -54,14 +57,14 @@ namespace
 {
 
 using gmx::test::CommandLine;
-using gmx::test::NoTextMatch;
+using gmx::test::ConfMatch;
 
 class SolvateTest : public gmx::test::CommandLineTestBase
 {
     public:
         SolvateTest()
         {
-            setOutputFile("-o", "out.gro", NoTextMatch());
+            setOutputFile("-o", "out.gro", ConfMatch());
         }
 
         void runTest(const CommandLine &args)
@@ -70,6 +73,7 @@ class SolvateTest : public gmx::test::CommandLineTestBase
             cmdline.merge(args);
 
             ASSERT_EQ(0, gmx_solvate(cmdline.argc(), cmdline.argv()));
+            checkOutputFiles();
         }
 };
 
@@ -109,4 +113,16 @@ TEST_F(SolvateTest, cs_cp_p_Works)
     runTest(CommandLine(cmdline));
 }
 
+TEST_F(SolvateTest, shell_Works)
+{
+    // use default solvent box (-cs without argument)
+    const char *const cmdline[] = {
+        "solvate", "-cs"
+    };
+    setInputFile("-cp", "spc-and-methanol.gro");
+    commandLine().addOption("-shell", 1.0);
+
+    runTest(CommandLine(cmdline));
+}
+
 } // namespace
index 3f32f7446340e4a59caa531d6f0bf95b2dec39a1..d72582984028bc5aba19913336c80eee541da44c 100644 (file)
@@ -607,7 +607,7 @@ do_pairs_simple(int nbonds,
         pbc_dx_aiuc(pbc, xi, xj, dr);
 
         T rsq   = dr[XX]*dr[XX] + dr[YY]*dr[YY] + dr[ZZ]*dr[ZZ];
-        T rinv  = invsqrt(rsq);
+        T rinv  = gmx::invsqrt(rsq);
         T rinv2 = rinv*rinv;
         T rinv6 = rinv2*rinv2*rinv2;
 
index 38dbbd4a67cd99ade440e11a71ca4665151e2389..f0bbde93e52d96c12ad3ad79cd3e124d9566ebc8 100644 (file)
@@ -2484,11 +2484,21 @@ void finish_run(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
             elapsed_time_over_all_ranks,
             elapsed_time_over_all_threads,
             elapsed_time_over_all_threads_over_all_ranks;
+    /* Control whether it is valid to print a report. Only the
+       simulation master may print, but it should not do so if the run
+       terminated e.g. before a scheduled reset step. This is
+       complicated by the fact that PME ranks are unaware of the
+       reason why they were sent a pmerecvqxFINISH. To avoid
+       communication deadlocks, we always do the communication for the
+       report, even if we've decided not to write the report, because
+       how long it takes to finish the run is not important when we've
+       decided not to report on the simulation performance. */
+    bool    printReport = SIMMASTER(cr);
 
     if (!walltime_accounting_get_valid_finish(walltime_accounting))
     {
         GMX_LOG(mdlog.warning).asParagraph().appendText("Simulation ended prematurely, no performance report will be written.");
-        return;
+        printReport = false;
     }
 
     if (cr->nnodes > 1)
@@ -2526,7 +2536,7 @@ void finish_run(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
     }
 #endif
 
-    if (SIMMASTER(cr))
+    if (printReport)
     {
         print_flop(fplog, nrnb_tot, &nbfs, &mflop);
     }
@@ -2549,7 +2559,7 @@ void finish_run(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
     wallcycle_scale_by_num_threads(wcycle, cr->duty == DUTY_PME, nthreads_pp, nthreads_pme);
     auto cycle_sum(wallcycle_sum(cr, wcycle));
 
-    if (SIMMASTER(cr))
+    if (printReport)
     {
         struct gmx_wallclock_gpu_t* gputimes = use_GPU(nbv) ? nbnxn_gpu_get_timings(nbv->gpu_nbv) : nullptr;
 
index e80fcae74e2630891cf7d5d24efcf37798125cd5..89adcd4efddb55aa95e0b52cb7cbfea9830d3f10 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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,2017, 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.
@@ -43,7 +43,7 @@ static inline void
 simdPrefetch(const void * m)
 {
 #if defined(__ibmxl__) || defined(__xlC__)
-    __dcbt(m);
+    __dcbt((void *)m);
 #elif defined __GNUC__
     __builtin_prefetch(m);
 #endif
index 7843aa0d8086584bbec44d147022e51adcc54205..2ce5bd1a834ff279aeb8a4f03d69c2dcb6f47408 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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,2017, 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.
@@ -105,25 +105,15 @@ store4(float *m, Simd4Float a)
 static inline Simd4Float gmx_simdcall
 load4U(const float *m)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    return {
-               vec_xlw4(0, const_cast<float *>(m))
-    }
-#else
     return {
                *reinterpret_cast<const __vector float *>(m)
     };
-#endif
 }
 
 static inline void gmx_simdcall
 store4U(float *m, Simd4Float a)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    vec_xstw4(a.simdInternal_, 0, m);
-#else
     *reinterpret_cast<__vector float *>(m) = a.simdInternal_;
-#endif
 }
 
 static inline Simd4Float gmx_simdcall
index 0ef99549246280536fd5531264900756ceaef0ba..19a6b08a69f7197aefa8190fd588e34a98cb4841 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, 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.
@@ -99,19 +99,8 @@ class SimdDIBool
         __vector vsxBool int  simdInternal_;
 };
 
-// The VSX load & store operations are a bit of a mess. The interface is different
-// for xlc version 12, xlc version 13, and gcc. Long-term IBM recommends
-// simply using pointer dereferencing both for aligned and unaligned loads.
-// That's nice, but unfortunately xlc still bugs out when the pointer is
-// not aligned. Sticking to vec_xl/vec_xst isn't a solution either, since
-// that appears to be buggy for some _aligned_ loads :-)
-//
-// For now, we use pointer dereferencing for all aligned load/stores, and
-// for unaligned ones with gcc. On xlc we use vec_xlw4/vec_xstw4 for
-// unaligned memory operations. The latest docs recommend using the overloaded
-// vec_xl/vec_xst, but that is not supported on xlc version 12. We'll
-// revisit things once xlc is a bit more stable - for now you probably want
-// to stick to gcc...
+// Note that the interfaces we use here have been a mess in xlc;
+// currently version 13.1.5 is required.
 
 static inline SimdDouble gmx_simdcall
 simdLoad(const double *m)
@@ -130,25 +119,15 @@ store(double *m, SimdDouble a)
 static inline SimdDouble gmx_simdcall
 simdLoadU(const double *m)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    return {
-               vec_xlw4(0, const_cast<double *>(m))
-    }
-#else
     return {
                *reinterpret_cast<const __vector double *>(m)
     };
-#endif
 }
 
 static inline void gmx_simdcall
 storeU(double *m, SimdDouble a)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    vec_xstw4(a.simdInternal_, 0, m);
-#else
     *reinterpret_cast<__vector double *>(m) = a.simdInternal_;
-#endif
 }
 
 static inline SimdDouble gmx_simdcall
index 73169a3f6901fb44bb3e74328e2a397a46bd5612..12353fc350746b7612f76ed157dec4b74fca9bb5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, 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.
@@ -99,19 +99,8 @@ class SimdFIBool
         __vector vsxBool int  simdInternal_;
 };
 
-// The VSX load & store operations are a bit of a mess. The interface is different
-// for xlc version 12, xlc version 13, and gcc. Long-term IBM recommends
-// simply using pointer dereferencing both for aligned and unaligned loads.
-// That's nice, but unfortunately xlc still bugs out when the pointer is
-// not aligned. Sticking to vec_xl/vec_xst isn't a solution either, since
-// that appears to be buggy for some _aligned_ loads :-)
-//
-// For now, we use pointer dereferencing for all aligned load/stores, and
-// for unaligned ones with gcc. On xlc we use vec_xlw4/vec_xstw4 for
-// unaligned memory operations. The latest docs recommend using the overloaded
-// vec_xl/vec_xst, but that is not supported on xlc version 12. We'll
-// revisit things once xlc is a bit more stable - for now you probably want
-// to stick to gcc...
+// Note that the interfaces we use here have been a mess in xlc;
+// currently version 13.1.5 is required.
 
 static inline SimdFloat gmx_simdcall
 simdLoad(const float *m)
@@ -130,25 +119,15 @@ store(float *m, SimdFloat a)
 static inline SimdFloat gmx_simdcall
 simdLoadU(const float *m)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    return {
-               vec_xlw4(0, const_cast<float *>(m))
-    }
-#else
     return {
                *reinterpret_cast<const __vector float *>(m)
     };
-#endif
 }
 
 static inline void gmx_simdcall
 storeU(float *m, SimdFloat a)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    vec_xstw4(a.simdInternal_, 0, m);
-#else
     *reinterpret_cast<__vector float *>(m) = a.simdInternal_;
-#endif
 }
 
 static inline SimdFloat gmx_simdcall
@@ -176,25 +155,15 @@ store(std::int32_t * m, SimdFInt32 a)
 static inline SimdFInt32 gmx_simdcall
 simdLoadUFI(const std::int32_t *m)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    return {
-               vec_xlw4(0, const_cast<int *>(m))
-    }
-#else
     return {
                *reinterpret_cast<const __vector int *>(m)
     };
-#endif
 }
 
 static inline void gmx_simdcall
 storeU(std::int32_t * m, SimdFInt32 a)
 {
-#if defined(__ibmxl__) || defined(__xlC__)
-    vec_xstw4(a.simdInternal_, 0, m);
-#else
     *reinterpret_cast<__vector int *>(m) = a.simdInternal_;
-#endif
 }
 
 static inline SimdFInt32 gmx_simdcall
index 8dedb9a66df72951e249418ba2958bc8f6fac3d3..8863765784e716b99bfc4bc734871bb4cd7e1cb4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, 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.
@@ -55,15 +55,17 @@ gatherLoadTranspose(const float *        base,
                     SimdFloat *          v2,
                     SimdFloat *          v3)
 {
-    *v0 = simdLoad( base + align * offset[0] );
-    *v1 = simdLoad( base + align * offset[1] );
-    *v2 = simdLoad( base + align * offset[2] );
-    *v3 = simdLoad( base + align * offset[3] );
-
-    __vector float t0 = vec_mergeh(v0->simdInternal_, v2->simdInternal_);
-    __vector float t1 = vec_mergel(v0->simdInternal_, v2->simdInternal_);
-    __vector float t2 = vec_mergeh(v1->simdInternal_, v3->simdInternal_);
-    __vector float t3 = vec_mergel(v1->simdInternal_, v3->simdInternal_);
+    __vector float l0, l1, l2, l3;
+
+    l0 = simdLoad( base + align * offset[0] ).simdInternal_;
+    l1 = simdLoad( base + align * offset[1] ).simdInternal_;
+    l2 = simdLoad( base + align * offset[2] ).simdInternal_;
+    l3 = simdLoad( base + align * offset[3] ).simdInternal_;
+
+    __vector float t0 = vec_mergeh(l0, l2);
+    __vector float t1 = vec_mergel(l0, l2);
+    __vector float t2 = vec_mergeh(l1, l3);
+    __vector float t3 = vec_mergel(l1, l3);
     v0->simdInternal_ = vec_mergeh(t0, t2);
     v1->simdInternal_ = vec_mergel(t0, t2);
     v2->simdInternal_ = vec_mergeh(t1, t3);
@@ -316,6 +318,9 @@ expandScalarsToTriplets(SimdFloat    scalar,
     triplets2->simdInternal_ = vec_perm(scalar.simdInternal_, t1, perm2);
 }
 
+/* TODO In debug mode, xlc 13.1.5 seems to overwrite v0 on the stack,
+   leading to segfaults. Possibly the calling convention doesn't
+   implement __vector int correctly. Release mode is OK. gcc is OK. */
 template <int align>
 static inline void gmx_simdcall
 gatherLoadBySimdIntTranspose(const float *  base,
index d9aa834dec488223b0e7f18a78c09d716dec4333..532ab3ec887aa5a934664809939f5f4f8d1d6834 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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,2017, 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.
@@ -439,8 +439,9 @@ TEST_F(SimdMathTest, atan2)
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 0.0)), atan2(rSimd_1_2_3, setZero()));
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, -1.0)), atan2(setZero(), rSimd_m1_m2_m3));
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 0.0)), atan2(rSimd_m1_m2_m3, setZero()));
-    // degenerate value (origin) should return 0.0
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, 0.0)), atan2(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
+    // degenerate value (origin) should return 0.0. At least IBM xlc 13.1.5 gets the reference
+    // value wrong (-nan) at -O3 optimization, so we compare to the correct value (0.0) instead.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(0.0), atan2(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
 }
 
 /*! \brief Evaluate reference version of PME force correction. */
@@ -691,8 +692,9 @@ TEST_F(SimdMathTest, atan2SingleAccuracy)
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 0.0)), atan2SingleAccuracy(rSimd_1_2_3, setZero()));
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, -1.0)), atan2SingleAccuracy(setZero(), rSimd_m1_m2_m3));
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 0.0)), atan2SingleAccuracy(rSimd_m1_m2_m3, setZero()));
-    // degenerate value (origin) should return 0.0
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, 0.0)), atan2SingleAccuracy(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
+    // degenerate value (origin) should return 0.0. At least IBM xlc 13.1.5 gets the reference
+    // value wrong (-nan) at -O3 optimization, so we compare to the correct value (0.0) instead.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(0.0), atan2SingleAccuracy(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
 }
 
 TEST_F(SimdMathTest, pmeForceCorrectionSingleAccuracy)
index 6e9e627f12b92db476c2a59e0d3dffffa9c87bb8..f805b1f003ee681b9dfef83d2088888755056fb2 100644 (file)
@@ -139,7 +139,7 @@ void printCopyright(gmx::TextWriter *writer)
     };
     static const char * const CopyrightText[] = {
         "Copyright (c) 1991-2000, University of Groningen, The Netherlands.",
-        "Copyright (c) 2001-2015, The GROMACS development team at",
+        "Copyright (c) 2001-2017, The GROMACS development team at",
         "Uppsala University, Stockholm University and",
         "the Royal Institute of Technology, Sweden.",
         "check out http://www.gromacs.org for more information."
index 2e58d0a7660190baa6d93f4e3a8281c31a03290f..0a52bbe3017c56414e301ec61a1d36d5d6ee39b8 100644 (file)
@@ -1191,8 +1191,15 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                     m_add(force_vir, shake_vir, total_vir);     /* we need the un-dispersion corrected total vir here */
                     trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ2);
 
-                    copy_mat(shake_vir, state->svir_prev);
-                    copy_mat(force_vir, state->fvir_prev);
+                    /* TODO This is only needed when we're about to write
+                     * a checkpoint, because we use it after the restart
+                     * (in a kludge?). But what should we be doing if
+                     * startingFromCheckpoint or bInitStep are true? */
+                    if (inputrecNptTrotter(ir) || inputrecNphTrotter(ir))
+                    {
+                        copy_mat(shake_vir, state->svir_prev);
+                        copy_mat(force_vir, state->fvir_prev);
+                    }
                     if (inputrecNvtTrotter(ir) && ir->eI == eiVV)
                     {
                         /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
@@ -1271,7 +1278,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         bIMDstep = do_IMD(ir->bIMD, step, cr, bNS, state->box, as_rvec_array(state->x.data()), ir, t, wcycle);
 
         /* kludge -- virial is lost with restart for MTTK NPT control. Must reload (saved earlier). */
-        if (startingFromCheckpoint && bTrotter)
+        if (startingFromCheckpoint && (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)))
         {
             copy_mat(state->svir_prev, shake_vir);
             copy_mat(state->fvir_prev, force_vir);
index 0b3dc645eed307cd51dd40afde6f009baa64fe1c..0f1afabcebae4ec4b9d9835c97eca874ef83e15a 100644 (file)
@@ -40,6 +40,7 @@ endif()
 include_directories(BEFORE SYSTEM ${GMOCK_INCLUDE_DIRS})
 set(TESTUTILS_SOURCES
     cmdlinetest.cpp
+    conftest.cpp
     integrationtests.cpp
     interactivetest.cpp
     loggertest.cpp
diff --git a/src/testutils/conftest.cpp b/src/testutils/conftest.cpp
new file mode 100644 (file)
index 0000000..dc591ee
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2017, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Implements routine to check the content of conf files.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \ingroup module_testutils
+ */
+#include "gmxpre.h"
+
+#include "conftest.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textstream.h"
+
+#include "testutils/refdata.h"
+#include "testutils/testasserts.h"
+#include "testutils/textblockmatchers.h"
+
+namespace gmx
+{
+
+namespace test
+{
+
+namespace
+{
+
+class ConfMatcher : public ITextBlockMatcher
+{
+    public:
+        explicit ConfMatcher(const ConfMatchSettings &settings) : settings_(settings)
+        {
+        }
+
+        virtual void checkStream(TextInputStream      *stream,
+                                 TestReferenceChecker *checker)
+        {
+            checkConfFile(stream, checker, settings_);
+        }
+    private:
+        ConfMatchSettings settings_;
+};
+
+}       // namespace
+
+void checkConfFile(TextInputStream         *input,
+                   TestReferenceChecker    *checker,
+                   const ConfMatchSettings  &)
+{
+
+    TestReferenceChecker groChecker(checker->checkCompound("GroFile", "Header"));
+    // Just check the first two lines of the output file
+    std::string          line;
+    EXPECT_TRUE(input->readLine(&line));
+    line = stripSuffixIfPresent(line, "\n");
+    groChecker.checkString(line, "Title");
+    EXPECT_TRUE(input->readLine(&line));
+    line = stripSuffixIfPresent(line, "\n");
+    groChecker.checkInteger(std::atoi(line.c_str()), "Number of atoms");
+}
+
+TextBlockMatcherPointer ConfMatch::createMatcher() const
+{
+    return TextBlockMatcherPointer(new ConfMatcher(settings_));
+}
+
+} // namespace test
+} // namespace gmx
diff --git a/src/testutils/conftest.h b/src/testutils/conftest.h
new file mode 100644 (file)
index 0000000..1ef81de
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2017, 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.
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares function to add the content of a conf file to a checker.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+#ifndef GMX_TESTUTILS_CONFTEST_H
+#define GMX_TESTUTILS_CONFTEST_H
+
+#include <string>
+
+#include "testutils/testasserts.h"
+#include "testutils/textblockmatchers.h"
+
+namespace gmx
+{
+
+class TextInputStream;
+
+namespace test
+{
+
+class TestReferenceChecker;
+
+struct ConfMatchSettings
+{
+    ConfMatchSettings() : tolerance(defaultRealTolerance())
+    {
+    }
+
+    FloatingPointTolerance  tolerance;
+};
+
+/*! \brief
+ * Adds content of a gro file to TestReferenceChecker object.
+ *
+ * \param[in] input       Stream that provides the gro content.
+ * \param[in,out] checker Checker to use.
+ * \param[in] settings    Settings to use for matching.
+ *
+ * Parses a gro file from the input stream, and checks the contents against
+ * reference data (only first two lines for now).
+ *
+ * \see ConfMatch
+ */
+void checkConfFile(TextInputStream         *input,
+                   TestReferenceChecker    *checker,
+                   const ConfMatchSettings &settings);
+
+/*! \libinternal \brief
+ * Match the contents as an gro file.
+ *
+ * \see checkGroFile()
+ *
+ * \inlibraryapi
+ * \ingroup module_testutils
+ */
+class ConfMatch : public ITextBlockMatcherSettings
+{
+    public:
+        //! Sets the tolerance for matching floating point values.
+        ConfMatch &tolerance(const FloatingPointTolerance &tolerance)
+        {
+            settings_.tolerance = tolerance;
+            return *this;
+        }
+
+        virtual TextBlockMatcherPointer createMatcher() const;
+
+    private:
+        ConfMatchSettings  settings_;
+};
+
+} // namespace test
+
+} // namespace gmx
+
+#endif