Domain decomposition now checks the rlist buffer
[alexxy/gromacs.git] / src / gromacs / mdlib / domdec.c
index 8d2fdb7f4a66a96c87c9db8052c3ee49cd97adca..ca2514a5dd4df5bd133c842e9890aa7c54a4f297 100644 (file)
@@ -1,19 +1,36 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
+/*
+ * This file is part of the GROMACS molecular simulation package.
  *
- * This file is part of Gromacs        Copyright (c) 1991-2008
- * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ * Copyright (c) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
+ * 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.
  *
- * To help us fund GROMACS development, we humbly ask that you cite
- * the research papers on the package. Check out http://www.gromacs.org
+ * 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.
  *
- * And Hey:
- * Gnomes, ROck Monsters And Chili Sauce
+ * 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 <math.h>
 #include <string.h>
 #include <stdlib.h>
+#include <assert.h>
+
 #include "typedefs.h"
-#include "smalloc.h"
+#include "gromacs/utility/smalloc.h"
 #include "gmx_fatal.h"
 #include "gmx_fatal_collective.h"
 #include "vec.h"
 #include "constr.h"
 #include "mdatoms.h"
 #include "names.h"
-#include "pdbio.h"
-#include "futil.h"
 #include "force.h"
 #include "pme.h"
-#include "pull.h"
-#include "pull_rotation.h"
-#include "gmx_wallcycle.h"
 #include "mdrun.h"
 #include "nsgrid.h"
 #include "shellfc.h"
 #include "mtop_util.h"
-#include "gmxfio.h"
 #include "gmx_ga2la.h"
-#include "gmx_sort.h"
 #include "macros.h"
 #include "nbnxn_search.h"
 #include "bondf.h"
 #include "gmx_omp_nthreads.h"
-
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREAD_MPI
-#include "tmpi.h"
-#endif
+#include "gpu_utils.h"
+
+#include "gromacs/fileio/futil.h"
+#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/fileio/pdbio.h"
+#include "gromacs/timing/wallcycle.h"
+#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/swap/swapcoords.h"
+#include "gromacs/utility/qsort_threadsafe.h"
+#include "gromacs/pulling/pull.h"
+#include "gromacs/pulling/pull_rotation.h"
+#include "gromacs/imd/imd.h"
 
 #define DDRANK(dd, rank)    (rank)
 #define DDMASTERRANK(dd)   (dd->masterrank)
@@ -351,8 +368,10 @@ typedef struct gmx_domdec_comm
     /* Stuff for load communication */
     gmx_bool           bRecordLoad;
     gmx_domdec_load_t *load;
+    int                nrank_gpu_shared;
 #ifdef GMX_MPI
     MPI_Comm          *mpi_comm_load;
+    MPI_Comm           mpi_comm_gpu_shared;
 #endif
 
     /* Maximum DLB scaling per load balancing step in percent */
@@ -383,7 +402,7 @@ typedef struct gmx_domdec_comm
     double load_pme;
 
     /* The last partition step */
-    gmx_large_int_t partition_step;
+    gmx_int64_t partition_step;
 
     /* Debugging */
     int  nstDDDump;
@@ -433,8 +452,14 @@ static const ivec dd_zp1[dd_zp1n] = {{0, 0, 2}};
 /* Factor to account for pressure scaling during nstlist steps */
 #define DD_PRES_SCALE_MARGIN 1.02
 
-/* Allowed performance loss before we DLB or warn */
-#define DD_PERF_LOSS 0.05
+/* Turn on DLB when the load imbalance causes this amount of total loss.
+ * There is a bit of overhead with DLB and it's difficult to achieve
+ * a load imbalance of less than 2% with DLB.
+ */
+#define DD_PERF_LOSS_DLB_ON  0.02
+
+/* Warn about imbalance due to PP or PP/PME load imbalance at this loss */
+#define DD_PERF_LOSS_WARN    0.05
 
 #define DD_CELL_F_SIZE(dd, di) ((dd)->nc[(dd)->dim[(di)]]+1+(di)*2+1+(di))
 
@@ -1295,7 +1320,6 @@ static void dd_collect_cg(gmx_domdec_t *dd,
 {
     gmx_domdec_master_t *ma = NULL;
     int                  buf2[2], *ibuf, i, ncg_home = 0, *cg = NULL, nat_home = 0;
-    t_block             *cgs_gl;
 
     if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
     {
@@ -1305,12 +1329,18 @@ static void dd_collect_cg(gmx_domdec_t *dd,
 
     if (state_local->ddp_count == dd->ddp_count)
     {
+        /* The local state and DD are in sync, use the DD indices */
         ncg_home = dd->ncg_home;
         cg       = dd->index_gl;
         nat_home = dd->nat_home;
     }
     else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
     {
+        /* The DD is out of sync with the local state, but we have stored
+         * the cg indices with the local state, so we can use those.
+         */
+        t_block *cgs_gl;
+
         cgs_gl = &dd->comm->cgs_gl;
 
         ncg_home = state_local->ncg_gl;
@@ -1326,8 +1356,8 @@ static void dd_collect_cg(gmx_domdec_t *dd,
         gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
     }
 
-    buf2[0] = dd->ncg_home;
-    buf2[1] = dd->nat_home;
+    buf2[0] = ncg_home;
+    buf2[1] = nat_home;
     if (DDMASTER(dd))
     {
         ma   = dd->ma;
@@ -1369,7 +1399,7 @@ static void dd_collect_cg(gmx_domdec_t *dd,
 
     /* Collect the charge group indices on the master */
     dd_gatherv(dd,
-               dd->ncg_home*sizeof(int), dd->index_gl,
+               ncg_home*sizeof(int), cg,
                DDMASTER(dd) ? ma->ibuf : NULL,
                DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
                DDMASTER(dd) ? ma->cg : NULL);
@@ -1534,7 +1564,6 @@ void dd_collect_state(gmx_domdec_t *dd,
         copy_mat(state_local->fvir_prev, state->fvir_prev);
         copy_mat(state_local->pres_prev, state->pres_prev);
 
-
         for (i = 0; i < state_local->ngtc; i++)
         {
             for (j = 0; j < nh; j++)
@@ -1571,37 +1600,6 @@ void dd_collect_state(gmx_domdec_t *dd,
                 case estCGP:
                     dd_collect_vec(dd, state_local, state_local->cg_p, state->cg_p);
                     break;
-                case estLD_RNG:
-                    if (state->nrngi == 1)
-                    {
-                        if (DDMASTER(dd))
-                        {
-                            for (i = 0; i < state_local->nrng; i++)
-                            {
-                                state->ld_rng[i] = state_local->ld_rng[i];
-                            }
-                        }
-                    }
-                    else
-                    {
-                        dd_gather(dd, state_local->nrng*sizeof(state->ld_rng[0]),
-                                  state_local->ld_rng, state->ld_rng);
-                    }
-                    break;
-                case estLD_RNGI:
-                    if (state->nrngi == 1)
-                    {
-                        if (DDMASTER(dd))
-                        {
-                            state->ld_rngi[0] = state_local->ld_rngi[0];
-                        }
-                    }
-                    else
-                    {
-                        dd_gather(dd, sizeof(state->ld_rngi[0]),
-                                  state_local->ld_rngi, state->ld_rngi);
-                    }
-                    break;
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
                 case estORIRE_INITF:
@@ -1643,8 +1641,6 @@ static void dd_realloc_state(t_state *state, rvec **f, int nalloc)
                 case estCGP:
                     srenew(state->cg_p, state->nalloc);
                     break;
-                case estLD_RNG:
-                case estLD_RNGI:
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
                 case estORIRE_INITF:
@@ -1792,6 +1788,35 @@ static void dd_distribute_vec(gmx_domdec_t *dd, t_block *cgs, rvec *v, rvec *lv)
     }
 }
 
+static void dd_distribute_dfhist(gmx_domdec_t *dd, df_history_t *dfhist)
+{
+    int i;
+    dd_bcast(dd, sizeof(int), &dfhist->bEquil);
+    dd_bcast(dd, sizeof(int), &dfhist->nlambda);
+    dd_bcast(dd, sizeof(real), &dfhist->wl_delta);
+
+    if (dfhist->nlambda > 0)
+    {
+        int nlam = dfhist->nlambda;
+        dd_bcast(dd, sizeof(int)*nlam, dfhist->n_at_lam);
+        dd_bcast(dd, sizeof(real)*nlam, dfhist->wl_histo);
+        dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_weights);
+        dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_dg);
+        dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_minvar);
+        dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_variance);
+
+        for (i = 0; i < nlam; i++)
+        {
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p[i]);
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m[i]);
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p2[i]);
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m2[i]);
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij[i]);
+            dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij_empirical[i]);
+        }
+    }
+}
+
 static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
                                 t_state *state, t_state *state_local,
                                 rvec **f)
