Merge release-5-0 into master
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 29 Oct 2014 18:52:16 +0000 (20:52 +0200)
committerTeemu Murtola <teemu.murtola@gmail.com>
Wed, 29 Oct 2014 18:52:16 +0000 (20:52 +0200)
Conflicts:
    src/external/gmock-1.7.0/CMakeLists.txt
        - took both changes on the same line
    src/gromacs/gmxpreprocess/calc_verletbuf.c
        - took both changes on the same line
    src/gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_data_mgmt.cu
        - discarded temporary common.h hack from release-5-0 in favor of
          better solution in master
    src/gromacs/selection/nbsearch.cpp
        - resolved all conflicts in favor of master (were from a
          back-ported change)

Change-Id: I34190b704bcb1c020dcc2a3586a25620fd3c3ccf

1  2 
src/external/gmock-1.7.0/CMakeLists.txt
src/gromacs/gmxana/gmx_trjconv.c
src/gromacs/gmxlib/checkpoint.cpp
src/gromacs/gmxpreprocess/calc_verletbuf.c
src/gromacs/mdlib/sim_util.cpp
src/gromacs/selection/nbsearch.cpp

index c9404bf48be0b3eef9b666d115a8fcbe65910753,c31ccf06877d249fa46135673594ef12ea30d952..b9a0f2aada7b4c3182a86679eea043c33d261234
@@@ -37,6 -37,8 +37,6 @@@
  
  include(gmxGetGmockTupleWorkaround)
  get_gmock_tuple_workaround(GMOCK_COMPILE_DEFINITIONS)
 -set(GMOCK_COMPILE_DEFINITIONS "_GNU_SOURCE=1;${GMOCK_COMPILE_DEFINITIONS}")
 -set(GMOCK_COMPILE_DEFINITIONS ${GMOCK_COMPILE_DEFINITIONS} PARENT_SCOPE)
  
  # GTest/GMock suggest linking with pthreads when available for thread safety
  set(CMAKE_THREAD_PREFER_PTHREAD 1)
@@@ -66,11 -68,9 +66,11 @@@ if (HAS_NO_UNUSED_VARIABLE
  endif()
  
  add_library(gmock STATIC ${UNITTEST_TARGET_OPTIONS} ${GMOCK_SOURCES} ${GTEST_SOURCES})
 -set_property(TARGET gmock APPEND PROPERTY COMPILE_DEFINITIONS "${GMOCK_COMPILE_DEFINITIONS};GTEST_CAN_STREAM_RESULTS=0")
 +set_property(TARGET gmock APPEND PROPERTY COMPILE_DEFINITIONS
-              "_GNU_SOURCE=1;${GMOCK_COMPILE_DEFINITIONS}")
++             "_GNU_SOURCE=1;${GMOCK_COMPILE_DEFINITIONS};GTEST_CAN_STREAM_RESULTS=0")
  
  set(GMOCK_LIBRARIES gmock ${PTHREADS_LIBRARIES} PARENT_SCOPE)
  set(GTEST_LIBRARIES ${GMOCK_LIBRARIES} PARENT_SCOPE)
  set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIRS} PARENT_SCOPE)
  set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} PARENT_SCOPE)
 +set(GMOCK_COMPILE_DEFINITIONS ${GMOCK_COMPILE_DEFINITIONS} PARENT_SCOPE)
index 242a6031b075c824f6ca6373e441350295213026,984c8cc078e5a1d68fdd4c11a2484ec927f7355d..87cd62d53f63770bd325a77644ac86561525bbfb
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
  
 -#include <string.h>
  #include <math.h>
 +#include <stdlib.h>
 +#include <string.h>
  
 -#include "copyrite.h"
 -#include "macros.h"
 -#include "sysstuff.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "typedefs.h"
 +#include "gromacs/commandline/pargs.h"
 +#include "gromacs/fileio/confio.h"
  #include "gromacs/fileio/gmxfio.h"
 +#include "gromacs/fileio/pdbio.h"
 +#include "gromacs/fileio/tngio_for_tools.h"
  #include "gromacs/fileio/tpxio.h"
 -#include "gromacs/fileio/trxio.h"
  #include "gromacs/fileio/trnio.h"
 -#include "gromacs/fileio/tngio_for_tools.h"
 -#include "gromacs/commandline/pargs.h"
 -#include "gromacs/fileio/futil.h"
 -#include "gromacs/fileio/pdbio.h"
 -#include "gromacs/fileio/confio.h"
 -#include "names.h"
 -#include "index.h"
 -#include "vec.h"
 +#include "gromacs/fileio/trxio.h"
  #include "gromacs/fileio/xtcio.h"
 -#include "rmpbc.h"
 -#include "pbc.h"
 -#include "viewit.h"
 -#include "xvgr.h"
 -#include "gmx_ana.h"
 -
 +#include "gromacs/fileio/xvgr.h"
 +#include "gromacs/gmxana/gmx_ana.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/macros.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/viewit.h"
  #include "gromacs/math/do_fit.h"
 -#include "gmx_fatal.h"
 -
 -#ifdef HAVE_UNISTD_H
 -#include <unistd.h>
 -#endif
 +#include "gromacs/math/vec.h"
 +#include "gromacs/pbcutil/pbc.h"
 +#include "gromacs/pbcutil/rmpbc.h"
 +#include "gromacs/topology/index.h"
 +#include "gromacs/topology/topology.h"
 +#include "gromacs/utility/fatalerror.h"
 +#include "gromacs/utility/futil.h"
 +#include "gromacs/utility/smalloc.h"
  
  enum {
      euSel, euRect, euTric, euCompact, euNR
@@@ -370,7 -376,7 +370,7 @@@ static void put_residue_com_in_box(int 
              {
                  if (debug)
                  {
 -                    fprintf(debug, "\nShifting position of residue %d (atoms %u-%u) "
 +                    fprintf(debug, "\nShifting position of residue %d (atoms %d-%d) "
                              "by %g,%g,%g\n", atom[res_start].resind+1,
                              res_start+1, res_end+1, shift[XX], shift[YY], shift[ZZ]);
                  }
@@@ -463,12 -469,13 +463,12 @@@ static void mk_filenm(char *base, cons
  
  void check_trn(const char *fn)
  {
 -    if ((fn2ftp(fn) != efTRJ)  && (fn2ftp(fn) != efTRR))
 +    if (fn2ftp(fn) != efTRR)
      {
          gmx_fatal(FARGS, "%s is not a trajectory file, exiting\n", fn);
      }
  }
  
 -#ifndef GMX_NATIVE_WINDOWS
  void do_trunc(const char *fn, real t0)
  {
      t_fileio        *in;
          gmx_fatal(FARGS, "You forgot to set the truncation time");
      }
  
 -    /* Check whether this is a .trj file */
 +    /* Check whether this is a .trr file */
      check_trn(fn);
  
      in   = open_trn(fn, "r");
              {
                  fprintf(stderr, "Once again, I'm gonna DO this...\n");
                  close_trn(in);
 -                if (0 != truncate(fn, fpos))
 +                if (0 != gmx_truncate(fn, fpos))
                  {
                      gmx_fatal(FARGS, "Error truncating file %s", fn);
                  }
          }
      }
  }
 -#endif
  
  /*! \brief Read a full molecular topology if useful and available.
   *
@@@ -607,18 -615,18 +607,18 @@@ int gmx_trjconv(int argc, char *argv[]
          "[PAR]",
  
          "The following formats are supported for input and output:",
 -        "[TT].xtc[tt], [TT].trr[tt], [TT].trj[tt], [TT].gro[tt], [TT].g96[tt]",
 +        "[TT].xtc[tt], [TT].trr[tt], [TT].gro[tt], [TT].g96[tt]",
          "and [TT].pdb[tt].",
          "The file formats are detected from the file extension.",
          "The precision of [TT].xtc[tt] and [TT].gro[tt] output is taken from the",
          "input file for [TT].xtc[tt], [TT].gro[tt] and [TT].pdb[tt],",
          "and from the [TT]-ndec[tt] option for other input formats. The precision",
          "is always taken from [TT]-ndec[tt], when this option is set.",
 -        "All other formats have fixed precision. [TT].trr[tt] and [TT].trj[tt]",
 +        "All other formats have fixed precision. [TT].trr[tt]",
          "output can be single or double precision, depending on the precision",
          "of the [THISMODULE] binary.",
          "Note that velocities are only supported in",
 -        "[TT].trr[tt], [TT].trj[tt], [TT].gro[tt] and [TT].g96[tt] files.[PAR]",
 +        "[TT].trr[tt], [TT].gro[tt] and [TT].g96[tt] files.[PAR]",
  
          "Option [TT]-sep[tt] can be used to write every frame to a separate",
          "[TT].gro, .g96[tt] or [TT].pdb[tt] file. By default, all frames all written to one file.",
          "can reduce the number of frames while using low-pass frequency",
          "filtering, this reduces aliasing of high frequency motions.[PAR]",
  
 -        "Using [TT]-trunc[tt] [THISMODULE] can truncate [TT].trj[tt] in place, i.e.",
 +        "Using [TT]-trunc[tt] [THISMODULE] can truncate [TT].trr[tt] in place, i.e.",
          "without copying the file. This is useful when a run has crashed",
          "during disk I/O (i.e. full disk), or when two contiguous",
          "trajectories must be concatenated without having double frames.[PAR]",
            { &bVels }, "Read and write velocities if possible" },
          { "-force", FALSE, etBOOL,
            { &bForce }, "Read and write forces if possible" },
 -#ifndef GMX_NATIVE_WINDOWS
          { "-trunc", FALSE, etTIME,
            { &ttrunc },
            "Truncate input trajectory file after this time (%t)" },
 -#endif
          { "-exec", FALSE, etSTR,
            { &exec_command },
            "Execute command for every output frame with the "
  
      if (!parse_common_args(&argc, argv,
                             PCA_CAN_BEGIN | PCA_CAN_END | PCA_CAN_VIEW |
 -                           PCA_TIME_UNIT | PCA_BE_NICE,
 +                           PCA_TIME_UNIT,
                             NFILE, fnm, NPA, pa, asize(desc), desc,
                             0, NULL, &oenv))
      {
  
      if (ttrunc != -1)
      {
 -#ifndef GMX_NATIVE_WINDOWS
          do_trunc(in_file, ttrunc);
 -#endif
      }
      else
      {
          {
              /* check if velocities are possible in input and output files */
              ftpin = fn2ftp(in_file);
 -            bVels = (ftp == efTRR || ftp == efTRJ || ftp == efGRO ||
 +            bVels = (ftp == efTRR || ftp == efGRO ||
                       ftp == efG96 || ftp == efTNG)
 -                && (ftpin == efTRR || ftpin == efTRJ || ftpin == efGRO ||
 +                && (ftpin == efTRR || ftpin == efGRO ||
                      ftpin == efG96 || ftpin == efTNG || ftpin == efCPT);
          }
          if (bSeparate || bSplit)
              {
                  gmx_fatal(FARGS, "Output file name '%s' does not contain a '.'", out_file);
              }
 -            outf_base = strdup(out_file);
 +            outf_base = gmx_strdup(out_file);
              outf_base[outf_ext - out_file] = '\0';
          }
  
              useatoms.nr = nout;
          }
          /* select what to read */
 -        if (ftp == efTRR || ftp == efTRJ)
 +        if (ftp == efTRR)
          {
              flags = TRX_READ_X;
          }
                      break;
                  case efXTC:
                  case efTRR:
 -                case efTRJ:
                      out = NULL;
                      if (!bSplit && !bSubTraj)
                      {
                                  write_tng_frame(trxout, &frout);
                                  // TODO when trjconv behaves better: work how to read and write lambda
                                  break;
 -                            case efTRJ:
                              case efTRR:
                              case efXTC:
                                  if (bSplitHere)
                                          }
                                          write_g96_conf(out, &frout, -1, NULL);
                                  }
-                                 if (bSeparate)
+                                 if (bSeparate || bSplitHere)
                                  {
                                      gmx_ffclose(out);
                                      out = NULL;
                              char c[255];
                              sprintf(c, "%s  %d", exec_command, file_nr-1);
                              /*fprintf(stderr,"Executing '%s'\n",c);*/
 -#ifdef GMX_NO_SYSTEM
 -                            printf("Warning-- No calls to system(3) supported on this platform.");
 -                            printf("Warning-- Skipping execution of 'system(\"%s\")'.", c);
 -#else
                              if (0 != system(c))
                              {
                                  gmx_fatal(FARGS, "Error executing command: %s", c);
                              }
 -#endif
                          }
                          outframe++;
                      }