@@ -1814,6 +1839,7 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
         copy_mat(state->boxv, state_local->boxv);
         copy_mat(state->svir_prev, state_local->svir_prev);
         copy_mat(state->fvir_prev, state_local->fvir_prev);
+        copy_df_history(&state_local->dfhist, &state->dfhist);
         for (i = 0; i < state_local->ngtc; i++)
         {
             for (j = 0; j < nh; j++)
@@ -1847,6 +1873,9 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
     dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_xi);
     dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_vxi);
 
+    /* communicate df_history -- required for restarting from checkpoint */
+    dd_distribute_dfhist(dd, &state_local->dfhist);
+
     if (dd->nat_home > state_local->nalloc)
     {
         dd_realloc_state(state_local, f, dd->nat_home);
@@ -1869,32 +1898,6 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
                 case estCGP:
                     dd_distribute_vec(dd, cgs, state->cg_p, state_local->cg_p);
                     break;
-                case estLD_RNG:
-                    if (state->nrngi == 1)
-                    {
-                        dd_bcastc(dd,
-                                  state_local->nrng*sizeof(state_local->ld_rng[0]),
-                                  state->ld_rng, state_local->ld_rng);
-                    }
-                    else
-                    {
-                        dd_scatter(dd,
-                                   state_local->nrng*sizeof(state_local->ld_rng[0]),
-                                   state->ld_rng, state_local->ld_rng);
-                    }
-                    break;
-                case estLD_RNGI:
-                    if (state->nrngi == 1)
-                    {
-                        dd_bcastc(dd, sizeof(state_local->ld_rngi[0]),
-                                  state->ld_rngi, state_local->ld_rngi);
-                    }
-                    else
-                    {
-                        dd_scatter(dd, sizeof(state_local->ld_rngi[0]),
-                                   state->ld_rngi, state_local->ld_rngi);
-                    }
-                    break;
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
                 case estORIRE_INITF:
@@ -1923,11 +1926,11 @@ static char dim2char(int dim)
     return c;
 }
 
-static void write_dd_grid_pdb(const char *fn, gmx_large_int_t step,
+static void write_dd_grid_pdb(const char *fn, gmx_int64_t step,
                               gmx_domdec_t *dd, matrix box, gmx_ddbox_t *ddbox)
 {
     rvec   grid_s[2], *grid_r = NULL, cx, r;
-    char   fname[STRLEN], format[STRLEN], buf[22];
+    char   fname[STRLEN], buf[22];
     FILE  *out;
     int    a, i, d, z, y, x;
     matrix tric;
@@ -1967,7 +1970,6 @@ static void write_dd_grid_pdb(const char *fn, gmx_large_int_t step,
             }
         }
         sprintf(fname, "%s_%s.pdb", fn, gmx_step_str(step, buf));
-        sprintf(format, "%s%s\n", get_pdbformat(), "%6.2f%6.2f");
         out = gmx_fio_fopen(fname, "w");
         gmx_write_pdb_box(out, dd->bScrewPBC ? epbcSCREW : epbcXYZ, box);
         a = 1;
@@ -1988,8 +1990,8 @@ static void write_dd_grid_pdb(const char *fn, gmx_large_int_t step,
                         cx[YY] = grid_r[i*2+y][YY];
                         cx[ZZ] = grid_r[i*2+z][ZZ];
                         mvmul(tric, cx, r);
-                        fprintf(out, format, "ATOM", a++, "CA", "GLY", ' ', 1+i,
-                                10*r[XX], 10*r[YY], 10*r[ZZ], 1.0, vol);
+                        gmx_fprintf_pdb_atomline(out, epdbATOM, a++, "CA", ' ', "GLY", ' ', i+1, ' ',
+                                                 10*r[XX], 10*r[YY], 10*r[ZZ], 1.0, vol, "");
                     }
                 }
             }
@@ -2012,11 +2014,11 @@ static void write_dd_grid_pdb(const char *fn, gmx_large_int_t step,
     }
 }
 
-void write_dd_pdb(const char *fn, gmx_large_int_t step, const char *title,
+void write_dd_pdb(const char *fn, gmx_int64_t step, const char *title,
                   gmx_mtop_t *mtop, t_commrec *cr,
                   int natoms, rvec x[], matrix box)
 {
-    char          fname[STRLEN], format[STRLEN], format4[STRLEN], buf[22];
+    char          fname[STRLEN], buf[22];
     FILE         *out;
     int           i, ii, resnr, c;
     char         *atomname, *resname;
@@ -2031,9 +2033,6 @@ void write_dd_pdb(const char *fn, gmx_large_int_t step, const char *title,
 
     sprintf(fname, "%s_%s_n%d.pdb", fn, gmx_step_str(step, buf), cr->sim_nodeid);
 
-    sprintf(format, "%s%s\n", get_pdbformat(), "%6.2f%6.2f");
-    sprintf(format4, "%s%s\n", get_pdbformat4(), "%6.2f%6.2f");
-
     out = gmx_fio_fopen(fname, "w");
 
     fprintf(out, "TITLE     %s\n", title);
@@ -2059,10 +2058,8 @@ void write_dd_pdb(const char *fn, gmx_large_int_t step, const char *title,
         {
             b = dd->comm->zones.n + 1;
         }
-        fprintf(out, strlen(atomname) < 4 ? format : format4,
-                "ATOM", (ii+1)%100000,
-                atomname, resname, ' ', resnr%10000, ' ',
-                10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ], 1.0, b);
+        gmx_fprintf_pdb_atomline(out, epdbATOM, ii+1, atomname, ' ', resname, ' ', resnr, ' ',
+                                 10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ], 1.0, b, "");
     }
     fprintf(out, "TER\n");
 
@@ -2300,6 +2297,21 @@ static int dd_simnode2pmenode(t_commrec *cr, int sim_nodeid)
     return pmenode;
 }
 