index cf722fcff0d48e57c71ad052615dafd5743cb2c6,5f93ff28e57262ae3452529eb9b5c91a82af36c6..438eafba7df1a448ca468cc11332e7a8b9d062f9
  
  /* The source code in this file should be thread-safe.
     Please keep it that way. */
 +#include "gmxpre.h"
  
 +#include "gromacs/legacyheaders/checkpoint.h"
  
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "config.h"
  
 +#include <errno.h>
 +#include <stdlib.h>
  #include <string.h>
 -#include <time.h>
 -
 -#ifdef HAVE_SYS_TIME_H
 -#include <sys/time.h>
 -#endif
 -
 -#ifdef HAVE_UNISTD_H
 -#include <unistd.h>
 -#endif
  
 +#include <fcntl.h>
  #ifdef GMX_NATIVE_WINDOWS
 -/* _chsize_s */
  #include <io.h>
  #include <sys/locking.h>
  #endif
  
 -#include "copyrite.h"
 -#include "names.h"
 -#include "typedefs.h"
 -#include "types/commrec.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "txtdump.h"
 -#include "vec.h"
 -#include "network.h"
 -#include "checkpoint.h"
 -#include "main.h"
 -#include "gromacs/utility/cstringutil.h"
 -#include <fcntl.h>
 -
 +#include "buildinfo.h"
  #include "gromacs/fileio/filenm.h"
 -#include "gromacs/fileio/futil.h"
  #include "gromacs/fileio/gmxfio.h"
 -#include "gromacs/fileio/xdrf.h"
  #include "gromacs/fileio/xdr_datatype.h"
 +#include "gromacs/fileio/xdrf.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/legacyheaders/txtdump.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/math/vec.h"
  #include "gromacs/utility/baseversion.h"
 -#include "gmx_fatal.h"
 -
 -#include "buildinfo.h"
 +#include "gromacs/utility/cstringutil.h"
 +#include "gromacs/utility/fatalerror.h"
 +#include "gromacs/utility/futil.h"
 +#include "gromacs/utility/smalloc.h"
 +#include "gromacs/utility/sysinfo.h"
  
  #ifdef GMX_FAHCORE
  #include "corewrap.h"
@@@ -148,6 -159,34 +148,6 @@@ const char *edfh_names[edfhNR] 
      "accumulated_plus", "accumulated_minus", "accumulated_plus_2",  "accumulated_minus_2", "Tij", "Tij_empirical"
  };
  
 -#ifdef GMX_NATIVE_WINDOWS
 -static int
 -gmx_wintruncate(const char *filename, __int64 size)
 -{
 -#ifdef GMX_FAHCORE
 -    /*we do this elsewhere*/
 -    return 0;
 -#else
 -    FILE *fp;
 -    int   rc;
 -
 -    fp = fopen(filename, "rb+");
 -
 -    if (fp == NULL)
 -    {
 -        return -1;
 -    }
 -
 -#ifdef _MSC_VER
 -    return _chsize_s( fileno(fp), size);
 -#else
 -    return _chsize( fileno(fp), size);
 -#endif
 -#endif
 -}
 -#endif
 -
 -
  enum {
      ecprREAL, ecprRVEC, ecprMATRIX
  };
@@@ -428,8 -467,6 +428,8 @@@ static int do_cpte_reals_low(XDR *xd, i
      {
          if (dtc == xdr_datatype_double)
          {
 +            /* cppcheck-suppress invalidPointerCast
 +             * Only executed if real is anyhow double */
              vd = (double *)vp;
          }
          else
@@@ -498,6 -535,8 +498,6 @@@ static int do_cpte_n_reals(XDR *xd, in
  static int do_cpte_real(XDR *xd, int cptp, int ecpt, int sflags,
                          real *r, FILE *list)
  {
 -    int n;
 -
      return do_cpte_reals_low(xd, cptp, ecpt, sflags, 1, NULL, &r, list, ecprREAL);
  }
  
@@@ -507,7 -546,7 +507,7 @@@ static int do_cpte_ints(XDR *xd, int cp
      bool_t res = 0;
      int    dtc = xdr_datatype_int;
      int   *vp, *va = NULL;
 -    int    nf, dt, i;
 +    int    nf, dt;
  
      nf  = n;
      res = xdr_int(xd, &nf);
@@@ -574,7 -613,7 +574,7 @@@ static int do_cpte_doubles(XDR *xd, in
      bool_t  res = 0;
      int     dtc = xdr_datatype_double;
      double *vp, *va = NULL;
 -    int     nf, dt, i;
 +    int     nf, dt;
  
      nf  = n;
      res = xdr_int(xd, &nf);
@@@ -639,6 -678,8 +639,6 @@@ static int do_cpte_double(XDR *xd, int 
  static int do_cpte_rvecs(XDR *xd, int cptp, int ecpt, int sflags,
                           int n, rvec **v, FILE *list)
  {
 -    int n3;
 -
      return do_cpte_reals_low(xd, cptp, ecpt, sflags,
                               n*DIM, NULL, (real **)v, list, ecprRVEC);
  }
@@@ -647,7 -688,7 +647,7 @@@ static int do_cpte_matrix(XDR *xd, int 
                            matrix v, FILE *list)
  {
      real *vr;
 -    real  ret;
 +    int   ret;
  
      vr  = (real *)&(v[0][0]);
      ret = do_cpte_reals_low(xd, cptp, ecpt, sflags,
@@@ -666,7 -707,8 +666,7 @@@ static int do_cpte_nmatrix(XDR *xd, in
                             int n, real **v, FILE *list)
  {
      int   i;
 -    real *vr;
 -    real  ret, reti;
 +    int   ret, reti;
      char  name[CPTSTRLEN];
  
      ret = 0;
      }
      for (i = 0; i < n; i++)
      {
 -        reti = 0;
 -        vr   = v[i];
          reti = do_cpte_reals_low(xd, cptp, ecpt, sflags, n, NULL, &(v[i]), NULL, ecprREAL);
          if (list && reti == 0)
          {
              sprintf(name, "%s[%d]", st_names(cptp, ecpt), i);
              pr_reals(list, 0, name, v[i], n);
          }
 -        if (reti == 0)
 +        if (reti != 0)
          {
 -            ret = 0;
 +            ret = reti;
          }
      }
      return ret;
@@@ -778,6 -822,7 +778,6 @@@ static void do_cpt_header(XDR *xd, gmx_
      bool_t res = 0;
      int    magic;
      int    idum = 0;
 -    int    i;
      char  *fhost;
  
      if (bRead)
@@@ -1238,6 -1283,7 +1238,6 @@@ static int do_cpt_enerhist(XDR *xd, gmx
          {
              enerhist->ener_sum_sim[i] = enerhist->ener_sum[i];
          }
 -        fflags |= (1<<eenhENERGY_SUM_SIM);
      }
  
      if ( (fflags & (1<<eenhENERGY_NSUM)) &&
      {
          /* Assume we have an old file format and copy nsum to nsteps */
          enerhist->nsteps = enerhist->nsum;
 -        fflags          |= (1<<eenhENERGY_NSTEPS);
      }
      if ( (fflags & (1<<eenhENERGY_NSUM_SIM)) &&
           !(fflags & (1<<eenhENERGY_NSTEPS_SIM)))
      {
          /* Assume we have an old file format and copy nsum to nsteps */
          enerhist->nsteps_sim = enerhist->nsum_sim;
 -        fflags              |= (1<<eenhENERGY_NSTEPS_SIM);
      }
  
      return ret;
@@@ -1302,7 -1350,7 +1302,7 @@@ static int do_cpt_df_hist(XDR *xd, int 
  static int do_cpt_EDstate(XDR *xd, gmx_bool bRead,
                            edsamstate_t *EDstate, FILE *list)
  {
 -    int  i, j;
 +    int  i;
      int  ret = 0;
      char buf[STRLEN];
  
@@@ -1364,7 -1412,7 +1364,7 @@@ static int do_cpt_files(XDR *xd, gmx_bo
                          gmx_file_position_t **p_outputfiles, int *nfiles,
                          FILE *list, int file_version)
  {
 -    int                  i, j;
 +    int                  i;
      gmx_off_t            offset;
      gmx_off_t            mask = 0xFFFFFFFFL;
      int                  offset_high, offset_low;
@@@ -1466,13 -1514,14 +1466,13 @@@ void write_checkpoint(const char *fn, g
      int                  double_prec;
      char                *fprog;
      char                *fntemp; /* the temporary checkpoint file name */
 -    time_t               now;
      char                 timebuf[STRLEN];
 -    int                  nppnodes, npmenodes, flag_64bit;
 +    int                  nppnodes, npmenodes;
      char                 buf[1024], suffix[5+STEPSTRSIZE], sbuf[STEPSTRSIZE];
      gmx_file_position_t *outputfiles;
      int                  noutputfiles;
      char                *ftime;
 -    int                  flags_eks, flags_enh, flags_dfh, i;
 +    int                  flags_eks, flags_enh, flags_dfh;
      t_fileio            *ret;
  
      if (DOMAINDECOMP(cr))
      snew(fntemp, strlen(fn));
      strcpy(fntemp, fn);
  #endif
 -    time(&now);
 -    gmx_ctime_r(&now, timebuf, STRLEN);
 +    gmx_format_current_time(timebuf, STRLEN);
  
      if (fplog)
      {
@@@ -1758,8 -1808,8 +1758,8 @@@ static void check_match(FILE *fplog
           */
          int   gmx_major, gmx_minor;
          int   cpt_major, cpt_minor;
 -        sscanf(gmx_version(), "VERSION %d.%d", &gmx_major, &gmx_minor);
 -        sscanf(version, "VERSION %d.%d", &cpt_major, &cpt_minor);
 +        sscanf(gmx_version(), "VERSION %5d.%5d", &gmx_major, &gmx_minor);
 +        sscanf(version, "VERSION %5d.%5d", &cpt_major, &cpt_minor);
          version_differs = (gmx_major != cpt_major || gmx_minor != cpt_minor);
      }
  
@@@ -1838,8 -1888,8 +1838,8 @@@ static void read_checkpoint(const char 
      int                  file_version;
      char                *version, *btime, *buser, *bhost, *fprog, *ftime;
      int                  double_prec;
 -    char                 filename[STRLEN], buf[STEPSTRSIZE];
 -    int                  nppnodes, eIntegrator_f, nppnodes_f, npmenodes_f;
 +    char                 buf[STEPSTRSIZE];
 +    int                  eIntegrator_f, nppnodes_f, npmenodes_f;
      ivec                 dd_nc_f;
      int                  natoms, ngtc, nnhpres, nhchainlength, nlambda, fflags, flags_eks, flags_enh, flags_dfh;
      int                  d;
  
      if (!PAR(cr))
      {
 -        nppnodes      = 1;
          cr->npmenodes = 0;
      }
      else if (cr->nnodes == nppnodes_f + npmenodes_f)
          {
              cr->npmenodes = npmenodes_f;
          }
 -        nppnodes = cr->nnodes - cr->npmenodes;
 +        int nppnodes = cr->nnodes - cr->npmenodes;
          if (nppnodes == nppnodes_f)
          {
              for (d = 0; d < DIM; d++)
              }
          }
      }
 -    else
 -    {
 -        /* The number of PP nodes has not been set yet */
 -        nppnodes = -1;
 -    }
  
      if (fflags != state->flags)
      {
          cp_error();
      }
  
-     ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, &state->swapstate, NULL);
+     ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, &state->edsamstate, NULL);
      if (ret)
      {
          cp_error();
      }
  
-     ret = do_cpt_EDstate(gmx_fio_getxdr(fp), TRUE, &state->edsamstate, NULL);
+     ret = do_cpt_swapstate(gmx_fio_getxdr(fp), TRUE, &state->swapstate, NULL);
      if (ret)
      {
          cp_error();
  
              if (i != 0) /*log file is already seeked to correct position */
              {
 -#ifdef GMX_NATIVE_WINDOWS
 -                rc = gmx_wintruncate(outputfiles[i].filename, outputfiles[i].offset);
 -#else
 -                rc = truncate(outputfiles[i].filename, outputfiles[i].offset);
 -#endif
 +#if !defined(GMX_NATIVE_WINDOWS) || !defined(GMX_FAHCORE)
 +                /* For FAHCORE, we do this elsewhere*/
 +                rc = gmx_truncate(outputfiles[i].filename, outputfiles[i].offset);
                  if (rc != 0)
                  {
                      gmx_fatal(FARGS, "Truncation of file %s failed. Cannot do appending because of this failure.", outputfiles[i].filename);
                  }
 +#endif
              }
          }
      }
@@@ -2413,6 -2470,8 +2413,6 @@@ void list_checkpoint(const char *fn, FI
      ivec                 dd_nc;
      t_state              state;
      int                  flags_eks, flags_enh, flags_dfh;
 -    int                  indent;
 -    int                  i, j;
      int                  ret;
      gmx_file_position_t *outputfiles;
      int                  nfiles;
index 676c8c09d183edf975fd49d496e78ab9392bfeab,45d22062d78ecc9cba98133bc7f8311273daa8a3..5c8329344c8434cb468cda962731219e7d12259e
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "calc_verletbuf.h"
  
  #include <assert.h>
 +#include <math.h>
 +#include <stdlib.h>
  
  #include <sys/types.h>
 -#include <math.h>
 -#include "typedefs.h"
 -#include "physics.h"
 +
 +#include "gromacs/ewald/ewald-util.h"
 +#include "gromacs/legacyheaders/macros.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/math/units.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/mdlib/nbnxn_consts.h"
 +#include "gromacs/utility/fatalerror.h"
  #include "gromacs/utility/smalloc.h"
 -#include "gmx_fatal.h"
 -#include "macros.h"
 -#include "vec.h"
 -#include "coulomb.h"
 -#include "calc_verletbuf.h"
 -#include "../mdlib/nbnxn_consts.h"
  
  #ifdef GMX_NBNXN_SIMD
  /* The include below sets the SIMD instruction type (precision+width)
@@@ -208,8 -207,8 +208,8 @@@ static void get_vsite_masses(const gmx_
              for (i = 0; i < il->nr; i += 1+NRAL(ft))
              {
                  const t_iparams *ip;
-                 real             cam[5] = {0}, inv_mass, m_aj;
-                 int              a1, j, aj, coeff;
 -                real             cam[5], inv_mass, coeff, m_aj;
++                real             cam[5] = {0}, inv_mass, coeff, m_aj;
+                 int              a1, j, aj;
  
                  ip = &ffparams->iparams[il->iatoms[i]];
  
                      case F_VSITEN:
                          /* Exact */
                          inv_mass = 0;
-                         for (j = 0; j < 3*ip->vsiten.n; j += 3)
+                         for (j = 0; j < 3*ffparams->iparams[il->iatoms[i]].vsiten.n; j += 3)
                          {
                              aj    = il->iatoms[i+j+2];
-                             coeff = ip[il->iatoms[i+j]].vsiten.a;
+                             coeff = ffparams->iparams[il->iatoms[i+j]].vsiten.a;
                              if (moltype->atoms.atom[aj].ptype == eptVSite)
                              {
                                  m_aj = vsite_m[aj];
@@@ -414,7 -413,6 +414,7 @@@ static void get_verlet_buffer_atomtypes
              add_at(&att, &natt, &prop[a], nmol);
          }
  
 +        /* cppcheck-suppress uninitvar Fixed in cppcheck 1.65 */
          sfree(vsite_m);
          sfree(prop);
      }
index e35e31a8e60044796c1c9544952f14757386949c,72a708f500580847d8de93446f9a707532a05f68..ca9c53f513a198da49e9631f64c5bd9283ddfd91
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "gromacs/legacyheaders/sim_util.h"
 +
 +#include "config.h"
  
  #include <assert.h>
  #include <math.h>
  #include <stdio.h>
  #include <string.h>
 -#ifdef HAVE_SYS_TIME_H
 -#include <sys/time.h>
 -#endif
 -
 -#include "typedefs.h"
 -#include "gromacs/utility/cstringutil.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "names.h"
 -#include "txtdump.h"
 -#include "pbc.h"
 -#include "chargegroup.h"
 -#include "vec.h"
 -#include "nrnb.h"
 -#include "mshift.h"
 -#include "mdrun.h"
 -#include "sim_util.h"
 -#include "update.h"
 -#include "physics.h"
 -#include "main.h"
 -#include "mdatoms.h"
 -#include "force.h"
 -#include "bondf.h"
 -#include "pme.h"
 -#include "disre.h"
 -#include "orires.h"
 -#include "network.h"
 -#include "calcmu.h"
 -#include "constr.h"
 -#include "xvgr.h"
 -#include "copyrite.h"
 -#include "domdec.h"
 -#include "genborn.h"
 -#include "nbnxn_atomdata.h"
 -#include "nbnxn_search.h"
 -#include "nbnxn_kernels/nbnxn_kernel_ref.h"
 -#include "nbnxn_kernels/simd_4xn/nbnxn_kernel_simd_4xn.h"
 -#include "nbnxn_kernels/simd_2xnn/nbnxn_kernel_simd_2xnn.h"
 -#include "nbnxn_kernels/nbnxn_kernel_gpu_ref.h"
 -#include "nonbonded.h"
 -#include "../gmxlib/nonbonded/nb_kernel.h"
 -#include "../gmxlib/nonbonded/nb_free_energy.h"
  
 -#include "gromacs/timing/wallcycle.h"
 -#include "gromacs/timing/walltime_accounting.h"
 -#include "gromacs/utility/gmxmpi.h"
  #include "gromacs/essentialdynamics/edsam.h"
 +#include "gromacs/ewald/pme.h"
 +#include "gromacs/gmxlib/nonbonded/nb_free_energy.h"
 +#include "gromacs/gmxlib/nonbonded/nb_kernel.h"
 +#include "gromacs/imd/imd.h"
 +#include "gromacs/legacyheaders/calcmu.h"
 +#include "gromacs/legacyheaders/chargegroup.h"
 +#include "gromacs/legacyheaders/constr.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/disre.h"
 +#include "gromacs/legacyheaders/domdec.h"
 +#include "gromacs/legacyheaders/force.h"
 +#include "gromacs/legacyheaders/genborn.h"
 +#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
 +#include "gromacs/legacyheaders/mdatoms.h"
 +#include "gromacs/legacyheaders/mdrun.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/legacyheaders/nonbonded.h"
 +#include "gromacs/legacyheaders/nrnb.h"
 +#include "gromacs/legacyheaders/orires.h"
 +#include "gromacs/legacyheaders/qmmm.h"
 +#include "gromacs/legacyheaders/txtdump.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/update.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/listed-forces/bonded.h"
 +#include "gromacs/math/units.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/mdlib/nb_verlet.h"
 +#include "gromacs/mdlib/nbnxn_atomdata.h"
 +#include "gromacs/mdlib/nbnxn_search.h"
 +#include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda.h"
 +#include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_data_mgmt.h"
 +#include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_gpu_ref.h"
 +#include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref.h"
 +#include "gromacs/mdlib/nbnxn_kernels/simd_2xnn/nbnxn_kernel_simd_2xnn.h"
 +#include "gromacs/mdlib/nbnxn_kernels/simd_4xn/nbnxn_kernel_simd_4xn.h"
 +#include "gromacs/pbcutil/ishift.h"
 +#include "gromacs/pbcutil/mshift.h"
 +#include "gromacs/pbcutil/pbc.h"
  #include "gromacs/pulling/pull.h"
  #include "gromacs/pulling/pull_rotation.h"
 -#include "gromacs/imd/imd.h"
 -#include "adress.h"
 -#include "qmmm.h"
 -
 -#include "gmx_omp_nthreads.h"
 +#include "gromacs/timing/wallcycle.h"
 +#include "gromacs/timing/walltime_accounting.h"
 +#include "gromacs/utility/cstringutil.h"
 +#include "gromacs/utility/gmxmpi.h"
 +#include "gromacs/utility/smalloc.h"
 +#include "gromacs/utility/sysinfo.h"
  
 -#include "nbnxn_cuda_data_mgmt.h"
 -#include "nbnxn_cuda/nbnxn_cuda.h"
 +#include "adress.h"
  
  void print_time(FILE                     *out,
                  gmx_walltime_accounting_t walltime_accounting,
@@@ -279,7 -281,8 +279,7 @@@ static void calc_virial(int start, int 
                          tensor vir_part, t_graph *graph, matrix box,
                          t_nrnb *nrnb, const t_forcerec *fr, int ePBC)
  {
 -    int    i, j;
 -    tensor virtest;
 +    int    i;
  
      /* The short-range virial from surrounding boxes */
      clear_mat(vir_part);
      }
  }
  
 -static void posres_wrapper(FILE *fplog,
 -                           int flags,
 -                           gmx_bool bSepDVDL,
 +static void posres_wrapper(int flags,
                             t_inputrec *ir,
                             t_nrnb *nrnb,
                             gmx_localtop_t *top,
                    ir->ePBC == epbcNONE ? NULL : &pbc,
                    lambda[efptRESTRAINT], &dvdl,
                    fr->rc_scaling, fr->ePBC, fr->posres_com, fr->posres_comB);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, interaction_function[F_POSRES].longname, v, dvdl);
 -    }
      enerd->term[F_POSRES] += v;
      /* If just the force constant changes, the FEP term is linear,
       * but if k changes, it is not.
      {
          for (i = 0; i < enerd->n_lambda; i++)
          {
 -            real dvdl_dum, lambda_dum;
 +            real lambda_dum;
  
              lambda_dum = (i == 0 ? lambda[efptRESTRAINT] : ir->fepvals->all_lambda[efptRESTRAINT][i-1]);
              v          = posres(top->idef.il[F_POSRES].nr, top->idef.il[F_POSRES].iatoms,
@@@ -377,7 -386,9 +377,7 @@@ static void fbposres_wrapper(t_inputre
      inc_nrnb(nrnb, eNR_FBPOSRES, top->idef.il[F_FBPOSRES].nr/2);
  }
  
 -static void pull_potential_wrapper(FILE *fplog,
 -                                   gmx_bool bSepDVDL,
 -                                   t_commrec *cr,
 +static void pull_potential_wrapper(t_commrec *cr,
                                     t_inputrec *ir,
                                     matrix box, rvec x[],
                                     rvec f[],
      enerd->term[F_COM_PULL] +=
          pull_potential(ir->ePull, ir->pull, mdatoms, &pbc,
                         cr, t, lambda[efptRESTRAINT], x, f, vir_force, &dvdl);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, "Com pull", enerd->term[F_COM_PULL], dvdl);
 -    }
      enerd->dvdl_lin[efptRESTRAINT] += dvdl;
      wallcycle_stop(wcycle, ewcPULLPOT);
  }
  
 -static void pme_receive_force_ener(FILE           *fplog,
 -                                   gmx_bool        bSepDVDL,
 -                                   t_commrec      *cr,
 +static void pme_receive_force_ener(t_commrec      *cr,
                                     gmx_wallcycle_t wcycle,
                                     gmx_enerdata_t *enerd,
                                     t_forcerec     *fr)
  {
 -    real   e_q, e_lj, v, dvdl_q, dvdl_lj;
 +    real   e_q, e_lj, dvdl_q, dvdl_lj;
      float  cycles_ppdpme, cycles_seppme;
  
      cycles_ppdpme = wallcycle_stop(wcycle, ewcPPDURINGPME);
      gmx_pme_receive_f(cr, fr->f_novirsum, fr->vir_el_recip, &e_q,
                        fr->vir_lj_recip, &e_lj, &dvdl_q, &dvdl_lj,
                        &cycles_seppme);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, "Electrostatic PME mesh", e_q, dvdl_q);
 -        gmx_print_sepdvdl(fplog, "Lennard-Jones PME mesh", e_lj, dvdl_lj);
 -    }
      enerd->term[F_COUL_RECIP] += e_q;
      enerd->term[F_LJ_RECIP]   += e_lj;
      enerd->dvdl_lin[efptCOUL] += dvdl_q;
@@@ -529,7 -551,8 +529,7 @@@ static void do_nb_verlet(t_forcerec *fr
                           t_nrnb *nrnb,
                           gmx_wallcycle_t wcycle)
  {
 -    int                        nnbl, kernel_type, enr_nbnxn_kernel_ljc, enr_nbnxn_kernel_lj;
 -    char                      *env;
 +    int                        enr_nbnxn_kernel_ljc, enr_nbnxn_kernel_lj;
      nonbonded_verlet_group_t  *nbvg;
      gmx_bool                   bCUDA;
  
@@@ -779,11 -802,6 +779,11 @@@ static void do_nb_verlet_fep(nbnxn_pair
      wallcycle_sub_stop(wcycle, ewcsNONBONDED);
  }
  
 +gmx_bool use_GPU(const nonbonded_verlet_t *nbv)
 +{
 +    return nbv != NULL && nbv->bUseGPU;
 +}
 +
  void do_force_cutsVERLET(FILE *fplog, t_commrec *cr,
                           t_inputrec *inputrec,
                           gmx_int64_t step, t_nrnb *nrnb, gmx_wallcycle_t wcycle,
                           gmx_bool bBornRadii,
                           int flags)
  {
 -    int                 cg0, cg1, i, j;
 +    int                 cg1, i, j;
      int                 start, homenr;
 -    int                 nb_kernel_type;
      double              mu[2*DIM];
 -    gmx_bool            bSepDVDL, bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
 +    gmx_bool            bStateChanged, bNS, bFillGrid, bCalcCGCM;
      gmx_bool            bDoLongRange, bDoForces, bSepLRF, bUseGPU, bUseOrEmulGPU;
      gmx_bool            bDiffKernels = FALSE;
 -    matrix              boxs;
      rvec                vzero, box_diag;
 -    real                e, v, dvdl;
      float               cycles_pme, cycles_force, cycles_wait_gpu;
      nonbonded_verlet_t *nbv;
  
      cycles_force    = 0;
      cycles_wait_gpu = 0;
      nbv             = fr->nbv;
 -    nb_kernel_type  = fr->nbv->grp[0].kernel_type;
  
      start  = 0;
      homenr = mdatoms->homenr;
  
 -    bSepDVDL = (fr->bSepDVDL && do_per_step(step, inputrec->nstlog));
 -
      clear_mat(vir_force);
  
 -    cg0 = 0;
      if (DOMAINDECOMP(cr))
      {
          cg1 = cr->dd->ncg_tot;
  #ifdef GMX_MPI
      if (!(cr->duty & DUTY_PME))
      {
 +        gmx_bool bBS;
 +        matrix   boxs;
 +
          /* Send particle coordinates to the pme nodes.
           * Since this is only implemented for domain decomposition
           * and domain decomposition does not use the graph,
      }
  
      /* We calculate the non-bonded forces, when done on the CPU, here.
 -     * We do this before calling do_force_lowlevel, as in there bondeds
 -     * forces are calculated before PME, which does communication.
 -     * With this order, non-bonded and bonded force calculation imbalance
 -     * can be balanced out by the domain decomposition load balancing.
 +     * We do this before calling do_force_lowlevel, because in that
 +     * function, the listed forces are calculated before PME, which
 +     * does communication.  With this order, non-bonded and listed
 +     * force calculation imbalance can be balanced out by the domain
 +     * decomposition load balancing.
       */
  
      if (!bUseOrEmulGPU)
          update_QMMMrec(cr, fr, x, mdatoms, box, top);
      }
  
 -    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
 +    if ((flags & GMX_FORCE_LISTED) && top->idef.il[F_POSRES].nr > 0)
      {
 -        posres_wrapper(fplog, flags, bSepDVDL, inputrec, nrnb, top, box, x,
 +        posres_wrapper(flags, inputrec, nrnb, top, box, x,
                         enerd, lambda, fr);
      }
  
 -    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_FBPOSRES].nr > 0)
 +    if ((flags & GMX_FORCE_LISTED) && top->idef.il[F_FBPOSRES].nr > 0)
      {
          fbposres_wrapper(inputrec, nrnb, top, box, x, enerd, fr);
      }
  
      /* Compute the bonded and non-bonded energies and optionally forces */
 -    do_force_lowlevel(fplog, step, fr, inputrec, &(top->idef),
 +    do_force_lowlevel(fr, inputrec, &(top->idef),
                        cr, nrnb, wcycle, mdatoms,
                        x, hist, f, bSepLRF ? fr->f_twin : f, enerd, fcd, top, fr->born,
 -                      &(top->atomtypes), bBornRadii, box,
 +                      bBornRadii, box,
                        inputrec->fepvals, lambda, graph, &(top->excls), fr->mu_tot,
                        flags, &cycles_pme);
  
          /* Communicate the forces */
          wallcycle_start(wcycle, ewcMOVEF);
          dd_move_f(cr->dd, f, fr->fshift);
-         /* Do we need to communicate the separate force array
-          * for terms that do not contribute to the single sum virial?
-          * Position restraints and electric fields do not introduce
-          * inter-cg forces, only full electrostatics methods do.
-          * When we do not calculate the virial, fr->f_novirsum = f,
-          * so we have already communicated these forces.
-          */
-         if (EEL_FULL(fr->eeltype) && cr->dd->n_intercg_excl &&
-             (flags & GMX_FORCE_VIRIAL))
-         {
-             dd_move_f(cr->dd, fr->f_novirsum, NULL);
-         }
          if (bSepLRF)
          {
              /* We should not update the shift forces here,
          }
  
          /* If we have NoVirSum forces, but we do not calculate the virial,
-          * we sum fr->f_novirum=f later.
+          * we sum fr->f_novirsum=f later.
           */
          if (vsite && !(fr->bF_NoVirSum && !(flags & GMX_FORCE_VIRIAL)))
          {
          /* Since the COM pulling is always done mass-weighted, no forces are
           * applied to vsites and this call can be done after vsite spreading.
           */
 -        pull_potential_wrapper(fplog, bSepDVDL, cr, inputrec, box, x,
 +        pull_potential_wrapper(cr, inputrec, box, x,
                                 f, vir_force, mdatoms, enerd, lambda, t,
                                 wcycle);
      }
          /* In case of node-splitting, the PP nodes receive the long-range
           * forces, virial and energy from the PME nodes here.
           */
 -        pme_receive_force_ener(fplog, bSepDVDL, cr, wcycle, enerd, fr);
 +        pme_receive_force_ener(cr, wcycle, enerd, fr);
      }
  
      if (bDoForces)
@@@ -1607,15 -1616,20 +1595,15 @@@ void do_force_cutsGROUP(FILE *fplog, t_
      int        cg0, cg1, i, j;
      int        start, homenr;
      double     mu[2*DIM];
 -    gmx_bool   bSepDVDL, bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
 -    gmx_bool   bDoLongRangeNS, bDoForces, bDoPotential, bSepLRF;
 +    gmx_bool   bStateChanged, bNS, bFillGrid, bCalcCGCM;
 +    gmx_bool   bDoLongRangeNS, bDoForces, bSepLRF;
      gmx_bool   bDoAdressWF;
 -    matrix     boxs;
 -    rvec       vzero, box_diag;
 -    real       e, v, dvdlambda[efptNR];
      t_pbc      pbc;
      float      cycles_pme, cycles_force;
  
      start  = 0;
      homenr = mdatoms->homenr;
  
 -    bSepDVDL = (fr->bSepDVDL && do_per_step(step, inputrec->nstlog));
 -
      clear_mat(vir_force);
  
      cg0 = 0;
      bFillGrid      = (bNS && bStateChanged);
      bCalcCGCM      = (bFillGrid && !DOMAINDECOMP(cr));
      bDoForces      = (flags & GMX_FORCE_FORCES);
 -    bDoPotential   = (flags & GMX_FORCE_ENERGY);
      bSepLRF        = ((inputrec->nstcalclr > 1) && bDoForces &&
                        (flags & GMX_FORCE_SEPLRF) && (flags & GMX_FORCE_DO_LR));
  
  #ifdef GMX_MPI
      if (!(cr->duty & DUTY_PME))
      {
 +        gmx_bool bBS;
 +        matrix   boxs;
 +
          /* Send particle coordinates to the pme nodes.
           * Since this is only implemented for domain decomposition
           * and domain decomposition does not use the graph,
          update_QMMMrec(cr, fr, x, mdatoms, box, top);
      }
  
 -    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
 +    if ((flags & GMX_FORCE_LISTED) && top->idef.il[F_POSRES].nr > 0)
      {
 -        posres_wrapper(fplog, flags, bSepDVDL, inputrec, nrnb, top, box, x,
 +        posres_wrapper(flags, inputrec, nrnb, top, box, x,
                         enerd, lambda, fr);
      }
  
 -    if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_FBPOSRES].nr > 0)
 +    if ((flags & GMX_FORCE_LISTED) && top->idef.il[F_FBPOSRES].nr > 0)
      {
          fbposres_wrapper(inputrec, nrnb, top, box, x, enerd, fr);
      }
  
      /* Compute the bonded and non-bonded energies and optionally forces */
 -    do_force_lowlevel(fplog, step, fr, inputrec, &(top->idef),
 +    do_force_lowlevel(fr, inputrec, &(top->idef),
                        cr, nrnb, wcycle, mdatoms,
                        x, hist, f, bSepLRF ? fr->f_twin : f, enerd, fcd, top, fr->born,
 -                      &(top->atomtypes), bBornRadii, box,
 +                      bBornRadii, box,
                        inputrec->fepvals, lambda,
                        graph, &(top->excls), fr->mu_tot,
                        flags,
          }
  
          /* If we have NoVirSum forces, but we do not calculate the virial,
-          * we sum fr->f_novirum=f later.
+          * we sum fr->f_novirsum=f later.
           */
          if (vsite && !(fr->bF_NoVirSum && !(flags & GMX_FORCE_VIRIAL)))
          {
  
      if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F)
      {
 -        pull_potential_wrapper(fplog, bSepDVDL, cr, inputrec, box, x,
 +        pull_potential_wrapper(cr, inputrec, box, x,
                                 f, vir_force, mdatoms, enerd, lambda, t,
                                 wcycle);
      }
          /* In case of node-splitting, the PP nodes receive the long-range
           * forces, virial and energy from the PME nodes here.
           */
 -        pme_receive_force_ener(fplog, bSepDVDL, cr, wcycle, enerd, fr);
 +        pme_receive_force_ener(cr, wcycle, enerd, fr);
      }
  
      if (bDoForces)
@@@ -2226,8 -2238,7 +2214,8 @@@ integrate_table(real vdwtab[], real sca
      double invscale, invscale2, invscale3;
      double r, ea, eb, ec, pa, pb, pc, pd;
      double y0, f, g, h;
 -    int    ri, offset, tabfactor;
 +    int    ri, offset;
 +    double tabfactor;
  
      invscale  = 1.0/scale;
      invscale2 = invscale*invscale;
  
  void calc_enervirdiff(FILE *fplog, int eDispCorr, t_forcerec *fr)
  {
 -    double   eners[2], virs[2], enersum, virsum, y0, f, g, h;
 -    double   r0, r1, r, rc3, rc9, ea, eb, ec, pa, pb, pc, pd;
 -    double   invscale, invscale2, invscale3;
 -    int      ri0, ri1, ri, i, offstart, offset;
 -    real     scale, *vdwtab, tabfactor, tmp;
 +    double   eners[2], virs[2], enersum, virsum;
 +    double   r0, rc3, rc9;
 +    int      ri0, ri1, i;
 +    real     scale, *vdwtab;
  
      fr->enershiftsix    = 0;
      fr->enershifttwelve = 0;
              vdwtab = fr->nblists[0].table_vdw.data;
  
              /* Round the cut-offs to exact table values for precision */
 -            ri0  = floor(fr->rvdw_switch*scale);
 -            ri1  = ceil(fr->rvdw*scale);
 +            ri0  = static_cast<int>(floor(fr->rvdw_switch*scale));
 +            ri1  = static_cast<int>(ceil(fr->rvdw*scale));
  
              /* The code below has some support for handling force-switching, i.e.
               * when the force (instead of potential) is switched over a limited
              ri0  = (fr->vdw_modifier == eintmodPOTSHIFT) ? ri1 : ri0;
  
              r0   = ri0/scale;
 -            r1   = ri1/scale;
              rc3  = r0*r0*r0;
              rc9  = rc3*rc3*rc3;
  
      }
  }
  
 -void calc_dispcorr(FILE *fplog, t_inputrec *ir, t_forcerec *fr,
 -                   gmx_int64_t step, int natoms,
 +void calc_dispcorr(t_inputrec *ir, t_forcerec *fr,
 +                   int natoms,
                     matrix box, real lambda, tensor pres, tensor virial,
                     real *prescorr, real *enercorr, real *dvdlcorr)
  {
              }
          }
  
 -        if (fr->bSepDVDL && do_per_step(step, ir->nstlog))
 -        {
 -            gmx_print_sepdvdl(fplog, "Dispersion correction", *enercorr, dvdlambda);
 -        }
          if (fr->efep != efepNO)
          {
              *dvdlcorr += dvdlambda;
@@@ -2667,12 -2684,13 +2655,12 @@@ void finish_run(FILE *fplog, t_commrec 
                  t_inputrec *inputrec,
                  t_nrnb nrnb[], gmx_wallcycle_t wcycle,
                  gmx_walltime_accounting_t walltime_accounting,
 -                wallclock_gpu_t *gputimes,
 +                nonbonded_verlet_t *nbv,
                  gmx_bool bWriteStat)
  {
 -    int     i, j;
      t_nrnb *nrnb_tot = NULL;
 -    real    delta_t;
 -    double  nbfs, mflop;
 +    double  delta_t  = 0;
 +    double  nbfs     = 0, mflop = 0;
      double  elapsed_time,
              elapsed_time_over_all_ranks,
              elapsed_time_over_all_threads,
  
      if (SIMMASTER(cr))
      {
 +        wallclock_gpu_t* gputimes = use_GPU(nbv) ?
 +            nbnxn_cuda_get_timings(nbv->cu_nbv) : NULL;
          wallcycle_print(fplog, cr->nnodes, cr->npmenodes,
                          elapsed_time_over_all_ranks,
                          wcycle, gputimes);
          {
              delta_t = inputrec->delta_t;
          }
 -        else
 -        {
 -            delta_t = 0;
 -        }
  
          if (fplog)
          {
@@@ -2842,7 -2862,8 +2830,7 @@@ void init_md(FILE *fplog
               gmx_bool *bSimAnn, t_vcm **vcm, unsigned long Flags,
               gmx_wallcycle_t wcycle)
  {
 -    int  i, j, n;
 -    real tmpt, mod;
 +    int  i;
  
      /* Initial values */
      *t = *t0       = ir->init_t;
index 7e32fa6536b1ad066a2d7cdb1bb9df420a9fc742,599d4218812acaea132c5fb533d554e65633a307..801ee2a1db6c94e9a23fe234de1e971b47350549
@@@ -40,6 -40,9 +40,6 @@@
   * The grid implementation could still be optimized in several different ways:
   *   - Triclinic grid cells are not the most efficient shape, but make PBC
   *     handling easier.
 - *   - Precalculating the required PBC shift for a pair of cells outside the
 - *     inner loop. After this is done, it should be quite straightforward to
 - *     move to rectangular cells.
   *   - Pruning grid cells from the search list if they are completely outside
   *     the sphere that is being considered.
   *   - A better heuristic could be added for falling back to simple loops for a
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_selection
   */
 -#include "gromacs/selection/nbsearch.h"
 +#include "gmxpre.h"
  
 -#include <math.h>
 +#include "nbsearch.h"
 +
 +#include <cmath>
 +#include <cstring>
  
  #include <algorithm>
  #include <vector>
  
  #include "thread_mpi/mutex.h"
  
 -#include "gromacs/legacyheaders/typedefs.h"
 -#include "gromacs/legacyheaders/pbc.h"
 -#include "gromacs/legacyheaders/vec.h"
 -
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/pbcutil/pbc.h"
  #include "gromacs/selection/position.h"
 +#include "gromacs/topology/block.h"
  #include "gromacs/utility/arrayref.h"
 +#include "gromacs/utility/exceptions.h"
  #include "gromacs/utility/gmxassert.h"
  #include "gromacs/utility/smalloc.h"
 +#include "gromacs/utility/stringutil.h"
  
  namespace gmx
  {
@@@ -100,14 -98,10 +100,14 @@@ class AnalysisNeighborhoodSearchImp
           * Initializes the search with a given box and reference positions.
           *
           * \param[in]     mode      Search mode to use.
 +         * \param[in]     bXY       Whether to use 2D searching.
 +         * \param[in]     excls     Exclusions.
           * \param[in]     pbc       PBC information.
           * \param[in]     positions Set of reference positions.
           */
          void init(AnalysisNeighborhood::SearchMode     mode,
 +                  bool                                 bXY,
 +                  const t_blocka                      *excls,
                    const t_pbc                         *pbc,
                    const AnalysisNeighborhoodPositions &positions);
          PairSearchImplPointer getPairSearch();
           * \param[in]     pbc  Information about the box.
           * \returns  false if grid search is not suitable.
           */
 -        bool initGridCells(const t_pbc *pbc);
 +        bool initGridCells(const t_pbc &pbc);
          /*! \brief
           * Sets ua a search grid for a given box.
           *
           * \param[in]     pbc  Information about the box.
           * \returns  false if grid search is not suitable.
           */
 -        bool initGrid(const t_pbc *pbc);
 +        bool initGrid(const t_pbc &pbc);
          /*! \brief
           * Maps a point into a grid cell.
           *
           * \param[in]     i    Index to add.
           */
          void addToGridCell(const ivec cell, int i);
 +        /*! \brief
 +         * Calculates the index of a neighboring grid cell.
 +         *
 +         * \param[in]  sourceCell Location of the source cell.
 +         * \param[in]  index      Index of the neighbor to calculate.
 +         * \param[out] shift      Shift to apply to get the periodic distance
 +         *     for distances between the cells.
 +         * \returns    Grid cell index of the neighboring cell.
 +         */
 +        int getNeighboringCell(const ivec sourceCell, int index, rvec shift) const;
  
          //! Whether to try grid searching.
          bool                    bTryGrid_;
          real                    cutoff_;
          //! The cutoff squared.
          real                    cutoff2_;
 +        //! Whether to do searching in XY plane only.
 +        bool                    bXY_;
  
          //! Number of reference points for the current frame.
          int                     nref_;
          //! Reference point positions.
          const rvec             *xref_;
 -        //! Reference position ids (NULL if not available).
 -        const int              *refid_;
 +        //! Reference position exclusion IDs.
 +        const int              *refExclusionIds_;
 +        //! Exclusions.
 +        const t_blocka         *excls_;
          //! PBC data.
 -        t_pbc                  *pbc_;
 -
 -        //! Number of excluded reference positions for current test particle.
 -        int                     nexcl_;
 -        //! Exclusions for current test particle.
 -        int                    *excl_;
 +        t_pbc                   pbc_;
  
          //! Whether grid searching is actually used for the current positions.
          bool                    bGrid_;
@@@ -223,9 -208,6 +223,9 @@@ class AnalysisNeighborhoodPairSearchImp
          explicit AnalysisNeighborhoodPairSearchImpl(const AnalysisNeighborhoodSearchImpl &search)
              : search_(search)
          {
 +            testExclusionIds_ = NULL;
 +            nexcl_            = 0;
 +            excl_             = NULL;
              clear_rvec(xtest_);
              clear_ivec(testcell_);
              reset(-1);
          const AnalysisNeighborhoodSearchImpl   &search_;
          //! Reference to the test positions.
          ConstArrayRef<rvec>                     testPositions_;
 +        //! Reference to the test exclusion indices.
 +        const int                              *testExclusionIds_;
 +        //! Number of excluded reference positions for current test particle.
 +        int                                     nexcl_;
 +        //! Exclusions for current test particle.
 +        const int                              *excl_;
          //! Index of the currently active test position in \p testPositions_.
          int                                     testIndex_;
          //! Stores test position during a pair loop.
          rvec                                    xtest_;
          //! Stores the previous returned position during a pair loop.
          int                                     previ_;
 +        //! Stores the pair distance corresponding to previ_;
 +        real                                    prevr2_;
          //! Stores the current exclusion index during loops.
          int                                     exclind_;
          //! Stores the test particle cell index during loops.
@@@ -291,12 -265,14 +291,12 @@@ AnalysisNeighborhoodSearchImpl::Analysi
          bTryGrid_   = false;
      }
      cutoff2_        = sqr(cutoff_);
 +    bXY_            = false;
  
 -    nref_           = 0;
 -    xref_           = NULL;
 -    refid_          = NULL;
 -    pbc_            = NULL;
 -
 -    nexcl_          = 0;
 -    excl_           = NULL;
 +    nref_            = 0;
 +    xref_            = NULL;
 +    refExclusionIds_ = NULL;
 +    std::memset(&pbc_, 0, sizeof(pbc_));
  
      bGrid_          = false;
  
@@@ -382,16 -358,16 +382,16 @@@ void AnalysisNeighborhoodSearchImpl::in
      }
  }
  
 -bool AnalysisNeighborhoodSearchImpl::initGridCells(const t_pbc *pbc)
 +bool AnalysisNeighborhoodSearchImpl::initGridCells(const t_pbc &pbc)
  {
      const real targetsize =
 -        pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
 +        pow(pbc.box[XX][XX] * pbc.box[YY][YY] * pbc.box[ZZ][ZZ]
              * 10 / nref_, static_cast<real>(1./3.));
  
      int cellCount = 1;
      for (int dd = 0; dd < DIM; ++dd)
      {
 -        ncelldim_[dd] = static_cast<int>(pbc->box[dd][dd] / targetsize);
 +        ncelldim_[dd] = static_cast<int>(pbc.box[dd][dd] / targetsize);
          cellCount    *= ncelldim_[dd];
          if (ncelldim_[dd] < 3)
          {
      return true;
  }
  
 -bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc *pbc)
 +bool AnalysisNeighborhoodSearchImpl::initGrid(const t_pbc &pbc)
  {
      /* TODO: This check could be improved. */
 -    if (0.5*pbc->max_cutoff2 < cutoff2_)
 +    if (0.5*pbc.max_cutoff2 < cutoff2_)
      {
          return false;
      }
          return false;
      }
  
 -    bTric_ = TRICLINIC(pbc->box);
 +    bTric_ = TRICLINIC(pbc.box);
      if (bTric_)
      {
          for (int dd = 0; dd < DIM; ++dd)
          {
 -            svmul(1.0 / ncelldim_[dd], pbc->box[dd], cellbox_[dd]);
 +            svmul(1.0 / ncelldim_[dd], pbc.box[dd], cellbox_[dd]);
          }
          m_inv_ur0(cellbox_, recipcell_);
      }
      {
          for (int dd = 0; dd < DIM; ++dd)
          {
 -            cellbox_[dd][dd]   = pbc->box[dd][dd] / ncelldim_[dd];
 +            cellbox_[dd][dd]   = pbc.box[dd][dd] / ncelldim_[dd];
              recipcell_[dd][dd] = 1.0 / cellbox_[dd][dd];
          }
      }
@@@ -463,12 -439,12 +463,12 @@@ void AnalysisNeighborhoodSearchImpl::ma
              while (cellIndex < 0)
              {
                  cellIndex += cellCount;
 -                rvec_add(xtmp, pbc_->box[dd], xtmp);
 +                rvec_add(xtmp, pbc_.box[dd], xtmp);
              }
              while (cellIndex >= cellCount)
              {
                  cellIndex -= cellCount;
 -                rvec_sub(xtmp, pbc_->box[dd], xtmp);
 +                rvec_sub(xtmp, pbc_.box[dd], xtmp);
              }
              cell[dd] = cellIndex;
          }
              while (cellIndex < 0)
              {
                  cellIndex += cellCount;
 -                xtmp[dd]  += pbc_->box[dd][dd];
 +                xtmp[dd]  += pbc_.box[dd][dd];
              }
              while (cellIndex >= cellCount)
              {
                  cellIndex -= cellCount;
 -                xtmp[dd]  -= pbc_->box[dd][dd];
 +                xtmp[dd]  -= pbc_.box[dd][dd];
              }
              cell[dd] = cellIndex;
          }
@@@ -513,72 -489,19 +513,72 @@@ void AnalysisNeighborhoodSearchImpl::ad
      cells_[ci].push_back(i);
  }
  
 +int AnalysisNeighborhoodSearchImpl::getNeighboringCell(
 +        const ivec sourceCell, int index, rvec shift) const
 +{
 +    ivec cell;
 +    ivec_add(sourceCell, gnboffs_[index], cell);
 +
 +    // TODO: Consider unifying with the similar shifting code in
 +    // mapPointToGridCell().
 +    clear_rvec(shift);
 +    for (int d = 0; d < DIM; ++d)
 +    {
 +        const int cellCount = ncelldim_[d];
 +        if (cell[d] < 0)
 +        {
 +            cell[d] += cellCount;
 +            rvec_add(shift, pbc_.box[d], shift);
 +        }
 +        else if (cell[d] >= cellCount)
 +        {
 +            cell[d] -= cellCount;
 +            rvec_sub(shift, pbc_.box[d], shift);
 +        }
 +    }
 +
 +    return getGridCellIndex(cell);
 +}
 +
  void AnalysisNeighborhoodSearchImpl::init(
          AnalysisNeighborhood::SearchMode     mode,
 +        bool                                 bXY,
 +        const t_blocka                      *excls,
          const t_pbc                         *pbc,
          const AnalysisNeighborhoodPositions &positions)
  {
      GMX_RELEASE_ASSERT(positions.index_ == -1,
                         "Individual indexed positions not supported as reference");
 -    pbc_  = const_cast<t_pbc *>(pbc);
 +    bXY_ = bXY;
 +    if (bXY_ && pbc->ePBC != epbcNONE)
 +    {
 +        if (pbc->ePBC != epbcXY && pbc->ePBC != epbcXYZ)
 +        {
 +            std::string message =
 +                formatString("Computations in the XY plane are not supported with PBC type '%s'",
 +                             EPBC(pbc->ePBC));
 +            GMX_THROW(NotImplementedError(message));
 +        }
 +        if (std::fabs(pbc->box[ZZ][XX]) > GMX_REAL_EPS*pbc->box[ZZ][ZZ] ||
 +            std::fabs(pbc->box[ZZ][YY]) > GMX_REAL_EPS*pbc->box[ZZ][ZZ])
 +        {
 +            GMX_THROW(NotImplementedError("Computations in the XY plane are not supported when the last box vector is not parallel to the Z axis"));
 +        }
 +        set_pbc(&pbc_, epbcXY, const_cast<rvec *>(pbc->box));
 +    }
 +    else if (pbc != NULL)
 +    {
 +        pbc_  = *pbc;
 +    }
 +    else
 +    {
 +        pbc_.ePBC = epbcNONE;
 +    }
      nref_ = positions.count_;
      // TODO: Consider whether it would be possible to support grid searching in
      // more cases.
      if (mode == AnalysisNeighborhood::eSearchMode_Simple
 -        || pbc_ == NULL || pbc_->ePBC != epbcXYZ)
 +        || pbc_.ePBC != epbcXYZ)
      {
          bGrid_ = false;
      }
      {
          xref_ = positions.x_;
      }
 -    // TODO: Once exclusions are supported, this may need to be initialized.
 -    refid_ = NULL;
 -}
 -
 -#if 0
 -/*! \brief
 - * Sets the exclusions for the next neighborhood search.
 - *
 - * \param[in,out] d     Neighborhood search data structure.
 - * \param[in]     nexcl Number of reference positions to exclude from next
 - *      search.
 - * \param[in]     excl  Indices of reference positions to exclude.
 - *
 - * The set exclusions remain in effect until the next call of this function.
 - */
 -void
 -gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
 -{
 -
 -    d->nexcl = nexcl;
 -    d->excl  = excl;
 +    excls_           = excls;
 +    refExclusionIds_ = NULL;
 +    if (excls != NULL)
 +    {
 +        // TODO: Check that the IDs are ascending, or remove the limitation.
 +        refExclusionIds_ = positions.exclusionIds_;
 +        GMX_RELEASE_ASSERT(refExclusionIds_ != NULL,
 +                           "Exclusion IDs must be set for reference positions "
 +                           "when exclusions are enabled");
 +    }
  }
 -#endif
  
  /********************************************************************
   * AnalysisNeighborhoodPairSearchImpl
@@@ -628,7 -563,6 +628,6 @@@ void AnalysisNeighborhoodPairSearchImpl
      testIndex_ = testIndex;
      if (testIndex_ >= 0 && testIndex_ < static_cast<int>(testPositions_.size()))
      {
-         copy_rvec(testPositions_[testIndex_], xtest_);
          if (search_.bGrid_)
          {
              search_.mapPointToGridCell(testPositions_[testIndex], testcell_, xtest_);
          {
              copy_rvec(testPositions_[testIndex_], xtest_);
          }
 +        if (search_.excls_ != NULL)
 +        {
 +            const int exclIndex  = testExclusionIds_[testIndex];
 +            if (exclIndex < search_.excls_->nr)
 +            {
 +                const int startIndex = search_.excls_->index[exclIndex];
 +                nexcl_ = search_.excls_->index[exclIndex + 1] - startIndex;
 +                excl_  = &search_.excls_->a[startIndex];
 +            }
 +            else
 +            {
 +                nexcl_ = 0;
 +                excl_  = NULL;
 +            }
 +        }
      }
      previ_     = -1;
 +    prevr2_    = 0.0;
      exclind_   = 0;
      prevnbi_   = 0;
      prevcai_   = -1;
@@@ -671,17 -589,34 +670,17 @@@ void AnalysisNeighborhoodPairSearchImpl
  
  bool AnalysisNeighborhoodPairSearchImpl::isExcluded(int j)
  {
 -    if (exclind_ < search_.nexcl_)
 +    if (exclind_ < nexcl_)
      {
 -        if (search_.refid_)
 +        const int refId = search_.refExclusionIds_[j];
 +        while (exclind_ < nexcl_ && excl_[exclind_] < refId)
          {
 -            while (exclind_ < search_.nexcl_
 -                   && search_.excl_[exclind_] < search_.refid_[j])
 -            {
 -                ++exclind_;
 -            }
 -            if (exclind_ < search_.nexcl_
 -                && search_.refid_[j] == search_.excl_[exclind_])
 -            {
 -                ++exclind_;
 -                return true;
 -            }
 +            ++exclind_;
          }
 -        else
 +        if (exclind_ < nexcl_ && refId == excl_[exclind_])
          {
 -            while (search_.bGrid_ && exclind_ < search_.nexcl_
 -                   && search_.excl_[exclind_] < j)
 -            {
 -                ++exclind_;
 -            }
 -            if (search_.excl_[exclind_] == j)
 -            {
 -                ++exclind_;
 -                return true;
 -            }
 +            ++exclind_;
 +            return true;
          }
      }
      return false;
  void AnalysisNeighborhoodPairSearchImpl::startSearch(
          const AnalysisNeighborhoodPositions &positions)
  {
 +    testExclusionIds_ = positions.exclusionIds_;
 +    GMX_RELEASE_ASSERT(search_.excls_ == NULL || testExclusionIds_ != NULL,
 +                       "Exclusion IDs must be set when exclusions are enabled");
      if (positions.index_ < 0)
      {
          testPositions_ = constArrayRefFromArray<rvec>(positions.x_, positions.count_);
@@@ -714,16 -646,21 +713,16 @@@ bool AnalysisNeighborhoodPairSearchImpl
      {
          if (search_.bGrid_)
          {
 +            GMX_RELEASE_ASSERT(!search_.bXY_, "Grid-based XY searches not implemented");
 +
              int nbi = prevnbi_;
              int cai = prevcai_ + 1;
  
              for (; nbi < search_.ngridnb_; ++nbi)
              {
 -                ivec cell;
 -
 -                ivec_add(testcell_, search_.gnboffs_[nbi], cell);
 -                cell[XX] = (cell[XX] + search_.ncelldim_[XX]) % search_.ncelldim_[XX];
 -                cell[YY] = (cell[YY] + search_.ncelldim_[YY]) % search_.ncelldim_[YY];
 -                cell[ZZ] = (cell[ZZ] + search_.ncelldim_[ZZ]) % search_.ncelldim_[ZZ];
 -
 -                const int ci       = search_.getGridCellIndex(cell);
 +                rvec      shift;
 +                const int ci       = search_.getNeighboringCell(testcell_, nbi, shift);
                  const int cellSize = static_cast<int>(search_.cells_[ci].size());
 -                /* TODO: Calculate the required PBC shift outside the inner loop */
                  for (; cai < cellSize; ++cai)
                  {
                      const int i = search_.cells_[ci][cai];
                          continue;
                      }
                      rvec       dx;
 -                    pbc_dx_aiuc(search_.pbc_, xtest_, search_.xref_[i], dx);
 +                    rvec_sub(xtest_, search_.xref_[i], dx);
 +                    rvec_add(dx, shift, dx);
                      const real r2 = norm2(dx);
                      if (r2 <= search_.cutoff2_)
                      {
                              prevnbi_ = nbi;
                              prevcai_ = cai;
                              previ_   = i;
 +                            prevr2_  = r2;
                              return true;
                          }
                      }
                      continue;
                  }
                  rvec dx;
 -                if (search_.pbc_)
 +                if (search_.pbc_.ePBC != epbcNONE)
                  {
 -                    pbc_dx(search_.pbc_, xtest_, search_.xref_[i], dx);
 +                    pbc_dx(&search_.pbc_, xtest_, search_.xref_[i], dx);
                  }
                  else
                  {
                      rvec_sub(xtest_, search_.xref_[i], dx);
                  }
 -                const real r2 = norm2(dx);
 +                const real r2
 +                    = search_.bXY_
 +                        ? dx[XX]*dx[XX] + dx[YY]*dx[YY]
 +                        : norm2(dx);
                  if (r2 <= search_.cutoff2_)
                  {
                      if (action(i, r2))
                      {
 -                        previ_ = i;
 +                        previ_  = i;
 +                        prevr2_ = r2;
                          return true;
                      }
                  }
@@@ -797,7 -728,7 +796,7 @@@ void AnalysisNeighborhoodPairSearchImpl
      }
      else
      {
 -        *pair = AnalysisNeighborhoodPair(previ_, testIndex_);
 +        *pair = AnalysisNeighborhoodPair(previ_, testIndex_, prevr2_);
      }
  }
  
@@@ -878,7 -809,7 +877,7 @@@ class AnalysisNeighborhood::Imp
          typedef AnalysisNeighborhoodSearch::ImplPointer SearchImplPointer;
          typedef std::vector<SearchImplPointer> SearchList;
  
 -        Impl() : cutoff_(0), mode_(eSearchMode_Automatic)
 +        Impl() : cutoff_(0), excls_(NULL), mode_(eSearchMode_Automatic), bXY_(false)
          {
          }
          ~Impl()
          tMPI::mutex             createSearchMutex_;
          SearchList              searchList_;
          real                    cutoff_;
 +        const t_blocka         *excls_;
          SearchMode              mode_;
 +        bool                    bXY_;
  };
  
  AnalysisNeighborhood::Impl::SearchImplPointer
@@@ -940,18 -869,6 +939,18 @@@ void AnalysisNeighborhood::setCutoff(re
      impl_->cutoff_ = cutoff;
  }
  
 +void AnalysisNeighborhood::setXYMode(bool bXY)
 +{
 +    impl_->bXY_ = bXY;
 +}
 +
 +void AnalysisNeighborhood::setTopologyExclusions(const t_blocka *excls)
 +{
 +    GMX_RELEASE_ASSERT(impl_->searchList_.empty(),
 +                       "Changing the exclusions after initSearch() not currently supported");
 +    impl_->excls_ = excls;
 +}
 +
  void AnalysisNeighborhood::setMode(SearchMode mode)
  {
      impl_->mode_ = mode;
@@@ -967,7 -884,7 +966,7 @@@ AnalysisNeighborhood::initSearch(const 
                                   const AnalysisNeighborhoodPositions &positions)
  {
      Impl::SearchImplPointer search(impl_->getSearch());
 -    search->init(mode(), pbc, positions);
 +    search->init(mode(), impl_->bXY_, impl_->excls_, pbc, positions);
      return AnalysisNeighborhoodSearch(search);
  }
  
@@@ -1030,7 -947,7 +1029,7 @@@ AnalysisNeighborhoodSearch::nearestPoin
      int           closestPoint = -1;
      MindistAction action(&closestPoint, &minDist2);
      (void)pairSearch.searchNext(action);
 -    return AnalysisNeighborhoodPair(closestPoint, 0);
 +    return AnalysisNeighborhoodPair(closestPoint, 0, minDist2);
  }
  
  AnalysisNeighborhoodPairSearch