+void get_pme_nnodes(const gmx_domdec_t *dd,
+                    int *npmenodes_x, int *npmenodes_y)
+{
+    if (dd != NULL)
+    {
+        *npmenodes_x = dd->comm->npmenodes_x;
+        *npmenodes_y = dd->comm->npmenodes_y;
+    }
+    else
+    {
+        *npmenodes_x = 1;
+        *npmenodes_y = 1;
+    }
+}
+
 gmx_bool gmx_pmeonlynode(t_commrec *cr, int sim_nodeid)
 {
     gmx_bool bPMEOnlyNode;
@@ -2364,7 +2376,7 @@ void get_pme_ddnodes(t_commrec *cr, int pmenodeid,
 
     if (debug)
     {
-        fprintf(debug, "Receive coordinates from PP nodes:");
+        fprintf(debug, "Receive coordinates from PP ranks:");
         for (x = 0; x < *nmy_ddnodes; x++)
         {
             fprintf(debug, " %d", (*my_ddnodes)[x]);
@@ -2427,6 +2439,8 @@ static void set_zones_ncg_home(gmx_domdec_t *dd)
     {
         zones->cg_range[i] = dd->ncg_home;
     }
+    /* zone_ncg1[0] should always be equal to ncg_home */
+    dd->comm->zone_ncg1[0] = dd->ncg_home;
 }
 
 static void rebuild_cgindex(gmx_domdec_t *dd,
@@ -2578,7 +2592,7 @@ static int check_bLocalCG(gmx_domdec_t *dd, int ncg_sys, const char *bLocalCG,
         if (!bLocalCG[dd->index_gl[i]])
         {
             fprintf(stderr,
-                    "DD node %d, %s: cg %d, global cg %d is not marked in bLocalCG (ncg_home %d)\n", dd->rank, where, i+1, dd->index_gl[i]+1, dd->ncg_home);
+                    "DD rank %d, %s: cg %d, global cg %d is not marked in bLocalCG (ncg_home %d)\n", dd->rank, where, i+1, dd->index_gl[i]+1, dd->ncg_home);
             nerr++;
         }
     }
@@ -2592,7 +2606,7 @@ static int check_bLocalCG(gmx_domdec_t *dd, int ncg_sys, const char *bLocalCG,
     }
     if (ngl != dd->ncg_tot)
     {
-        fprintf(stderr, "DD node %d, %s: In bLocalCG %d cgs are marked as local, whereas there are %d\n", dd->rank, where, ngl, dd->ncg_tot);
+        fprintf(stderr, "DD rank %d, %s: In bLocalCG %d cgs are marked as local, whereas there are %d\n", dd->rank, where, ngl, dd->ncg_tot);
         nerr++;
     }
 
@@ -2615,7 +2629,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
         {
             if (have[dd->gatindex[a]] > 0)
             {
-                fprintf(stderr, "DD node %d: global atom %d occurs twice: index %d and %d\n", dd->rank, dd->gatindex[a]+1, have[dd->gatindex[a]], a+1);
+                fprintf(stderr, "DD rank %d: global atom %d occurs twice: index %d and %d\n", dd->rank, dd->gatindex[a]+1, have[dd->gatindex[a]], a+1);
             }
             else
             {
@@ -2634,7 +2648,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
         {
             if (a >= dd->nat_tot)
             {
-                fprintf(stderr, "DD node %d: global atom %d marked as local atom %d, which is larger than nat_tot (%d)\n", dd->rank, i+1, a+1, dd->nat_tot);
+                fprintf(stderr, "DD rank %d: global atom %d marked as local atom %d, which is larger than nat_tot (%d)\n", dd->rank, i+1, a+1, dd->nat_tot);
                 nerr++;
             }
             else
@@ -2642,7 +2656,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
                 have[a] = 1;
                 if (dd->gatindex[a] != i)
                 {
-                    fprintf(stderr, "DD node %d: global atom %d marked as local atom %d, which has global atom index %d\n", dd->rank, i+1, a+1, dd->gatindex[a]+1);
+                    fprintf(stderr, "DD rank %d: global atom %d marked as local atom %d, which has global atom index %d\n", dd->rank, i+1, a+1, dd->gatindex[a]+1);
                     nerr++;
                 }
             }
@@ -2652,7 +2666,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
     if (ngl != dd->nat_tot)
     {
         fprintf(stderr,
-                "DD node %d, %s: %d global atom indices, %d local atoms\n",
+                "DD rank %d, %s: %d global atom indices, %d local atoms\n",
                 dd->rank, where, ngl, dd->nat_tot);
     }
     for (a = 0; a < dd->nat_tot; a++)
@@ -2660,7 +2674,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
         if (have[a] == 0)
         {
             fprintf(stderr,
-                    "DD node %d, %s: local atom %d, global %d has no global index\n",
+                    "DD rank %d, %s: local atom %d, global %d has no global index\n",
                     dd->rank, where, a+1, dd->gatindex[a]+1);
         }
     }
@@ -2670,7 +2684,7 @@ static void check_index_consistency(gmx_domdec_t *dd,
 
     if (nerr > 0)
     {
-        gmx_fatal(FARGS, "DD node %d, %s: %d atom/cg index inconsistencies",
+        gmx_fatal(FARGS, "DD rank %d, %s: %d atom/cg index inconsistencies",
                   dd->rank, where, nerr);
     }
 }
@@ -2721,10 +2735,18 @@ static real cellsize_min_dlb(gmx_domdec_comm_t *comm, int dim_ind, int dim)
 
     cellsize_min = comm->cellsize_min[dim];
 
-    if (!comm->bVacDLBNoLimit && comm->bPMELoadBalDLBLimits)
+    if (!comm->bVacDLBNoLimit)
     {
-        cellsize_min = max(cellsize_min,
-                           comm->PMELoadBal_max_cutoff/comm->cd[dim_ind].np_dlb);
+        /* The cut-off might have changed, e.g. by PME load balacning,
+         * from the value used to set comm->cellsize_min, so check it.
+         */
+        cellsize_min = max(cellsize_min, comm->cutoff/comm->cd[dim_ind].np_dlb);
+
+        if (comm->bPMELoadBalDLBLimits)
+        {
+            /* Check for the cut-off limit set by the PME load balancing */
+            cellsize_min = max(cellsize_min, comm->PMELoadBal_max_cutoff/comm->cd[dim_ind].np_dlb);
+        }
     }
 
     return cellsize_min;
@@ -2755,7 +2777,7 @@ static real grid_jump_limit(gmx_domdec_comm_t *comm, real cutoff,
     return grid_jump_limit;
 }
 
-static gmx_bool check_grid_jump(gmx_large_int_t step,
+static gmx_bool check_grid_jump(gmx_int64_t     step,
                                 gmx_domdec_t   *dd,
                                 real            cutoff,
                                 gmx_ddbox_t    *ddbox,
@@ -2791,7 +2813,7 @@ static gmx_bool check_grid_jump(gmx_large_int_t step,
                 /* This error should never be triggered under normal
                  * circumstances, but you never know ...
                  */
-                gmx_fatal(FARGS, "Step %s: The domain decomposition grid has shifted too much in the %c-direction around cell %d %d %d. This should not have happened. Running with less nodes might avoid this issue.",
+                gmx_fatal(FARGS, "Step %s: The domain decomposition grid has shifted too much in the %c-direction around cell %d %d %d. This should not have happened. Running with fewer ranks might avoid this issue.",
                           gmx_step_str(step, buf),
                           dim2char(dim), dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
             }
@@ -2824,12 +2846,40 @@ static float dd_force_load(gmx_domdec_comm_t *comm)
         if (comm->cycl_n[ddCyclF] > 1)
         {
             /* Subtract the maximum of the last n cycle counts
-             * to get rid of possible high counts due to other soures,
+             * to get rid of possible high counts due to other sources,
              * for instance system activity, that would otherwise
              * affect the dynamic load balancing.
              */
             load -= comm->cycl_max[ddCyclF];
         }
+
+#ifdef GMX_MPI
+        if (comm->cycl_n[ddCyclWaitGPU] && comm->nrank_gpu_shared > 1)
+        {
+            float gpu_wait, gpu_wait_sum;
+
+            gpu_wait = comm->cycl[ddCyclWaitGPU];
+            if (comm->cycl_n[ddCyclF] > 1)
+            {
+                /* We should remove the WaitGPU time of the same MD step
+                 * as the one with the maximum F time, since the F time
+                 * and the wait time are not independent.
+                 * Furthermore, the step for the max F time should be chosen
+                 * the same on all ranks that share the same GPU.
+                 * But to keep the code simple, we remove the average instead.
+                 * The main reason for artificially long times at some steps
+                 * is spurious CPU activity or MPI time, so we don't expect
+                 * that changes in the GPU wait time matter a lot here.
+                 */
+                gpu_wait *= (comm->cycl_n[ddCyclF] - 1)/(float)comm->cycl_n[ddCyclF];
+            }
+            /* Sum the wait times over the ranks that share the same GPU */
+            MPI_Allreduce(&gpu_wait, &gpu_wait_sum, 1, MPI_FLOAT, MPI_SUM,
+                          comm->mpi_comm_gpu_shared);
+            /* Replace the wait time by the average over the ranks */
+            load += -gpu_wait + gpu_wait_sum/comm->nrank_gpu_shared;
+        }
+#endif
     }
 
     return load;
@@ -3035,8 +3085,17 @@ static void check_box_size(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
     }
 }
 
+enum {
+    setcellsizeslbLOCAL, setcellsizeslbMASTER, setcellsizeslbPULSE_ONLY
+};
+
+/* Set the domain boundaries. Use for static (or no) load balancing,
+ * and also for the starting state for dynamic load balancing.
+ * setmode determine if and where the boundaries are stored, use enum above.
+ * Returns the number communication pulses in npulse.
+ */
 static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
-                                  gmx_bool bMaster, ivec npulse)
+                                  int setmode, ivec npulse)
 {
     gmx_domdec_comm_t *comm;
     int                d, j;
@@ -3053,20 +3112,23 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
         {
             /* Uniform grid */
             cell_dx = ddbox->box_size[d]/dd->nc[d];
-            if (bMaster)
-            {
-                for (j = 0; j < dd->nc[d]+1; j++)
-                {
-                    dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
-                }
-            }
-            else
+            switch (setmode)
             {
-                comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d]  )*cell_dx;
-                comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
+                case setcellsizeslbMASTER:
+                    for (j = 0; j < dd->nc[d]+1; j++)
+                    {
+                        dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
+                    }
+                    break;
+                case setcellsizeslbLOCAL:
+                    comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d]  )*cell_dx;
+                    comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
+                    break;
+                default:
+                    break;
             }
             cellsize = cell_dx*ddbox->skew_fac[d];
-            while (cellsize*npulse[d] < comm->cutoff && npulse[d] < dd->nc[d]-1)
+            while (cellsize*npulse[d] < comm->cutoff)
             {
                 npulse[d]++;
             }
@@ -3079,7 +3141,7 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
              * all cell borders in a loop to obtain identical values
              * to the master distribution case and to determine npulse.
              */
-            if (bMaster)
+            if (setmode == setcellsizeslbMASTER)
             {
                 cell_x = dd->ma->cell_x[d];
             }
@@ -3100,10 +3162,13 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
                 }
                 cellsize_min[d] = min(cellsize_min[d], cellsize);
             }
-            if (!bMaster)
+            if (setmode == setcellsizeslbLOCAL)
             {
                 comm->cell_x0[d] = cell_x[dd->ci[d]];
                 comm->cell_x1[d] = cell_x[dd->ci[d]+1];
+            }
+            if (setmode != setcellsizeslbMASTER)
+            {
                 sfree(cell_x);
             }
         }
@@ -3114,12 +3179,23 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
         if (d < ddbox->npbcdim &&
             dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
         {
-            gmx_fatal_collective(FARGS, NULL, dd,
-                                 "The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
-                                 dim2char(d), ddbox->box_size[d], ddbox->skew_fac[d],
-                                 comm->cutoff,
-                                 dd->nc[d], dd->nc[d],
-                                 dd->nnodes > dd->nc[d] ? "cells" : "processors");
+            char error_string[STRLEN];
+
+            sprintf(error_string,
+                    "The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
+                    dim2char(d), ddbox->box_size[d], ddbox->skew_fac[d],
+                    comm->cutoff,
+                    dd->nc[d], dd->nc[d],
+                    dd->nnodes > dd->nc[d] ? "cells" : "ranks");
+
+            if (setmode == setcellsizeslbLOCAL)
+            {
+                gmx_fatal_collective(FARGS, NULL, dd, error_string);
+            }
+            else
+            {
+                gmx_fatal(FARGS, error_string);
+            }
         }
     }
 
@@ -3140,7 +3216,7 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
 static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
                                                   int d, int dim, gmx_domdec_root_t *root,
                                                   gmx_ddbox_t *ddbox,
-                                                  gmx_bool bUniform, gmx_large_int_t step, real cellsize_limit_f, int range[])
+                                                  gmx_bool bUniform, gmx_int64_t step, real cellsize_limit_f, int range[])
 {
     gmx_domdec_comm_t *comm;
     int                ncd, i, j, nmin, nmin_old;
@@ -3351,7 +3427,7 @@ static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
 static void set_dd_cell_sizes_dlb_root(gmx_domdec_t *dd,
                                        int d, int dim, gmx_domdec_root_t *root,
                                        gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
-                                       gmx_bool bUniform, gmx_large_int_t step)
+                                       gmx_bool bUniform, gmx_int64_t step)
 {
     gmx_domdec_comm_t *comm;
     int                ncd, d1, i, j, pos;
@@ -3576,7 +3652,7 @@ static void distribute_dd_cell_sizes_dlb(gmx_domdec_t *dd,
 
 static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
                                          gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
-                                         gmx_bool bUniform, gmx_large_int_t step)
+                                         gmx_bool bUniform, gmx_int64_t step)
 {
     gmx_domdec_comm_t *comm;
     int                d, dim, d1;
@@ -3594,7 +3670,7 @@ static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
         {
             if (dd->ci[dd->dim[d1]] > 0)
             {
-                if (d1 > d)
+                if (d1 != d)
                 {
                     bRowMember = FALSE;
                 }
@@ -3636,7 +3712,7 @@ static void set_dd_cell_sizes_dlb_nochange(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
 
 static void set_dd_cell_sizes_dlb(gmx_domdec_t *dd,
                                   gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
-                                  gmx_bool bUniform, gmx_bool bDoDLB, gmx_large_int_t step,
+                                  gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
                                   gmx_wallcycle_t wcycle)
 {
     gmx_domdec_comm_t *comm;
@@ -3706,7 +3782,7 @@ static void realloc_comm_ind(gmx_domdec_t *dd, ivec npulse)
 
 static void set_dd_cell_sizes(gmx_domdec_t *dd,
                               gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
-                              gmx_bool bUniform, gmx_bool bDoDLB, gmx_large_int_t step,
+                              gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
                               gmx_wallcycle_t wcycle)
 {
     gmx_domdec_comm_t *comm;
@@ -3729,7 +3805,7 @@ static void set_dd_cell_sizes(gmx_domdec_t *dd,
     }
     else
     {
-        set_dd_cell_sizes_slb(dd, ddbox, FALSE, npulse);
+        set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbLOCAL, npulse);
         realloc_comm_ind(dd, npulse);
     }
 
@@ -3746,7 +3822,7 @@ static void set_dd_cell_sizes(gmx_domdec_t *dd,
 static void comm_dd_ns_cell_sizes(gmx_domdec_t *dd,
                                   gmx_ddbox_t *ddbox,
                                   rvec cell_ns_x0, rvec cell_ns_x1,
-                                  gmx_large_int_t step)
+                                  gmx_int64_t step)
 {
     gmx_domdec_comm_t *comm;
     int                dim_ind, dim;
@@ -3822,7 +3898,7 @@ static void check_screw_box(matrix box)
     }
 }
 
-static void distribute_cg(FILE *fplog, gmx_large_int_t step,
+static void distribute_cg(FILE *fplog, gmx_int64_t step,
                           matrix box, ivec tric_dir, t_block *cgs, rvec pos[],
                           gmx_domdec_t *dd)
 {
@@ -3987,7 +4063,7 @@ static void distribute_cg(FILE *fplog, gmx_large_int_t step,
     }
 }
 
-static void get_cg_distribution(FILE *fplog, gmx_large_int_t step, gmx_domdec_t *dd,
+static void get_cg_distribution(FILE *fplog, gmx_int64_t step, gmx_domdec_t *dd,
                                 t_block *cgs, matrix box, gmx_ddbox_t *ddbox,
                                 rvec pos[])
 {
@@ -3996,6 +4072,7 @@ static void get_cg_distribution(FILE *fplog, gmx_large_int_t step, gmx_domdec_t
     int                  i, cg_gl;
     int                 *ibuf, buf2[2] = { 0, 0 };
     gmx_bool             bMaster = DDMASTER(dd);
+
     if (bMaster)
     {
         ma = dd->ma;
@@ -4005,7 +4082,7 @@ static void get_cg_distribution(FILE *fplog, gmx_large_int_t step, gmx_domdec_t
             check_screw_box(box);
         }
 
-        set_dd_cell_sizes_slb(dd, ddbox, TRUE, npulse);
+        set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbMASTER, npulse);
 
         distribute_cg(fplog, step, box, ddbox->tric_dir, cgs, pos, dd);
         for (i = 0; i < dd->nnodes; i++)
@@ -4255,8 +4332,8 @@ static void clear_and_mark_ind(int ncg, int *move,
 
 static void print_cg_move(FILE *fplog,
                           gmx_domdec_t *dd,
-                          gmx_large_int_t step, int cg, int dim, int dir,
-                          gmx_bool bHaveLimitdAndCMOld, real limitd,
+                          gmx_int64_t step, int cg, int dim, int dir,
+                          gmx_bool bHaveCgcmOld, real limitd,
                           rvec cm_old, rvec cm_new, real pos_d)
 {
     gmx_domdec_comm_t *comm;
@@ -4265,19 +4342,22 @@ static void print_cg_move(FILE *fplog,
     comm = dd->comm;
 
     fprintf(fplog, "\nStep %s:\n", gmx_step_str(step, buf));
-    if (bHaveLimitdAndCMOld)
+    if (limitd > 0)
     {
-        fprintf(fplog, "The charge group starting at atom %d moved more than the distance allowed by the domain decomposition (%f) in direction %c\n",
+        fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition (%f) in direction %c\n",
+                dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
                 ddglatnr(dd, dd->cgindex[cg]), limitd, dim2char(dim));
     }
     else
     {
-        fprintf(fplog, "The charge group starting at atom %d moved than the distance allowed by the domain decomposition in direction %c\n",
+        /* We don't have a limiting distance available: don't print it */
+        fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition in direction %c\n",
+                dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
                 ddglatnr(dd, dd->cgindex[cg]), dim2char(dim));
     }
     fprintf(fplog, "distance out of cell %f\n",
             dir == 1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
-    if (bHaveLimitdAndCMOld)
+    if (bHaveCgcmOld)
     {
         fprintf(fplog, "Old coordinates: %8.3f %8.3f %8.3f\n",
                 cm_old[XX], cm_old[YY], cm_old[ZZ]);
@@ -4294,20 +4374,21 @@ static void print_cg_move(FILE *fplog,
 
 static void cg_move_error(FILE *fplog,
                           gmx_domdec_t *dd,
-                          gmx_large_int_t step, int cg, int dim, int dir,
-                          gmx_bool bHaveLimitdAndCMOld, real limitd,
+                          gmx_int64_t step, int cg, int dim, int dir,
+                          gmx_bool bHaveCgcmOld, real limitd,
                           rvec cm_old, rvec cm_new, real pos_d)
 {
     if (fplog)
     {
         print_cg_move(fplog, dd, step, cg, dim, dir,
-                      bHaveLimitdAndCMOld, limitd, cm_old, cm_new, pos_d);
+                      bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
     }
     print_cg_move(stderr, dd, step, cg, dim, dir,
-                  bHaveLimitdAndCMOld, limitd, cm_old, cm_new, pos_d);
+                  bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
     gmx_fatal(FARGS,
-              "A charge group moved too far between two domain decomposition steps\n"
-              "This usually means that your system is not well equilibrated");
+              "%s moved too far between two domain decomposition steps\n"
+              "This usually means that your system is not well equilibrated",
+              dd->comm->bCGs ? "A charge group" : "An atom");
 }
 
 static void rotate_state_atom(t_state *state, int a)
@@ -4362,7 +4443,7 @@ static int *get_moved(gmx_domdec_comm_t *comm, int natoms)
     return comm->moved;
 }
 
-static void calc_cg_move(FILE *fplog, gmx_large_int_t step,
+static void calc_cg_move(FILE *fplog, gmx_int64_t step,
                          gmx_domdec_t *dd,
                          t_state *state,
                          ivec tric_dir, matrix tcm,
@@ -4429,7 +4510,8 @@ static void calc_cg_move(FILE *fplog, gmx_large_int_t step,
                 {
                     if (pos_d >= limit1[d])
                     {
-                        cg_move_error(fplog, dd, step, cg, d, 1, TRUE, limitd[d],
+                        cg_move_error(fplog, dd, step, cg, d, 1,
+                                      cg_cm != state->x, limitd[d],
                                       cg_cm[cg], cm_new, pos_d);
                     }
                     dev[d] = 1;
@@ -4455,7 +4537,8 @@ static void calc_cg_move(FILE *fplog, gmx_large_int_t step,
                 {
                     if (pos_d < limit0[d])
                     {
-                        cg_move_error(fplog, dd, step, cg, d, -1, TRUE, limitd[d],
+                        cg_move_error(fplog, dd, step, cg, d, -1,
+                                      cg_cm != state->x, limitd[d],
                                       cg_cm[cg], cm_new, pos_d);
                     }
                     dev[d] = -1;
@@ -4537,10 +4620,10 @@ static void calc_cg_move(FILE *fplog, gmx_large_int_t step,
     }
 }
 
-static void dd_redistribute_cg(FILE *fplog, gmx_large_int_t step,
+static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
                                gmx_domdec_t *dd, ivec tric_dir,
                                t_state *state, rvec **f,
-                               t_forcerec *fr, t_mdatoms *md,
+                               t_forcerec *fr,
                                gmx_bool bCompact,
                                t_nrnb *nrnb,
                                int *ncg_stay_home,
@@ -4873,7 +4956,7 @@ static void dd_redistribute_cg(FILE *fplog, gmx_large_int_t step,
                 {
                     cg_move_error(fplog, dd, step, cg, dim,
                                   (flag & DD_FLAG_FW(d)) ? 1 : 0,
-                                  FALSE, 0,
+                                  fr->cutoff_scheme == ecutsGROUP, 0,
                                   comm->vbuf.v[buf_pos],
                                   comm->vbuf.v[buf_pos],
                                   comm->vbuf.v[buf_pos][dim]);
@@ -5406,7 +5489,7 @@ static void print_dd_load_av(FILE *fplog, gmx_domdec_t *dd)
         fprintf(fplog, "\n");
         fprintf(stderr, "\n");
 
-        if (lossf >= DD_PERF_LOSS)
+        if (lossf >= DD_PERF_LOSS_WARN)
         {
             sprintf(buf,
                     "NOTE: %.1f %% of the available CPU time was lost due to load imbalance\n"
@@ -5422,12 +5505,12 @@ static void print_dd_load_av(FILE *fplog, gmx_domdec_t *dd)
             fprintf(fplog, "%s\n", buf);
             fprintf(stderr, "%s\n", buf);
         }
-        if (npme > 0 && fabs(lossp) >= DD_PERF_LOSS)
+        if (npme > 0 && fabs(lossp) >= DD_PERF_LOSS_WARN)
         {
             sprintf(buf,
-                    "NOTE: %.1f %% performance was lost because the PME nodes\n"
-                    "      had %s work to do than the PP nodes.\n"
-                    "      You might want to %s the number of PME nodes\n"
+                    "NOTE: %.1f %% performance was lost because the PME ranks\n"
+                    "      had %s work to do than the PP ranks.\n"
+                    "      You might want to %s the number of PME ranks\n"
                     "      or %s the cut-off and the grid spacing.\n",
                     fabs(lossp*100),
                     (lossp < 0) ? "less"     : "more",
@@ -5466,7 +5549,7 @@ float dd_pme_f_ratio(gmx_domdec_t *dd)
     }
 }
 
-static void dd_print_load(FILE *fplog, gmx_domdec_t *dd, gmx_large_int_t step)
+static void dd_print_load(FILE *fplog, gmx_domdec_t *dd, gmx_int64_t step)
 {
     int  flags, d;
     char buf[22];
@@ -5572,7 +5655,63 @@ static void make_load_communicator(gmx_domdec_t *dd, int dim_ind, ivec loc)
 }
 #endif
 
-static void make_load_communicators(gmx_domdec_t *dd)
+void dd_setup_dlb_resource_sharing(t_commrec           gmx_unused *cr,
+                                   const gmx_hw_info_t gmx_unused *hwinfo,
+                                   const gmx_hw_opt_t  gmx_unused *hw_opt)
+{
+#ifdef GMX_MPI
+    int           physicalnode_id_hash;
+    int           gpu_id;
+    gmx_domdec_t *dd;
+    MPI_Comm      mpi_comm_pp_physicalnode;
+
+    if (!(cr->duty & DUTY_PP) ||
+        hw_opt->gpu_opt.ncuda_dev_use == 0)
+    {
+        /* Only PP nodes (currently) use GPUs.
+         * If we don't have GPUs, there are no resources to share.
+         */
+        return;
+    }
+
+    physicalnode_id_hash = gmx_physicalnode_id_hash();
+
+    gpu_id = get_gpu_device_id(&hwinfo->gpu_info, &hw_opt->gpu_opt, cr->rank_pp_intranode);
+
+    dd = cr->dd;
+
+    if (debug)
+    {
+        fprintf(debug, "dd_setup_dd_dlb_gpu_sharing:\n");
+        fprintf(debug, "DD PP rank %d physical node hash %d gpu_id %d\n",
+                dd->rank, physicalnode_id_hash, gpu_id);
+    }
+    /* Split the PP communicator over the physical nodes */
+    /* TODO: See if we should store this (before), as it's also used for
+     * for the nodecomm summution.
+     */
+    MPI_Comm_split(dd->mpi_comm_all, physicalnode_id_hash, dd->rank,
+                   &mpi_comm_pp_physicalnode);
+    MPI_Comm_split(mpi_comm_pp_physicalnode, gpu_id, dd->rank,
+                   &dd->comm->mpi_comm_gpu_shared);
+    MPI_Comm_free(&mpi_comm_pp_physicalnode);
+    MPI_Comm_size(dd->comm->mpi_comm_gpu_shared, &dd->comm->nrank_gpu_shared);
+
+    if (debug)
+    {
+        fprintf(debug, "nrank_gpu_shared %d\n", dd->comm->nrank_gpu_shared);
+    }
+
+    /* Note that some ranks could share a GPU, while others don't */
+
+    if (dd->comm->nrank_gpu_shared == 1)
+    {
+        MPI_Comm_free(&dd->comm->mpi_comm_gpu_shared);
+    }
+#endif
+}
+
+static void make_load_communicators(gmx_domdec_t gmx_unused *dd)
 {
 #ifdef GMX_MPI
     int  dim0, dim1, i, j;
@@ -5777,7 +5916,7 @@ void setup_dd_grid(FILE *fplog, gmx_domdec_t *dd)
     }
 }
 
-static void make_pp_communicator(FILE *fplog, t_commrec *cr, int reorder)
+static void make_pp_communicator(FILE *fplog, t_commrec *cr, int gmx_unused reorder)
 {
     gmx_domdec_t      *dd;
     gmx_domdec_comm_t *comm;
@@ -5891,13 +6030,13 @@ static void make_pp_communicator(FILE *fplog, t_commrec *cr, int reorder)
     if (fplog)
     {
         fprintf(fplog,
-                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
+                "Domain decomposition rank %d, coordinates %d %d %d\n\n",
                 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
     }
     if (debug)
     {
         fprintf(debug,
-                "Domain decomposition nodeid %d, coordinates %d %d %d\n\n",
+                "Domain decomposition rank %d, coordinates %d %d %d\n\n",
                 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
     }
 }
@@ -5962,8 +6101,8 @@ static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
     return ma;
 }
 
-static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
-                               int reorder)
+static void split_communicator(FILE *fplog, t_commrec *cr, int gmx_unused dd_node_order,
+                               int gmx_unused reorder)
 {
     gmx_domdec_t      *dd;
     gmx_domdec_comm_t *comm;
@@ -6008,7 +6147,7 @@ static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
         }
         else if (fplog)
         {
-            fprintf(fplog, "#pmenodes (%d) is not a multiple of nx*ny (%d*%d) or nx*nz (%d*%d)\n", cr->npmenodes, dd->nc[XX], dd->nc[YY], dd->nc[XX], dd->nc[ZZ]);
+            fprintf(fplog, "Number of PME-only ranks (%d) is not a multiple of nx*ny (%d*%d) or nx*nz (%d*%d)\n", cr->npmenodes, dd->nc[XX], dd->nc[YY], dd->nc[XX], dd->nc[ZZ]);
             fprintf(fplog,
                     "Will not use a Cartesian communicator for PP <-> PME\n\n");
         }
@@ -6045,7 +6184,7 @@ static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
 
         if (fplog)
         {
-            fprintf(fplog, "Cartesian nodeid %d, coordinates %d %d %d\n\n",
+            fprintf(fplog, "Cartesian rank %d, coordinates %d %d %d\n\n",
                     cr->sim_nodeid, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
         }
 
@@ -6072,7 +6211,7 @@ static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
             case ddnoPP_PME:
                 if (fplog)
                 {
-                    fprintf(fplog, "Order of the nodes: PP first, PME last\n");
+                    fprintf(fplog, "Order of the ranks: PP first, PME last\n");
                 }
                 break;
             case ddnoINTERLEAVE:
@@ -6083,7 +6222,7 @@ static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
                  */
                 if (fplog)
                 {
-                    fprintf(fplog, "Interleaving PP and PME nodes\n");
+                    fprintf(fplog, "Interleaving PP and PME ranks\n");
                 }
                 comm->pmenodes = dd_pmenodes(cr);
                 break;
@@ -6113,7 +6252,7 @@ static void split_communicator(FILE *fplog, t_commrec *cr, int dd_node_order,
 
     if (fplog)
     {
-        fprintf(fplog, "This is a %s only node\n\n",
+        fprintf(fplog, "This rank does only %s work.\n\n",
                 (cr->duty & DUTY_PP) ? "particle-particle" : "PME-mesh");
     }
 }
@@ -6266,7 +6405,7 @@ static int multi_body_bondeds_count(gmx_mtop_t *mtop)
     return n;
 }
 
-static int dd_nst_env(FILE *fplog, const char *env_var, int def)
+static int dd_getenv(FILE *fplog, const char *env_var, int def)
 {
     char *val;
     int   nst;
@@ -6312,7 +6451,7 @@ static void check_dd_restrictions(t_commrec *cr, gmx_domdec_t *dd,
 
     if (ir->ns_type == ensSIMPLE)
     {
-        gmx_fatal(FARGS, "Domain decomposition does not support simple neighbor searching, use grid searching or use particle decomposition");
+        gmx_fatal(FARGS, "Domain decomposition does not support simple neighbor searching, use grid searching or run with one MPI rank");
     }
 
     if (ir->nstlist == 0)
@@ -6496,7 +6635,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
     if (fplog)
     {
         fprintf(fplog,
-                "\nInitializing Domain Decomposition on %d nodes\n", cr->nnodes);
+                "\nInitializing Domain Decomposition on %d ranks\n", cr->nnodes);
     }
 
     snew(dd, 1);
@@ -6509,14 +6648,14 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
     dd->npbcdim   = ePBC2npbcdim(ir->ePBC);
     dd->bScrewPBC = (ir->ePBC == epbcSCREW);
 
-    dd->bSendRecv2      = dd_nst_env(fplog, "GMX_DD_SENDRECV2", 0);
-    comm->dlb_scale_lim = dd_nst_env(fplog, "GMX_DLB_MAX", 10);
-    comm->eFlop         = dd_nst_env(fplog, "GMX_DLB_FLOP", 0);
-    recload             = dd_nst_env(fplog, "GMX_DD_LOAD", 1);
-    comm->nstSortCG     = dd_nst_env(fplog, "GMX_DD_SORT", 1);
-    comm->nstDDDump     = dd_nst_env(fplog, "GMX_DD_DUMP", 0);
-    comm->nstDDDumpGrid = dd_nst_env(fplog, "GMX_DD_DUMP_GRID", 0);
-    comm->DD_debug      = dd_nst_env(fplog, "GMX_DD_DEBUG", 0);
+    dd->bSendRecv2      = dd_getenv(fplog, "GMX_DD_USE_SENDRECV2", 0);
+    comm->dlb_scale_lim = dd_getenv(fplog, "GMX_DLB_MAX_BOX_SCALING", 10);
+    comm->eFlop         = dd_getenv(fplog, "GMX_DLB_BASED_ON_FLOPS", 0);
+    recload             = dd_getenv(fplog, "GMX_DD_RECORD_LOAD", 1);
+    comm->nstSortCG     = dd_getenv(fplog, "GMX_DD_NST_SORT_CHARGE_GROUPS", 1);
+    comm->nstDDDump     = dd_getenv(fplog, "GMX_DD_NST_DUMP", 0);
+    comm->nstDDDumpGrid = dd_getenv(fplog, "GMX_DD_NST_DUMP_GRID", 0);
+    comm->DD_debug      = dd_getenv(fplog, "GMX_DD_DEBUG", 0);
 
     dd->pme_recv_f_alloc = 0;
     dd->pme_recv_f_buf   = NULL;
@@ -6543,6 +6682,9 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
 
     }
 
+    /* Initialize to GPU share count to 0, might change later */
+    comm->nrank_gpu_shared = 0;
+
     comm->eDLB = check_dlb_support(fplog, cr, dlb_opt, comm->bRecordLoad, Flags, ir);
 
     comm->bDynLoadBal = (comm->eDLB == edlbYES);
@@ -6609,6 +6751,13 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
     comm->cellsize_limit = 0;
     comm->bBondComm      = FALSE;
 
+    /* Atoms should be able to move by up to half the list buffer size (if > 0)
+     * within nstlist steps. Since boundaries are allowed to displace by half
+     * a cell size, DD cells should be at least the size of the list buffer.
+     */
+    comm->cellsize_limit = max(comm->cellsize_limit,
+                               ir->rlistlong - max(ir->rvdw, ir->rcoulomb));
+
     if (comm->bInterCGBondeds)
     {
         if (comm_distance_min > 0)
@@ -6635,7 +6784,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
         {
             if (MASTER(cr))
             {
-                dd_bonded_cg_distance(fplog, dd, mtop, ir, x, box,
+                dd_bonded_cg_distance(fplog, mtop, ir, x, box,
                                       Flags & MD_DDBONDCHECK, &r_2b, &r_mb);
             }
             gmx_bcast(sizeof(r_2b), &r_2b, cr);
@@ -6737,18 +6886,18 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
         limit = dd_choose_grid(fplog, cr, dd, ir, mtop, box, ddbox,
                                comm->eDLB != edlbNO, dlb_scale,
                                comm->cellsize_limit, comm->cutoff,
-                               comm->bInterCGBondeds, comm->bInterCGMultiBody);
+                               comm->bInterCGBondeds);
 
         if (dd->nc[XX] == 0)
         {
             bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
-            sprintf(buf, "Change the number of nodes or mdrun option %s%s%s",
+            sprintf(buf, "Change the number of ranks or mdrun option %s%s%s",
                     !bC ? "-rdd" : "-rcon",
                     comm->eDLB != edlbNO ? " or -dds" : "",
                     bC ? " or your LINCS settings" : "");
 
             gmx_fatal_collective(FARGS, cr, NULL,
-                                 "There is no domain decomposition for %d nodes that is compatible with the given box and a minimum cell size of %g nm\n"
+                                 "There is no domain decomposition for %d ranks that is compatible with the given box and a minimum cell size of %g nm\n"
                                  "%s\n"
                                  "Look in the log file for details on the domain decomposition",
                                  cr->nnodes-cr->npmenodes, limit, buf);
@@ -6759,7 +6908,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
     if (fplog)
     {
         fprintf(fplog,
-                "Domain decomposition grid %d x %d x %d, separate PME nodes %d\n",
+                "Domain decomposition grid %d x %d x %d, separate PME ranks %d\n",
                 dd->nc[XX], dd->nc[YY], dd->nc[ZZ], cr->npmenodes);
     }
 
@@ -6767,13 +6916,13 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
     if (cr->nnodes - dd->nnodes != cr->npmenodes)
     {
         gmx_fatal_collective(FARGS, cr, NULL,
-                             "The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
+                             "The size of the domain decomposition grid (%d) does not match the number of ranks (%d). The total number of ranks is %d",
                              dd->nnodes, cr->nnodes - cr->npmenodes, cr->nnodes);
     }
     if (cr->npmenodes > dd->nnodes)
     {
         gmx_fatal_collective(FARGS, cr, NULL,
-                             "The number of separate PME nodes (%d) is larger than the number of PP nodes (%d), this is not supported.", cr->npmenodes, dd->nnodes);
+                             "The number of separate PME ranks (%d) is larger than the number of PP ranks (%d), this is not supported.", cr->npmenodes, dd->nnodes);
     }
     if (cr->npmenodes > 0)
     {
@@ -6784,7 +6933,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
         comm->npmenodes = dd->nnodes;
     }
 
-    if (EEL_PME(ir->coulombtype))
+    if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
     {
         /* The following choices should match those
          * in comm_cost_est in domdec_setup.c.
@@ -6920,7 +7069,7 @@ static void set_dlb_limits(gmx_domdec_t *dd)
 }
 
 
-static void turn_on_dlb(FILE *fplog, t_commrec *cr, gmx_large_int_t step)
+static void turn_on_dlb(FILE *fplog, t_commrec *cr, gmx_int64_t step)
 {
     gmx_domdec_t      *dd;
     gmx_domdec_comm_t *comm;
@@ -7000,14 +7149,14 @@ static char *init_bLocalCG(gmx_mtop_t *mtop)
 
 void dd_init_bondeds(FILE *fplog,
                      gmx_domdec_t *dd, gmx_mtop_t *mtop,
-                     gmx_vsite_t *vsite, gmx_constr_t constr,
+                     gmx_vsite_t *vsite,
                      t_inputrec *ir, gmx_bool bBCheck, cginfo_mb_t *cginfo_mb)
 {
     gmx_domdec_comm_t *comm;
     gmx_bool           bBondComm;
     int                d;
 
-    dd_make_reverse_top(fplog, dd, mtop, vsite, constr, ir, bBCheck);
+    dd_make_reverse_top(fplog, dd, mtop, vsite, ir, bBCheck);
 
     comm = dd->comm;
 
@@ -7078,7 +7227,7 @@ static void print_dd_settings(FILE *fplog, gmx_domdec_t *dd,
     }
     else
     {
-        set_dd_cell_sizes_slb(dd, ddbox, FALSE, np);
+        set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbPULSE_ONLY, np);
         fprintf(fplog, "The initial number of communication pulses is:");
         for (d = 0; d < dd->ndim; d++)
         {
@@ -7201,7 +7350,7 @@ static void set_cell_limits_dlb(gmx_domdec_t      *dd,
     }
 
     /* This env var can override npulse */
-    d = dd_nst_env(debug, "GMX_DD_NPULSE", 0);
+    d = dd_getenv(debug, "GMX_DD_NPULSE", 0);
     if (d > 0)
     {
         npulse = d;
@@ -7265,8 +7414,7 @@ gmx_bool dd_bonded_molpbc(gmx_domdec_t *dd, int ePBC)
 }
 
 void set_dd_parameters(FILE *fplog, gmx_domdec_t *dd, real dlb_scale,
-                       t_inputrec *ir, t_forcerec *fr,
-                       gmx_ddbox_t *ddbox)
+                       t_inputrec *ir, gmx_ddbox_t *ddbox)
 {
     gmx_domdec_comm_t *comm;
     int                natoms_tot;
@@ -7284,7 +7432,7 @@ void set_dd_parameters(FILE *fplog, gmx_domdec_t *dd, real dlb_scale,
         snew(comm->dth, comm->nth);
     }
 
-    if (EEL_PME(ir->coulombtype))
+    if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
     {
         init_ddpme(dd, &comm->ddpme[0], 0);
         if (comm->npmedecompdim >= 2)
@@ -7298,7 +7446,7 @@ void set_dd_parameters(FILE *fplog, gmx_domdec_t *dd, real dlb_scale,
         if (dd->pme_nodeid >= 0)
         {
             gmx_fatal_collective(FARGS, NULL, dd,
-                                 "Can not have separate PME nodes without PME electrostatics");
+                                 "Can not have separate PME ranks without PME electrostatics");
         }
     }
 
@@ -8584,6 +8732,7 @@ static void set_zones_size(gmx_domdec_t *dd,
                 corner[YY] -= corner[ZZ]*box[ZZ][YY]/box[ZZ][ZZ];
             }
             /* Apply the triclinic couplings */
+            assert(ddbox->npbcdim <= DIM);
             for (i = YY; i < ddbox->npbcdim; i++)
             {
                 for (j = XX; j < i; j++)
@@ -8738,7 +8887,7 @@ static void ordered_sort(int nsort2, gmx_cgsort_t *sort2,
     int i1, i2, i_new;
 
     /* The new indices are not very ordered, so we qsort them */
-    qsort_threadsafe(sort_new, nsort_new, sizeof(sort_new[0]), comp_cgsort);
+    gmx_qsort_threadsafe(sort_new, nsort_new, sizeof(sort_new[0]), comp_cgsort);
 
     /* sort2 is already ordered, so now we can merge the two arrays */
     i1    = 0;
@@ -8851,7 +9000,7 @@ static int dd_sort_order(gmx_domdec_t *dd, t_forcerec *fr, int ncg_home_old)
             fprintf(debug, "qsort cgs: %d new home %d\n", dd->ncg_home, ncg_new);
         }
         /* Determine the order of the charge groups using qsort */
-        qsort_threadsafe(cgsort, dd->ncg_home, sizeof(cgsort[0]), comp_cgsort);
+        gmx_qsort_threadsafe(cgsort, dd->ncg_home, sizeof(cgsort[0]), comp_cgsort);
     }
 
     return ncg_new;
@@ -8879,8 +9028,7 @@ static int dd_sort_order_nbnxn(gmx_domdec_t *dd, t_forcerec *fr)
     return ncg_new;
 }
 
-static void dd_sort_state(gmx_domdec_t *dd, int ePBC,
-                          rvec *cgcm, t_forcerec *fr, t_state *state,
+static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state *state,
                           int ncg_home_old)
 {
     gmx_domdec_sort_t *sort;
@@ -9116,7 +9264,7 @@ void print_dd_statistics(t_commrec *cr, t_inputrec *ir, FILE *fplog)
 }
 
 void dd_partition_system(FILE                *fplog,
-                         gmx_large_int_t      step,
+                         gmx_int64_t          step,
                          t_commrec           *cr,
                          gmx_bool             bMasterState,
                          int                  nstglobalcomm,
@@ -9139,9 +9287,9 @@ void dd_partition_system(FILE                *fplog,
     gmx_domdec_comm_t *comm;
     gmx_ddbox_t        ddbox = {0};
     t_block           *cgs_gl;
-    gmx_large_int_t    step_pcoupl;
+    gmx_int64_t        step_pcoupl;
     rvec               cell_ns_x0, cell_ns_x1;
-    int                i, j, n, cg0 = 0, ncg_home_old = -1, ncg_moved, nat_f_novirsum;
+    int                i, j, n, ncgindex_set, ncg_home_old = -1, ncg_moved, nat_f_novirsum;
     gmx_bool           bBoxChanged, bNStGlobalComm, bDoDLB, bCheckDLB, bTurnOnDLB, bLogLoad;
     gmx_bool           bRedist, bSortCG, bResortAll;
     ivec               ncells_old = {0, 0, 0}, ncells_new = {0, 0, 0}, np;
@@ -9250,7 +9398,7 @@ void dd_partition_system(FILE                *fplog,
                 if (DDMASTER(dd))
                 {
                     bTurnOnDLB =
-                        (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS);
+                        (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS_DLB_ON);
                     if (debug)
                     {
                         fprintf(debug, "step %s, imb loss %f\n",
@@ -9276,6 +9424,7 @@ void dd_partition_system(FILE                *fplog,
     {
         /* Clear the old state */
         clear_dd_indices(dd, 0, 0);
+        ncgindex_set = 0;
 
         set_ddbox(dd, bMasterState, cr, ir, state_global->box,
                   TRUE, cgs_gl, state_global->x, &ddbox);
@@ -9300,8 +9449,6 @@ void dd_partition_system(FILE                *fplog,
         inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
 
         dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
-
-        cg0 = 0;
     }
     else if (state_local->ddp_count != dd->ddp_count)
     {
@@ -9321,6 +9468,7 @@ void dd_partition_system(FILE                *fplog,
         /* Build the new indices */
         rebuild_cgindex(dd, cgs_gl->index, state_local);
         make_dd_indices(dd, cgs_gl->index, 0);
+        ncgindex_set = dd->ncg_home;
 
         if (fr->cutoff_scheme == ecutsGROUP)
         {
@@ -9344,6 +9492,7 @@ void dd_partition_system(FILE                *fplog,
 
         /* Clear the non-home indices */
         clear_dd_indices(dd, dd->ncg_home, dd->nat_home);
+        ncgindex_set = 0;
 
         /* Avoid global communication for dim's without pbc and -gcom */
         if (!bNStGlobalComm)
@@ -9388,8 +9537,8 @@ void dd_partition_system(FILE                *fplog,
         wallcycle_sub_start(wcycle, ewcsDD_REDIST);
 
         dd_redistribute_cg(fplog, step, dd, ddbox.tric_dir,
-                           state_local, f, fr, mdatoms,
-                           !bSortCG, nrnb, &cg0, &ncg_moved);
+                           state_local, f, fr,
+                           !bSortCG, nrnb, &ncgindex_set, &ncg_moved);
 
         wallcycle_sub_stop(wcycle, ewcsDD_REDIST);
     }
@@ -9409,7 +9558,7 @@ void dd_partition_system(FILE                *fplog,
     {
         case ecutsGROUP:
             copy_ivec(fr->ns.grid->n, ncells_old);
-            grid_first(fplog, fr->ns.grid, dd, &ddbox, fr->ePBC,
+            grid_first(fplog, fr->ns.grid, dd, &ddbox,
                        state_local->box, cell_ns_x0, cell_ns_x1,
                        fr->rlistlong, grid_density);
             break;
@@ -9457,7 +9606,7 @@ void dd_partition_system(FILE                *fplog,
                 nbnxn_get_ncells(fr->nbv->nbs, &ncells_new[XX], &ncells_new[YY]);
                 break;
             case ecutsGROUP:
-                fill_grid(fplog, &comm->zones, fr->ns.grid, dd->ncg_home,
+                fill_grid(&comm->zones, fr->ns.grid, dd->ncg_home,
                           0, dd->ncg_home, fr->cg_cm);
 
                 copy_ivec(fr->ns.grid->n, ncells_new);
@@ -9483,11 +9632,11 @@ void dd_partition_system(FILE                *fplog,
             fprintf(debug, "Step %s, sorting the %d home charge groups\n",
                     gmx_step_str(step, sbuf), dd->ncg_home);
         }
-        dd_sort_state(dd, ir->ePBC, fr->cg_cm, fr, state_local,
+        dd_sort_state(dd, fr->cg_cm, fr, state_local,
                       bResortAll ? -1 : ncg_home_old);
         /* Rebuild all the indices */
-        cg0 = 0;
         ga2la_clear(dd->ga2la);
+        ncgindex_set = 0;
 
         wallcycle_sub_stop(wcycle, ewcsDD_GRID);
     }
@@ -9498,7 +9647,7 @@ void dd_partition_system(FILE                *fplog,
     setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local, f);
 
     /* Set the indices */
-    make_dd_indices(dd, cgs_gl->index, cg0);
+    make_dd_indices(dd, cgs_gl->index, ncgindex_set);
 
     /* Set the charge group boundaries for neighbor searching */
     set_cg_boundaries(&comm->zones);
@@ -9523,7 +9672,7 @@ void dd_partition_system(FILE                *fplog,
     {
         np[dd->dim[i]] = comm->cd[i].np;
     }
-    dd_make_local_top(fplog, dd, &comm->zones, dd->npbcdim, state_local->box,
+    dd_make_local_top(dd, &comm->zones, dd->npbcdim, state_local->box,
                       comm->cellsize_min, np,
                       fr,
                       fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : state_local->x,
@@ -9611,7 +9760,7 @@ void dd_partition_system(FILE                *fplog,
      */
     /* This call also sets the new number of home particles to dd->nat_home */
     atoms2md(top_global, ir,
-             comm->nat[ddnatCON], dd->gatindex, 0, dd->nat_home, mdatoms);
+             comm->nat[ddnatCON], dd->gatindex, dd->nat_home, mdatoms);
 
     /* Now we have the charges we can sort the FE interactions */
     dd_sort_local_top(dd, mdatoms, top_local);
@@ -9619,7 +9768,8 @@ void dd_partition_system(FILE                *fplog,
     if (vsite != NULL)
     {
         /* Now we have updated mdatoms, we can do the last vsite bookkeeping */
-        split_vsites_over_threads(top_local->idef.il, mdatoms, FALSE, vsite);
+        split_vsites_over_threads(top_local->idef.il, top_local->idef.iparams,
+                                  mdatoms, FALSE, vsite);
     }
 
     if (shellfc)
@@ -9633,14 +9783,18 @@ void dd_partition_system(FILE                *fplog,
         make_local_gb(cr, fr->born, ir->gb_algorithm);
     }
 
-    init_bonded_thread_force_reduction(fr, &top_local->idef);
+    setup_bonded_threading(fr, &top_local->idef);
 
     if (!(cr->duty & DUTY_PME))
     {
-        /* Send the charges to our PME only node */
-        gmx_pme_send_q(cr, mdatoms->nChargePerturbed,
-                       mdatoms->chargeA, mdatoms->chargeB,
-                       dd_pme_maxshift_x(dd), dd_pme_maxshift_y(dd));
+        /* Send the charges and/or c6/sigmas to our PME only node */
+        gmx_pme_send_parameters(cr,
+                                fr->ic,
+                                mdatoms->nChargePerturbed, mdatoms->nTypePerturbed,
+                                mdatoms->chargeA, mdatoms->chargeB,
+                                mdatoms->sqrt_c6A, mdatoms->sqrt_c6B,
+                                mdatoms->sigmaA, mdatoms->sigmaB,
+                                dd_pme_maxshift_x(dd), dd_pme_maxshift_y(dd));
     }
 
     if (constr)
@@ -9660,6 +9814,14 @@ void dd_partition_system(FILE                *fplog,
         dd_make_local_rotation_groups(dd, ir->rot);
     }
 
+    if (ir->eSwapCoords != eswapNO)
+    {
+        /* Update the local groups needed for ion swapping */
+        dd_make_local_swap_groups(dd, ir->swap);
+    }
+
+    /* Update the local atoms to be communicated via the IMD protocol if bIMD is TRUE. */
+    dd_make_local_IMD_atoms(ir->bIMD, dd, ir->imd);
 
     add_dd_statistics(dd);