Update to prepare for 2018.4 point release
[alexxy/gromacs.git] / src / gromacs / domdec / domdec.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35
36 #include "gmxpre.h"
37
38 #include "domdec.h"
39
40 #include "config.h"
41
42 #include <assert.h>
43 #include <limits.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include <cmath>
49
50 #include <algorithm>
51
52 #include "gromacs/domdec/domdec_network.h"
53 #include "gromacs/domdec/ga2la.h"
54 #include "gromacs/ewald/pme.h"
55 #include "gromacs/fileio/gmxfio.h"
56 #include "gromacs/fileio/pdbio.h"
57 #include "gromacs/gmxlib/chargegroup.h"
58 #include "gromacs/gmxlib/network.h"
59 #include "gromacs/gmxlib/nrnb.h"
60 #include "gromacs/gpu_utils/gpu_utils.h"
61 #include "gromacs/hardware/hw_info.h"
62 #include "gromacs/imd/imd.h"
63 #include "gromacs/listed-forces/manage-threading.h"
64 #include "gromacs/math/functions.h"
65 #include "gromacs/math/vec.h"
66 #include "gromacs/math/vectypes.h"
67 #include "gromacs/mdlib/calc_verletbuf.h"
68 #include "gromacs/mdlib/constr.h"
69 #include "gromacs/mdlib/force.h"
70 #include "gromacs/mdlib/forcerec.h"
71 #include "gromacs/mdlib/genborn.h"
72 #include "gromacs/mdlib/gmx_omp_nthreads.h"
73 #include "gromacs/mdlib/mdatoms.h"
74 #include "gromacs/mdlib/mdrun.h"
75 #include "gromacs/mdlib/mdsetup.h"
76 #include "gromacs/mdlib/nb_verlet.h"
77 #include "gromacs/mdlib/nbnxn_grid.h"
78 #include "gromacs/mdlib/nsgrid.h"
79 #include "gromacs/mdlib/vsite.h"
80 #include "gromacs/mdtypes/commrec.h"
81 #include "gromacs/mdtypes/df_history.h"
82 #include "gromacs/mdtypes/forcerec.h"
83 #include "gromacs/mdtypes/inputrec.h"
84 #include "gromacs/mdtypes/md_enums.h"
85 #include "gromacs/mdtypes/mdatom.h"
86 #include "gromacs/mdtypes/nblist.h"
87 #include "gromacs/mdtypes/state.h"
88 #include "gromacs/pbcutil/ishift.h"
89 #include "gromacs/pbcutil/pbc.h"
90 #include "gromacs/pulling/pull.h"
91 #include "gromacs/pulling/pull_rotation.h"
92 #include "gromacs/swap/swapcoords.h"
93 #include "gromacs/timing/wallcycle.h"
94 #include "gromacs/topology/block.h"
95 #include "gromacs/topology/idef.h"
96 #include "gromacs/topology/ifunc.h"
97 #include "gromacs/topology/mtop_lookup.h"
98 #include "gromacs/topology/mtop_util.h"
99 #include "gromacs/topology/topology.h"
100 #include "gromacs/utility/basedefinitions.h"
101 #include "gromacs/utility/basenetwork.h"
102 #include "gromacs/utility/cstringutil.h"
103 #include "gromacs/utility/exceptions.h"
104 #include "gromacs/utility/fatalerror.h"
105 #include "gromacs/utility/gmxmpi.h"
106 #include "gromacs/utility/qsort_threadsafe.h"
107 #include "gromacs/utility/real.h"
108 #include "gromacs/utility/smalloc.h"
109 #include "gromacs/utility/stringutil.h"
110
111 #include "domdec_constraints.h"
112 #include "domdec_internal.h"
113 #include "domdec_vsite.h"
114
115 #define DDRANK(dd, rank)    (rank)
116 #define DDMASTERRANK(dd)   (dd->masterrank)
117
118 struct gmx_domdec_master_t
119 {
120     /* The cell boundaries */
121     real **cell_x;
122     /* The global charge group division */
123     int   *ncg;    /* Number of home charge groups for each node */
124     int   *index;  /* Index of nnodes+1 into cg */
125     int   *cg;     /* Global charge group index */
126     int   *nat;    /* Number of home atoms for each node. */
127     int   *ibuf;   /* Buffer for communication */
128     rvec  *vbuf;   /* Buffer for state scattering and gathering */
129 };
130
131 #define DD_NLOAD_MAX 9
132
133 const char *edlbs_names[edlbsNR] = { "off", "auto", "locked", "on", "on" };
134
135 /* The size per charge group of the cggl_flag buffer in gmx_domdec_comm_t */
136 #define DD_CGIBS 2
137
138 /* The flags for the cggl_flag buffer in gmx_domdec_comm_t */
139 #define DD_FLAG_NRCG  65535
140 #define DD_FLAG_FW(d) (1<<(16+(d)*2))
141 #define DD_FLAG_BW(d) (1<<(16+(d)*2+1))
142
143 /* The DD zone order */
144 static const ivec dd_zo[DD_MAXZONE] =
145 {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 1, 1}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}};
146
147 /* The non-bonded zone-pair setup for domain decomposition
148  * The first number is the i-zone, the second number the first j-zone seen by
149  * this i-zone, the third number the last+1 j-zone seen by this i-zone.
150  * As is, this is for 3D decomposition, where there are 4 i-zones.
151  * With 2D decomposition use only the first 2 i-zones and a last+1 j-zone of 4.
152  * With 1D decomposition use only the first i-zone and a last+1 j-zone of 2.
153  */
154 static const int
155     ddNonbondedZonePairRanges[DD_MAXIZONE][3] = {{0, 0, 8},
156                                                  {1, 3, 6},
157                                                  {2, 5, 6},
158                                                  {3, 5, 7}};
159
160 /* Factors used to avoid problems due to rounding issues */
161 #define DD_CELL_MARGIN       1.0001
162 #define DD_CELL_MARGIN2      1.00005
163 /* Factor to account for pressure scaling during nstlist steps */
164 #define DD_PRES_SCALE_MARGIN 1.02
165
166 /* Turn on DLB when the load imbalance causes this amount of total loss.
167  * There is a bit of overhead with DLB and it's difficult to achieve
168  * a load imbalance of less than 2% with DLB.
169  */
170 #define DD_PERF_LOSS_DLB_ON  0.02
171
172 /* Warn about imbalance due to PP or PP/PME load imbalance at this loss */
173 #define DD_PERF_LOSS_WARN    0.05
174
175 #define DD_CELL_F_SIZE(dd, di) ((dd)->nc[(dd)->dim[(di)]]+1+(di)*2+1+(di))
176
177 /* Use separate MPI send and receive commands
178  * when nnodes <= GMX_DD_NNODES_SENDRECV.
179  * This saves memory (and some copying for small nnodes).
180  * For high parallelization scatter and gather calls are used.
181  */
182 #define GMX_DD_NNODES_SENDRECV 4
183
184
185 /* We check if to turn on DLB at the first and every 100 DD partitionings.
186  * With large imbalance DLB will turn on at the first step, so we can
187  * make the interval so large that the MPI overhead of the check is negligible.
188  */
189 static const int c_checkTurnDlbOnInterval  = 100;
190 /* We need to check if DLB results in worse performance and then turn it off.
191  * We check this more often then for turning DLB on, because the DLB can scale
192  * the domains very rapidly, so if unlucky the load imbalance can go up quickly
193  * and furthermore, we are already synchronizing often with DLB, so
194  * the overhead of the MPI Bcast is not that high.
195  */
196 static const int c_checkTurnDlbOffInterval =  20;
197
198 /* Forward declaration */
199 static void dd_dlb_set_should_check_whether_to_turn_dlb_on(gmx_domdec_t *dd, gmx_bool bValue);
200
201
202 /*
203    #define dd_index(n,i) ((((i)[ZZ]*(n)[YY] + (i)[YY])*(n)[XX]) + (i)[XX])
204
205    static void index2xyz(ivec nc,int ind,ivec xyz)
206    {
207    xyz[XX] = ind % nc[XX];
208    xyz[YY] = (ind / nc[XX]) % nc[YY];
209    xyz[ZZ] = ind / (nc[YY]*nc[XX]);
210    }
211  */
212
213 /* This order is required to minimize the coordinate communication in PME
214  * which uses decomposition in the x direction.
215  */
216 #define dd_index(n, i) ((((i)[XX]*(n)[YY] + (i)[YY])*(n)[ZZ]) + (i)[ZZ])
217
218 static void ddindex2xyz(ivec nc, int ind, ivec xyz)
219 {
220     xyz[XX] = ind / (nc[YY]*nc[ZZ]);
221     xyz[YY] = (ind / nc[ZZ]) % nc[YY];
222     xyz[ZZ] = ind % nc[ZZ];
223 }
224
225 static int ddcoord2ddnodeid(gmx_domdec_t *dd, ivec c)
226 {
227     int ddindex;
228     int ddnodeid = -1;
229
230     ddindex = dd_index(dd->nc, c);
231     if (dd->comm->bCartesianPP_PME)
232     {
233         ddnodeid = dd->comm->ddindex2ddnodeid[ddindex];
234     }
235     else if (dd->comm->bCartesianPP)
236     {
237 #if GMX_MPI
238         MPI_Cart_rank(dd->mpi_comm_all, c, &ddnodeid);
239 #endif
240     }
241     else
242     {
243         ddnodeid = ddindex;
244     }
245
246     return ddnodeid;
247 }
248
249 static gmx_bool dynamic_dd_box(const gmx_ddbox_t *ddbox, const t_inputrec *ir)
250 {
251     return (ddbox->nboundeddim < DIM || inputrecDynamicBox(ir));
252 }
253
254 int ddglatnr(const gmx_domdec_t *dd, int i)
255 {
256     int atnr;
257
258     if (dd == nullptr)
259     {
260         atnr = i + 1;
261     }
262     else
263     {
264         if (i >= dd->comm->nat[ddnatNR-1])
265         {
266             gmx_fatal(FARGS, "glatnr called with %d, which is larger than the local number of atoms (%d)", i, dd->comm->nat[ddnatNR-1]);
267         }
268         atnr = dd->gatindex[i] + 1;
269     }
270
271     return atnr;
272 }
273
274 t_block *dd_charge_groups_global(gmx_domdec_t *dd)
275 {
276     return &dd->comm->cgs_gl;
277 }
278
279 /*! \brief Returns true if the DLB state indicates that the balancer is on. */
280 static bool isDlbOn(const gmx_domdec_comm_t *comm)
281 {
282     return (comm->dlbState == edlbsOnCanTurnOff ||
283             comm->dlbState == edlbsOnUser);
284 }
285 /*! \brief Returns true if the DLB state indicates that the balancer is off/disabled.
286  */
287 static bool isDlbDisabled(const gmx_domdec_comm_t *comm)
288 {
289     return (comm->dlbState == edlbsOffUser ||
290             comm->dlbState == edlbsOffForever);
291 }
292
293 static void vec_rvec_init(vec_rvec_t *v)
294 {
295     v->nalloc = 0;
296     v->v      = nullptr;
297 }
298
299 static void vec_rvec_check_alloc(vec_rvec_t *v, int n)
300 {
301     if (n > v->nalloc)
302     {
303         v->nalloc = over_alloc_dd(n);
304         srenew(v->v, v->nalloc);
305     }
306 }
307
308 void dd_store_state(gmx_domdec_t *dd, t_state *state)
309 {
310     int i;
311
312     if (state->ddp_count != dd->ddp_count)
313     {
314         gmx_incons("The MD state does not match the domain decomposition state");
315     }
316
317     state->cg_gl.resize(dd->ncg_home);
318     for (i = 0; i < dd->ncg_home; i++)
319     {
320         state->cg_gl[i] = dd->index_gl[i];
321     }
322
323     state->ddp_count_cg_gl = dd->ddp_count;
324 }
325
326 gmx_domdec_zones_t *domdec_zones(gmx_domdec_t *dd)
327 {
328     return &dd->comm->zones;
329 }
330
331 void dd_get_ns_ranges(const gmx_domdec_t *dd, int icg,
332                       int *jcg0, int *jcg1, ivec shift0, ivec shift1)
333 {
334     gmx_domdec_zones_t *zones;
335     int                 izone, d, dim;
336
337     zones = &dd->comm->zones;
338
339     izone = 0;
340     while (icg >= zones->izone[izone].cg1)
341     {
342         izone++;
343     }
344
345     if (izone == 0)
346     {
347         *jcg0 = icg;
348     }
349     else if (izone < zones->nizone)
350     {
351         *jcg0 = zones->izone[izone].jcg0;
352     }
353     else
354     {
355         gmx_fatal(FARGS, "DD icg %d out of range: izone (%d) >= nizone (%d)",
356                   icg, izone, zones->nizone);
357     }
358
359     *jcg1 = zones->izone[izone].jcg1;
360
361     for (d = 0; d < dd->ndim; d++)
362     {
363         dim         = dd->dim[d];
364         shift0[dim] = zones->izone[izone].shift0[dim];
365         shift1[dim] = zones->izone[izone].shift1[dim];
366         if (dd->comm->tric_dir[dim] || (isDlbOn(dd->comm) && d > 0))
367         {
368             /* A conservative approach, this can be optimized */
369             shift0[dim] -= 1;
370             shift1[dim] += 1;
371         }
372     }
373 }
374
375 int dd_natoms_mdatoms(const gmx_domdec_t *dd)
376 {
377     /* We currently set mdatoms entries for all atoms:
378      * local + non-local + communicated for vsite + constraints
379      */
380
381     return dd->comm->nat[ddnatNR - 1];
382 }
383
384 int dd_natoms_vsite(const gmx_domdec_t *dd)
385 {
386     return dd->comm->nat[ddnatVSITE];
387 }
388
389 void dd_get_constraint_range(const gmx_domdec_t *dd, int *at_start, int *at_end)
390 {
391     *at_start = dd->comm->nat[ddnatCON-1];
392     *at_end   = dd->comm->nat[ddnatCON];
393 }
394
395 void dd_move_x(gmx_domdec_t *dd, matrix box, rvec x[])
396 {
397     int                    nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
398     int                   *index, *cgindex;
399     gmx_domdec_comm_t     *comm;
400     gmx_domdec_comm_dim_t *cd;
401     gmx_domdec_ind_t      *ind;
402     rvec                   shift = {0, 0, 0}, *buf, *rbuf;
403     gmx_bool               bPBC, bScrew;
404
405     comm = dd->comm;
406
407     cgindex = dd->cgindex;
408
409     buf = comm->vbuf.v;
410
411     nzone   = 1;
412     nat_tot = dd->nat_home;
413     for (d = 0; d < dd->ndim; d++)
414     {
415         bPBC   = (dd->ci[dd->dim[d]] == 0);
416         bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
417         if (bPBC)
418         {
419             copy_rvec(box[dd->dim[d]], shift);
420         }
421         cd = &comm->cd[d];
422         for (p = 0; p < cd->np; p++)
423         {
424             ind   = &cd->ind[p];
425             index = ind->index;
426             n     = 0;
427             if (!bPBC)
428             {
429                 for (i = 0; i < ind->nsend[nzone]; i++)
430                 {
431                     at0 = cgindex[index[i]];
432                     at1 = cgindex[index[i]+1];
433                     for (j = at0; j < at1; j++)
434                     {
435                         copy_rvec(x[j], buf[n]);
436                         n++;
437                     }
438                 }
439             }
440             else if (!bScrew)
441             {
442                 for (i = 0; i < ind->nsend[nzone]; i++)
443                 {
444                     at0 = cgindex[index[i]];
445                     at1 = cgindex[index[i]+1];
446                     for (j = at0; j < at1; j++)
447                     {
448                         /* We need to shift the coordinates */
449                         rvec_add(x[j], shift, buf[n]);
450                         n++;
451                     }
452                 }
453             }
454             else
455             {
456                 for (i = 0; i < ind->nsend[nzone]; i++)
457                 {
458                     at0 = cgindex[index[i]];
459                     at1 = cgindex[index[i]+1];
460                     for (j = at0; j < at1; j++)
461                     {
462                         /* Shift x */
463                         buf[n][XX] = x[j][XX] + shift[XX];
464                         /* Rotate y and z.
465                          * This operation requires a special shift force
466                          * treatment, which is performed in calc_vir.
467                          */
468                         buf[n][YY] = box[YY][YY] - x[j][YY];
469                         buf[n][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
470                         n++;
471                     }
472                 }
473             }
474
475             if (cd->bInPlace)
476             {
477                 rbuf = x + nat_tot;
478             }
479             else
480             {
481                 rbuf = comm->vbuf2.v;
482             }
483             /* Send and receive the coordinates */
484             dd_sendrecv_rvec(dd, d, dddirBackward,
485                              buf,  ind->nsend[nzone+1],
486                              rbuf, ind->nrecv[nzone+1]);
487             if (!cd->bInPlace)
488             {
489                 j = 0;
490                 for (zone = 0; zone < nzone; zone++)
491                 {
492                     for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
493                     {
494                         copy_rvec(rbuf[j], x[i]);
495                         j++;
496                     }
497                 }
498             }
499             nat_tot += ind->nrecv[nzone+1];
500         }
501         nzone += nzone;
502     }
503 }
504
505 void dd_move_f(gmx_domdec_t *dd, rvec f[], rvec *fshift)
506 {
507     int                    nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
508     int                   *index, *cgindex;
509     gmx_domdec_comm_t     *comm;
510     gmx_domdec_comm_dim_t *cd;
511     gmx_domdec_ind_t      *ind;
512     rvec                  *buf, *sbuf;
513     ivec                   vis;
514     int                    is;
515     gmx_bool               bShiftForcesNeedPbc, bScrew;
516
517     comm = dd->comm;
518
519     cgindex = dd->cgindex;
520
521     buf = comm->vbuf.v;
522
523     nzone   = comm->zones.n/2;
524     nat_tot = dd->nat_tot;
525     for (d = dd->ndim-1; d >= 0; d--)
526     {
527         /* Only forces in domains near the PBC boundaries need to
528            consider PBC in the treatment of fshift */
529         bShiftForcesNeedPbc   = (dd->ci[dd->dim[d]] == 0);
530         bScrew                = (bShiftForcesNeedPbc && dd->bScrewPBC && dd->dim[d] == XX);
531         if (fshift == nullptr && !bScrew)
532         {
533             bShiftForcesNeedPbc = FALSE;
534         }
535         /* Determine which shift vector we need */
536         clear_ivec(vis);
537         vis[dd->dim[d]] = 1;
538         is              = IVEC2IS(vis);
539
540         cd = &comm->cd[d];
541         for (p = cd->np-1; p >= 0; p--)
542         {
543             ind      = &cd->ind[p];
544             nat_tot -= ind->nrecv[nzone+1];
545             if (cd->bInPlace)
546             {
547                 sbuf = f + nat_tot;
548             }
549             else
550             {
551                 sbuf = comm->vbuf2.v;
552                 j    = 0;
553                 for (zone = 0; zone < nzone; zone++)
554                 {
555                     for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
556                     {
557                         copy_rvec(f[i], sbuf[j]);
558                         j++;
559                     }
560                 }
561             }
562             /* Communicate the forces */
563             dd_sendrecv_rvec(dd, d, dddirForward,
564                              sbuf, ind->nrecv[nzone+1],
565                              buf,  ind->nsend[nzone+1]);
566             index = ind->index;
567             /* Add the received forces */
568             n = 0;
569             if (!bShiftForcesNeedPbc)
570             {
571                 for (i = 0; i < ind->nsend[nzone]; i++)
572                 {
573                     at0 = cgindex[index[i]];
574                     at1 = cgindex[index[i]+1];
575                     for (j = at0; j < at1; j++)
576                     {
577                         rvec_inc(f[j], buf[n]);
578                         n++;
579                     }
580                 }
581             }
582             else if (!bScrew)
583             {
584                 /* fshift should always be defined if this function is
585                  * called when bShiftForcesNeedPbc is true */
586                 assert(NULL != fshift);
587                 for (i = 0; i < ind->nsend[nzone]; i++)
588                 {
589                     at0 = cgindex[index[i]];
590                     at1 = cgindex[index[i]+1];
591                     for (j = at0; j < at1; j++)
592                     {
593                         rvec_inc(f[j], buf[n]);
594                         /* Add this force to the shift force */
595                         rvec_inc(fshift[is], buf[n]);
596                         n++;
597                     }
598                 }
599             }
600             else
601             {
602                 for (i = 0; i < ind->nsend[nzone]; i++)
603                 {
604                     at0 = cgindex[index[i]];
605                     at1 = cgindex[index[i]+1];
606                     for (j = at0; j < at1; j++)
607                     {
608                         /* Rotate the force */
609                         f[j][XX] += buf[n][XX];
610                         f[j][YY] -= buf[n][YY];
611                         f[j][ZZ] -= buf[n][ZZ];
612                         if (fshift)
613                         {
614                             /* Add this force to the shift force */
615                             rvec_inc(fshift[is], buf[n]);
616                         }
617                         n++;
618                     }
619                 }
620             }
621         }
622         nzone /= 2;
623     }
624 }
625
626 void dd_atom_spread_real(gmx_domdec_t *dd, real v[])
627 {
628     int                    nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
629     int                   *index, *cgindex;
630     gmx_domdec_comm_t     *comm;
631     gmx_domdec_comm_dim_t *cd;
632     gmx_domdec_ind_t      *ind;
633     real                  *buf, *rbuf;
634
635     comm = dd->comm;
636
637     cgindex = dd->cgindex;
638
639     buf = &comm->vbuf.v[0][0];
640
641     nzone   = 1;
642     nat_tot = dd->nat_home;
643     for (d = 0; d < dd->ndim; d++)
644     {
645         cd = &comm->cd[d];
646         for (p = 0; p < cd->np; p++)
647         {
648             ind   = &cd->ind[p];
649             index = ind->index;
650             n     = 0;
651             for (i = 0; i < ind->nsend[nzone]; i++)
652             {
653                 at0 = cgindex[index[i]];
654                 at1 = cgindex[index[i]+1];
655                 for (j = at0; j < at1; j++)
656                 {
657                     buf[n] = v[j];
658                     n++;
659                 }
660             }
661
662             if (cd->bInPlace)
663             {
664                 rbuf = v + nat_tot;
665             }
666             else
667             {
668                 rbuf = &comm->vbuf2.v[0][0];
669             }
670             /* Send and receive the coordinates */
671             dd_sendrecv_real(dd, d, dddirBackward,
672                              buf,  ind->nsend[nzone+1],
673                              rbuf, ind->nrecv[nzone+1]);
674             if (!cd->bInPlace)
675             {
676                 j = 0;
677                 for (zone = 0; zone < nzone; zone++)
678                 {
679                     for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
680                     {
681                         v[i] = rbuf[j];
682                         j++;
683                     }
684                 }
685             }
686             nat_tot += ind->nrecv[nzone+1];
687         }
688         nzone += nzone;
689     }
690 }
691
692 void dd_atom_sum_real(gmx_domdec_t *dd, real v[])
693 {
694     int                    nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
695     int                   *index, *cgindex;
696     gmx_domdec_comm_t     *comm;
697     gmx_domdec_comm_dim_t *cd;
698     gmx_domdec_ind_t      *ind;
699     real                  *buf, *sbuf;
700
701     comm = dd->comm;
702
703     cgindex = dd->cgindex;
704
705     buf = &comm->vbuf.v[0][0];
706
707     nzone   = comm->zones.n/2;
708     nat_tot = dd->nat_tot;
709     for (d = dd->ndim-1; d >= 0; d--)
710     {
711         cd = &comm->cd[d];
712         for (p = cd->np-1; p >= 0; p--)
713         {
714             ind      = &cd->ind[p];
715             nat_tot -= ind->nrecv[nzone+1];
716             if (cd->bInPlace)
717             {
718                 sbuf = v + nat_tot;
719             }
720             else
721             {
722                 sbuf = &comm->vbuf2.v[0][0];
723                 j    = 0;
724                 for (zone = 0; zone < nzone; zone++)
725                 {
726                     for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
727                     {
728                         sbuf[j] = v[i];
729                         j++;
730                     }
731                 }
732             }
733             /* Communicate the forces */
734             dd_sendrecv_real(dd, d, dddirForward,
735                              sbuf, ind->nrecv[nzone+1],
736                              buf,  ind->nsend[nzone+1]);
737             index = ind->index;
738             /* Add the received forces */
739             n = 0;
740             for (i = 0; i < ind->nsend[nzone]; i++)
741             {
742                 at0 = cgindex[index[i]];
743                 at1 = cgindex[index[i]+1];
744                 for (j = at0; j < at1; j++)
745                 {
746                     v[j] += buf[n];
747                     n++;
748                 }
749             }
750         }
751         nzone /= 2;
752     }
753 }
754
755 static void print_ddzone(FILE *fp, int d, int i, int j, gmx_ddzone_t *zone)
756 {
757     fprintf(fp, "zone d0 %d d1 %d d2 %d  min0 %6.3f max1 %6.3f mch0 %6.3f mch1 %6.3f p1_0 %6.3f p1_1 %6.3f\n",
758             d, i, j,
759             zone->min0, zone->max1,
760             zone->mch0, zone->mch0,
761             zone->p1_0, zone->p1_1);
762 }
763
764
765 #define DDZONECOMM_MAXZONE  5
766 #define DDZONECOMM_BUFSIZE  3
767
768 static void dd_sendrecv_ddzone(const gmx_domdec_t *dd,
769                                int ddimind, int direction,
770                                gmx_ddzone_t *buf_s, int n_s,
771                                gmx_ddzone_t *buf_r, int n_r)
772 {
773 #define ZBS  DDZONECOMM_BUFSIZE
774     rvec vbuf_s[DDZONECOMM_MAXZONE*ZBS];
775     rvec vbuf_r[DDZONECOMM_MAXZONE*ZBS];
776     int  i;
777
778     for (i = 0; i < n_s; i++)
779     {
780         vbuf_s[i*ZBS  ][0] = buf_s[i].min0;
781         vbuf_s[i*ZBS  ][1] = buf_s[i].max1;
782         vbuf_s[i*ZBS  ][2] = buf_s[i].min1;
783         vbuf_s[i*ZBS+1][0] = buf_s[i].mch0;
784         vbuf_s[i*ZBS+1][1] = buf_s[i].mch1;
785         vbuf_s[i*ZBS+1][2] = 0;
786         vbuf_s[i*ZBS+2][0] = buf_s[i].p1_0;
787         vbuf_s[i*ZBS+2][1] = buf_s[i].p1_1;
788         vbuf_s[i*ZBS+2][2] = 0;
789     }
790
791     dd_sendrecv_rvec(dd, ddimind, direction,
792                      vbuf_s, n_s*ZBS,
793                      vbuf_r, n_r*ZBS);
794
795     for (i = 0; i < n_r; i++)
796     {
797         buf_r[i].min0 = vbuf_r[i*ZBS  ][0];
798         buf_r[i].max1 = vbuf_r[i*ZBS  ][1];
799         buf_r[i].min1 = vbuf_r[i*ZBS  ][2];
800         buf_r[i].mch0 = vbuf_r[i*ZBS+1][0];
801         buf_r[i].mch1 = vbuf_r[i*ZBS+1][1];
802         buf_r[i].p1_0 = vbuf_r[i*ZBS+2][0];
803         buf_r[i].p1_1 = vbuf_r[i*ZBS+2][1];
804     }
805
806 #undef ZBS
807 }
808
809 static void dd_move_cellx(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
810                           rvec cell_ns_x0, rvec cell_ns_x1)
811 {
812     int                d, d1, dim, pos, buf_size, i, j, p, npulse, npulse_min;
813     gmx_ddzone_t      *zp;
814     gmx_ddzone_t       buf_s[DDZONECOMM_MAXZONE];
815     gmx_ddzone_t       buf_r[DDZONECOMM_MAXZONE];
816     gmx_ddzone_t       buf_e[DDZONECOMM_MAXZONE];
817     rvec               extr_s[2], extr_r[2];
818     rvec               dh;
819     real               dist_d, c = 0, det;
820     gmx_domdec_comm_t *comm;
821     gmx_bool           bPBC, bUse;
822
823     comm = dd->comm;
824
825     for (d = 1; d < dd->ndim; d++)
826     {
827         dim      = dd->dim[d];
828         zp       = (d == 1) ? &comm->zone_d1[0] : &comm->zone_d2[0][0];
829         zp->min0 = cell_ns_x0[dim];
830         zp->max1 = cell_ns_x1[dim];
831         zp->min1 = cell_ns_x1[dim];
832         zp->mch0 = cell_ns_x0[dim];
833         zp->mch1 = cell_ns_x1[dim];
834         zp->p1_0 = cell_ns_x0[dim];
835         zp->p1_1 = cell_ns_x1[dim];
836     }
837
838     for (d = dd->ndim-2; d >= 0; d--)
839     {
840         dim  = dd->dim[d];
841         bPBC = (dim < ddbox->npbcdim);
842
843         /* Use an rvec to store two reals */
844         extr_s[d][0] = comm->cell_f0[d+1];
845         extr_s[d][1] = comm->cell_f1[d+1];
846         extr_s[d][2] = comm->cell_f1[d+1];
847
848         pos = 0;
849         /* Store the extremes in the backward sending buffer,
850          * so the get updated separately from the forward communication.
851          */
852         for (d1 = d; d1 < dd->ndim-1; d1++)
853         {
854             /* We invert the order to be able to use the same loop for buf_e */
855             buf_s[pos].min0 = extr_s[d1][1];
856             buf_s[pos].max1 = extr_s[d1][0];
857             buf_s[pos].min1 = extr_s[d1][2];
858             buf_s[pos].mch0 = 0;
859             buf_s[pos].mch1 = 0;
860             /* Store the cell corner of the dimension we communicate along */
861             buf_s[pos].p1_0 = comm->cell_x0[dim];
862             buf_s[pos].p1_1 = 0;
863             pos++;
864         }
865
866         buf_s[pos] = (dd->ndim == 2) ? comm->zone_d1[0] : comm->zone_d2[0][0];
867         pos++;
868
869         if (dd->ndim == 3 && d == 0)
870         {
871             buf_s[pos] = comm->zone_d2[0][1];
872             pos++;
873             buf_s[pos] = comm->zone_d1[0];
874             pos++;
875         }
876
877         /* We only need to communicate the extremes
878          * in the forward direction
879          */
880         npulse = comm->cd[d].np;
881         if (bPBC)
882         {
883             /* Take the minimum to avoid double communication */
884             npulse_min = std::min(npulse, dd->nc[dim]-1-npulse);
885         }
886         else
887         {
888             /* Without PBC we should really not communicate over
889              * the boundaries, but implementing that complicates
890              * the communication setup and therefore we simply
891              * do all communication, but ignore some data.
892              */
893             npulse_min = npulse;
894         }
895         for (p = 0; p < npulse_min; p++)
896         {
897             /* Communicate the extremes forward */
898             bUse = (bPBC || dd->ci[dim] > 0);
899
900             dd_sendrecv_rvec(dd, d, dddirForward,
901                              extr_s+d, dd->ndim-d-1,
902                              extr_r+d, dd->ndim-d-1);
903
904             if (bUse)
905             {
906                 for (d1 = d; d1 < dd->ndim-1; d1++)
907                 {
908                     extr_s[d1][0] = std::max(extr_s[d1][0], extr_r[d1][0]);
909                     extr_s[d1][1] = std::min(extr_s[d1][1], extr_r[d1][1]);
910                     extr_s[d1][2] = std::min(extr_s[d1][2], extr_r[d1][2]);
911                 }
912             }
913         }
914
915         buf_size = pos;
916         for (p = 0; p < npulse; p++)
917         {
918             /* Communicate all the zone information backward */
919             bUse = (bPBC || dd->ci[dim] < dd->nc[dim] - 1);
920
921             dd_sendrecv_ddzone(dd, d, dddirBackward,
922                                buf_s, buf_size,
923                                buf_r, buf_size);
924
925             clear_rvec(dh);
926             if (p > 0)
927             {
928                 for (d1 = d+1; d1 < dd->ndim; d1++)
929                 {
930                     /* Determine the decrease of maximum required
931                      * communication height along d1 due to the distance along d,
932                      * this avoids a lot of useless atom communication.
933                      */
934                     dist_d = comm->cell_x1[dim] - buf_r[0].p1_0;
935
936                     if (ddbox->tric_dir[dim])
937                     {
938                         /* c is the off-diagonal coupling between the cell planes
939                          * along directions d and d1.
940                          */
941                         c = ddbox->v[dim][dd->dim[d1]][dim];
942                     }
943                     else
944                     {
945                         c = 0;
946                     }
947                     det = (1 + c*c)*comm->cutoff*comm->cutoff - dist_d*dist_d;
948                     if (det > 0)
949                     {
950                         dh[d1] = comm->cutoff - (c*dist_d + std::sqrt(det))/(1 + c*c);
951                     }
952                     else
953                     {
954                         /* A negative value signals out of range */
955                         dh[d1] = -1;
956                     }
957                 }
958             }
959
960             /* Accumulate the extremes over all pulses */
961             for (i = 0; i < buf_size; i++)
962             {
963                 if (p == 0)
964                 {
965                     buf_e[i] = buf_r[i];
966                 }
967                 else
968                 {
969                     if (bUse)
970                     {
971                         buf_e[i].min0 = std::min(buf_e[i].min0, buf_r[i].min0);
972                         buf_e[i].max1 = std::max(buf_e[i].max1, buf_r[i].max1);
973                         buf_e[i].min1 = std::min(buf_e[i].min1, buf_r[i].min1);
974                     }
975
976                     if (dd->ndim == 3 && d == 0 && i == buf_size - 1)
977                     {
978                         d1 = 1;
979                     }
980                     else
981                     {
982                         d1 = d + 1;
983                     }
984                     if (bUse && dh[d1] >= 0)
985                     {
986                         buf_e[i].mch0 = std::max(buf_e[i].mch0, buf_r[i].mch0-dh[d1]);
987                         buf_e[i].mch1 = std::max(buf_e[i].mch1, buf_r[i].mch1-dh[d1]);
988                     }
989                 }
990                 /* Copy the received buffer to the send buffer,
991                  * to pass the data through with the next pulse.
992                  */
993                 buf_s[i] = buf_r[i];
994             }
995             if (((bPBC || dd->ci[dim]+npulse < dd->nc[dim]) && p == npulse-1) ||
996                 (!bPBC && dd->ci[dim]+1+p == dd->nc[dim]-1))
997             {
998                 /* Store the extremes */
999                 pos = 0;
1000
1001                 for (d1 = d; d1 < dd->ndim-1; d1++)
1002                 {
1003                     extr_s[d1][1] = std::min(extr_s[d1][1], buf_e[pos].min0);
1004                     extr_s[d1][0] = std::max(extr_s[d1][0], buf_e[pos].max1);
1005                     extr_s[d1][2] = std::min(extr_s[d1][2], buf_e[pos].min1);
1006                     pos++;
1007                 }
1008
1009                 if (d == 1 || (d == 0 && dd->ndim == 3))
1010                 {
1011                     for (i = d; i < 2; i++)
1012                     {
1013                         comm->zone_d2[1-d][i] = buf_e[pos];
1014                         pos++;
1015                     }
1016                 }
1017                 if (d == 0)
1018                 {
1019                     comm->zone_d1[1] = buf_e[pos];
1020                     pos++;
1021                 }
1022             }
1023         }
1024     }
1025
1026     if (dd->ndim >= 2)
1027     {
1028         dim = dd->dim[1];
1029         for (i = 0; i < 2; i++)
1030         {
1031             if (debug)
1032             {
1033                 print_ddzone(debug, 1, i, 0, &comm->zone_d1[i]);
1034             }
1035             cell_ns_x0[dim] = std::min(cell_ns_x0[dim], comm->zone_d1[i].min0);
1036             cell_ns_x1[dim] = std::max(cell_ns_x1[dim], comm->zone_d1[i].max1);
1037         }
1038     }
1039     if (dd->ndim >= 3)
1040     {
1041         dim = dd->dim[2];
1042         for (i = 0; i < 2; i++)
1043         {
1044             for (j = 0; j < 2; j++)
1045             {
1046                 if (debug)
1047                 {
1048                     print_ddzone(debug, 2, i, j, &comm->zone_d2[i][j]);
1049                 }
1050                 cell_ns_x0[dim] = std::min(cell_ns_x0[dim], comm->zone_d2[i][j].min0);
1051                 cell_ns_x1[dim] = std::max(cell_ns_x1[dim], comm->zone_d2[i][j].max1);
1052             }
1053         }
1054     }
1055     for (d = 1; d < dd->ndim; d++)
1056     {
1057         comm->cell_f_max0[d] = extr_s[d-1][0];
1058         comm->cell_f_min1[d] = extr_s[d-1][1];
1059         if (debug)
1060         {
1061             fprintf(debug, "Cell fraction d %d, max0 %f, min1 %f\n",
1062                     d, comm->cell_f_max0[d], comm->cell_f_min1[d]);
1063         }
1064     }
1065 }
1066
1067 static void dd_collect_cg(gmx_domdec_t  *dd,
1068                           const t_state *state_local)
1069 {
1070     gmx_domdec_master_t *ma = nullptr;
1071     int                  buf2[2], *ibuf, i, ncg_home = 0, nat_home = 0;
1072
1073     if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
1074     {
1075         /* The master has the correct distribution */
1076         return;
1077     }
1078
1079     const int *cg;
1080
1081     if (state_local->ddp_count == dd->ddp_count)
1082     {
1083         /* The local state and DD are in sync, use the DD indices */
1084         ncg_home = dd->ncg_home;
1085         cg       = dd->index_gl;
1086         nat_home = dd->nat_home;
1087     }
1088     else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
1089     {
1090         /* The DD is out of sync with the local state, but we have stored
1091          * the cg indices with the local state, so we can use those.
1092          */
1093         t_block *cgs_gl;
1094
1095         cgs_gl = &dd->comm->cgs_gl;
1096
1097         ncg_home = state_local->cg_gl.size();
1098         cg       = state_local->cg_gl.data();
1099         nat_home = 0;
1100         for (i = 0; i < ncg_home; i++)
1101         {
1102             nat_home += cgs_gl->index[cg[i]+1] - cgs_gl->index[cg[i]];
1103         }
1104     }
1105     else
1106     {
1107         gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
1108     }
1109
1110     buf2[0] = ncg_home;
1111     buf2[1] = nat_home;
1112     if (DDMASTER(dd))
1113     {
1114         ma   = dd->ma;
1115         ibuf = ma->ibuf;
1116     }
1117     else
1118     {
1119         ibuf = nullptr;
1120     }
1121     /* Collect the charge group and atom counts on the master */
1122     dd_gather(dd, 2*sizeof(int), buf2, ibuf);
1123
1124     if (DDMASTER(dd))
1125     {
1126         ma->index[0] = 0;
1127         for (i = 0; i < dd->nnodes; i++)
1128         {
1129             ma->ncg[i]     = ma->ibuf[2*i];
1130             ma->nat[i]     = ma->ibuf[2*i+1];
1131             ma->index[i+1] = ma->index[i] + ma->ncg[i];
1132
1133         }
1134         /* Make byte counts and indices */
1135         for (i = 0; i < dd->nnodes; i++)
1136         {
1137             ma->ibuf[i]            = ma->ncg[i]*sizeof(int);
1138             ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
1139         }
1140         if (debug)
1141         {
1142             fprintf(debug, "Initial charge group distribution: ");
1143             for (i = 0; i < dd->nnodes; i++)
1144             {
1145                 fprintf(debug, " %d", ma->ncg[i]);
1146             }
1147             fprintf(debug, "\n");
1148         }
1149     }
1150
1151     /* Collect the charge group indices on the master */
1152     dd_gatherv(dd,
1153                ncg_home*sizeof(int), cg,
1154                DDMASTER(dd) ? ma->ibuf : nullptr,
1155                DDMASTER(dd) ? ma->ibuf+dd->nnodes : nullptr,
1156                DDMASTER(dd) ? ma->cg : nullptr);
1157
1158     dd->comm->master_cg_ddp_count = state_local->ddp_count;
1159 }
1160
1161 static void dd_collect_vec_sendrecv(gmx_domdec_t                  *dd,
1162                                     gmx::ArrayRef<const gmx::RVec> lv,
1163                                     gmx::ArrayRef<gmx::RVec>       v)
1164 {
1165     gmx_domdec_master_t *ma;
1166     int                  n, i, c, a, nalloc = 0;
1167     rvec                *buf = nullptr;
1168     t_block             *cgs_gl;
1169
1170     ma = dd->ma;
1171
1172     if (!DDMASTER(dd))
1173     {
1174 #if GMX_MPI
1175         MPI_Send(const_cast<void *>(static_cast<const void *>(lv.data())), dd->nat_home*sizeof(rvec), MPI_BYTE,
1176                  DDMASTERRANK(dd), dd->rank, dd->mpi_comm_all);
1177 #endif
1178     }
1179     else
1180     {
1181         /* Copy the master coordinates to the global array */
1182         cgs_gl = &dd->comm->cgs_gl;
1183
1184         n = DDMASTERRANK(dd);
1185         a = 0;
1186         for (i = ma->index[n]; i < ma->index[n+1]; i++)
1187         {
1188             for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1189             {
1190                 copy_rvec(lv[a++], v[c]);
1191             }
1192         }
1193
1194         for (n = 0; n < dd->nnodes; n++)
1195         {
1196             if (n != dd->rank)
1197             {
1198                 if (ma->nat[n] > nalloc)
1199                 {
1200                     nalloc = over_alloc_dd(ma->nat[n]);
1201                     srenew(buf, nalloc);
1202                 }
1203 #if GMX_MPI
1204                 MPI_Recv(buf, ma->nat[n]*sizeof(rvec), MPI_BYTE, DDRANK(dd, n),
1205                          n, dd->mpi_comm_all, MPI_STATUS_IGNORE);
1206 #endif
1207                 a = 0;
1208                 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1209                 {
1210                     for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1211                     {
1212                         copy_rvec(buf[a++], v[c]);
1213                     }
1214                 }
1215             }
1216         }
1217         sfree(buf);
1218     }
1219 }
1220
1221 static void get_commbuffer_counts(gmx_domdec_t *dd,
1222                                   int **counts, int **disps)
1223 {
1224     gmx_domdec_master_t *ma;
1225     int                  n;
1226
1227     ma = dd->ma;
1228
1229     /* Make the rvec count and displacment arrays */
1230     *counts  = ma->ibuf;
1231     *disps   = ma->ibuf + dd->nnodes;
1232     for (n = 0; n < dd->nnodes; n++)
1233     {
1234         (*counts)[n] = ma->nat[n]*sizeof(rvec);
1235         (*disps)[n]  = (n == 0 ? 0 : (*disps)[n-1] + (*counts)[n-1]);
1236     }
1237 }
1238
1239 static void dd_collect_vec_gatherv(gmx_domdec_t                  *dd,
1240                                    gmx::ArrayRef<const gmx::RVec> lv,
1241                                    gmx::ArrayRef<gmx::RVec>       v)
1242 {
1243     gmx_domdec_master_t *ma;
1244     int                 *rcounts = nullptr, *disps = nullptr;
1245     int                  n, i, c, a;
1246     rvec                *buf = nullptr;
1247     t_block             *cgs_gl;
1248
1249     ma = dd->ma;
1250
1251     if (DDMASTER(dd))
1252     {
1253         get_commbuffer_counts(dd, &rcounts, &disps);
1254
1255         buf = ma->vbuf;
1256     }
1257
1258     dd_gatherv(dd, dd->nat_home*sizeof(rvec), lv.data(), rcounts, disps, buf);
1259
1260     if (DDMASTER(dd))
1261     {
1262         cgs_gl = &dd->comm->cgs_gl;
1263
1264         a = 0;
1265         for (n = 0; n < dd->nnodes; n++)
1266         {
1267             for (i = ma->index[n]; i < ma->index[n+1]; i++)
1268             {
1269                 for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1270                 {
1271                     copy_rvec(buf[a++], v[c]);
1272                 }
1273             }
1274         }
1275     }
1276 }
1277
1278 void dd_collect_vec(gmx_domdec_t                  *dd,
1279                     const t_state                 *state_local,
1280                     gmx::ArrayRef<const gmx::RVec> lv,
1281                     gmx::ArrayRef<gmx::RVec>       v)
1282 {
1283     dd_collect_cg(dd, state_local);
1284
1285     if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
1286     {
1287         dd_collect_vec_sendrecv(dd, lv, v);
1288     }
1289     else
1290     {
1291         dd_collect_vec_gatherv(dd, lv, v);
1292     }
1293 }
1294
1295
1296 void dd_collect_state(gmx_domdec_t *dd,
1297                       const t_state *state_local, t_state *state)
1298 {
1299     int nh = state_local->nhchainlength;
1300
1301     if (DDMASTER(dd))
1302     {
1303         GMX_RELEASE_ASSERT(state->nhchainlength == nh, "The global and local Nose-Hoover chain lengths should match");
1304
1305         for (int i = 0; i < efptNR; i++)
1306         {
1307             state->lambda[i] = state_local->lambda[i];
1308         }
1309         state->fep_state = state_local->fep_state;
1310         state->veta      = state_local->veta;
1311         state->vol0      = state_local->vol0;
1312         copy_mat(state_local->box, state->box);
1313         copy_mat(state_local->boxv, state->boxv);
1314         copy_mat(state_local->svir_prev, state->svir_prev);
1315         copy_mat(state_local->fvir_prev, state->fvir_prev);
1316         copy_mat(state_local->pres_prev, state->pres_prev);
1317
1318         for (int i = 0; i < state_local->ngtc; i++)
1319         {
1320             for (int j = 0; j < nh; j++)
1321             {
1322                 state->nosehoover_xi[i*nh+j]        = state_local->nosehoover_xi[i*nh+j];
1323                 state->nosehoover_vxi[i*nh+j]       = state_local->nosehoover_vxi[i*nh+j];
1324             }
1325             state->therm_integral[i] = state_local->therm_integral[i];
1326         }
1327         for (int i = 0; i < state_local->nnhpres; i++)
1328         {
1329             for (int j = 0; j < nh; j++)
1330             {
1331                 state->nhpres_xi[i*nh+j]        = state_local->nhpres_xi[i*nh+j];
1332                 state->nhpres_vxi[i*nh+j]       = state_local->nhpres_vxi[i*nh+j];
1333             }
1334         }
1335         state->baros_integral = state_local->baros_integral;
1336     }
1337     if (state_local->flags & (1 << estX))
1338     {
1339         gmx::ArrayRef<gmx::RVec> globalXRef = state ? gmx::makeArrayRef(state->x) : gmx::EmptyArrayRef();
1340         dd_collect_vec(dd, state_local, state_local->x, globalXRef);
1341     }
1342     if (state_local->flags & (1 << estV))
1343     {
1344         gmx::ArrayRef<gmx::RVec> globalVRef = state ? gmx::makeArrayRef(state->v) : gmx::EmptyArrayRef();
1345         dd_collect_vec(dd, state_local, state_local->v, globalVRef);
1346     }
1347     if (state_local->flags & (1 << estCGP))
1348     {
1349         gmx::ArrayRef<gmx::RVec> globalCgpRef = state ? gmx::makeArrayRef(state->cg_p) : gmx::EmptyArrayRef();
1350         dd_collect_vec(dd, state_local, state_local->cg_p, globalCgpRef);
1351     }
1352 }
1353
1354 static void dd_resize_state(t_state *state, PaddedRVecVector *f, int natoms)
1355 {
1356     if (debug)
1357     {
1358         fprintf(debug, "Resizing state: currently %d, required %d\n", state->natoms, natoms);
1359     }
1360
1361     state_change_natoms(state, natoms);
1362
1363     if (f != nullptr)
1364     {
1365         /* We need to allocate one element extra, since we might use
1366          * (unaligned) 4-wide SIMD loads to access rvec entries.
1367          */
1368         f->resize(paddedRVecVectorSize(natoms));
1369     }
1370 }
1371
1372 static void dd_check_alloc_ncg(t_forcerec       *fr,
1373                                t_state          *state,
1374                                PaddedRVecVector *f,
1375                                int               numChargeGroups)
1376 {
1377     if (numChargeGroups > fr->cg_nalloc)
1378     {
1379         if (debug)
1380         {
1381             fprintf(debug, "Reallocating forcerec: currently %d, required %d, allocating %d\n", fr->cg_nalloc, numChargeGroups, over_alloc_dd(numChargeGroups));
1382         }
1383         fr->cg_nalloc = over_alloc_dd(numChargeGroups);
1384         srenew(fr->cginfo, fr->cg_nalloc);
1385         if (fr->cutoff_scheme == ecutsGROUP)
1386         {
1387             srenew(fr->cg_cm, fr->cg_nalloc);
1388         }
1389     }
1390     if (fr->cutoff_scheme == ecutsVERLET)
1391     {
1392         /* We don't use charge groups, we use x in state to set up
1393          * the atom communication.
1394          */
1395         dd_resize_state(state, f, numChargeGroups);
1396     }
1397 }
1398
1399 static void dd_distribute_vec_sendrecv(gmx_domdec_t *dd, t_block *cgs,
1400                                        const rvec *v, rvec *lv)
1401 {
1402     gmx_domdec_master_t *ma;
1403     int                  n, i, c, a, nalloc = 0;
1404     rvec                *buf = nullptr;
1405
1406     if (DDMASTER(dd))
1407     {
1408         ma  = dd->ma;
1409
1410         for (n = 0; n < dd->nnodes; n++)
1411         {
1412             if (n != dd->rank)
1413             {
1414                 if (ma->nat[n] > nalloc)
1415                 {
1416                     nalloc = over_alloc_dd(ma->nat[n]);
1417                     srenew(buf, nalloc);
1418                 }
1419                 /* Use lv as a temporary buffer */
1420                 a = 0;
1421                 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1422                 {
1423                     for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1424                     {
1425                         copy_rvec(v[c], buf[a++]);
1426                     }
1427                 }
1428                 if (a != ma->nat[n])
1429                 {
1430                     gmx_fatal(FARGS, "Internal error a (%d) != nat (%d)",
1431                               a, ma->nat[n]);
1432                 }
1433
1434 #if GMX_MPI
1435                 MPI_Send(buf, ma->nat[n]*sizeof(rvec), MPI_BYTE,
1436                          DDRANK(dd, n), n, dd->mpi_comm_all);
1437 #endif
1438             }
1439         }
1440         sfree(buf);
1441         n = DDMASTERRANK(dd);
1442         a = 0;
1443         for (i = ma->index[n]; i < ma->index[n+1]; i++)
1444         {
1445             for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1446             {
1447                 copy_rvec(v[c], lv[a++]);
1448             }
1449         }
1450     }
1451     else
1452     {
1453 #if GMX_MPI
1454         MPI_Recv(lv, dd->nat_home*sizeof(rvec), MPI_BYTE, DDMASTERRANK(dd),
1455                  MPI_ANY_TAG, dd->mpi_comm_all, MPI_STATUS_IGNORE);
1456 #endif
1457     }
1458 }
1459
1460 static void dd_distribute_vec_scatterv(gmx_domdec_t *dd, t_block *cgs,
1461                                        const rvec *v, rvec *lv)
1462 {
1463     gmx_domdec_master_t *ma;
1464     int                 *scounts = nullptr, *disps = nullptr;
1465     int                  n, i, c, a;
1466     rvec                *buf = nullptr;
1467
1468     if (DDMASTER(dd))
1469     {
1470         ma  = dd->ma;
1471
1472         get_commbuffer_counts(dd, &scounts, &disps);
1473
1474         buf = ma->vbuf;
1475         a   = 0;
1476         for (n = 0; n < dd->nnodes; n++)
1477         {
1478             for (i = ma->index[n]; i < ma->index[n+1]; i++)
1479             {
1480                 for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1481                 {
1482                     copy_rvec(v[c], buf[a++]);
1483                 }
1484             }
1485         }
1486     }
1487
1488     dd_scatterv(dd, scounts, disps, buf, dd->nat_home*sizeof(rvec), lv);
1489 }
1490
1491 static void dd_distribute_vec(gmx_domdec_t *dd, t_block *cgs,
1492                               const rvec *v, rvec *lv)
1493 {
1494     if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
1495     {
1496         dd_distribute_vec_sendrecv(dd, cgs, v, lv);
1497     }
1498     else
1499     {
1500         dd_distribute_vec_scatterv(dd, cgs, v, lv);
1501     }
1502 }
1503
1504 static void dd_distribute_dfhist(gmx_domdec_t *dd, df_history_t *dfhist)
1505 {
1506     if (dfhist == nullptr)
1507     {
1508         return;
1509     }
1510
1511     dd_bcast(dd, sizeof(int), &dfhist->bEquil);
1512     dd_bcast(dd, sizeof(int), &dfhist->nlambda);
1513     dd_bcast(dd, sizeof(real), &dfhist->wl_delta);
1514
1515     if (dfhist->nlambda > 0)
1516     {
1517         int nlam = dfhist->nlambda;
1518         dd_bcast(dd, sizeof(int)*nlam, dfhist->n_at_lam);
1519         dd_bcast(dd, sizeof(real)*nlam, dfhist->wl_histo);
1520         dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_weights);
1521         dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_dg);
1522         dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_minvar);
1523         dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_variance);
1524
1525         for (int i = 0; i < nlam; i++)
1526         {
1527             dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p[i]);
1528             dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m[i]);
1529             dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p2[i]);
1530             dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m2[i]);
1531             dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij[i]);
1532             dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij_empirical[i]);
1533         }
1534     }
1535 }
1536
1537 static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
1538                                 t_state *state, t_state *state_local,
1539                                 PaddedRVecVector *f)
1540 {
1541     int nh = state_local->nhchainlength;
1542
1543     if (DDMASTER(dd))
1544     {
1545         GMX_RELEASE_ASSERT(state->nhchainlength == nh, "The global and local Nose-Hoover chain lengths should match");
1546
1547         for (int i = 0; i < efptNR; i++)
1548         {
1549             state_local->lambda[i] = state->lambda[i];
1550         }
1551         state_local->fep_state = state->fep_state;
1552         state_local->veta      = state->veta;
1553         state_local->vol0      = state->vol0;
1554         copy_mat(state->box, state_local->box);
1555         copy_mat(state->box_rel, state_local->box_rel);
1556         copy_mat(state->boxv, state_local->boxv);
1557         copy_mat(state->svir_prev, state_local->svir_prev);
1558         copy_mat(state->fvir_prev, state_local->fvir_prev);
1559         if (state->dfhist != nullptr)
1560         {
1561             copy_df_history(state_local->dfhist, state->dfhist);
1562         }
1563         for (int i = 0; i < state_local->ngtc; i++)
1564         {
1565             for (int j = 0; j < nh; j++)
1566             {
1567                 state_local->nosehoover_xi[i*nh+j]        = state->nosehoover_xi[i*nh+j];
1568                 state_local->nosehoover_vxi[i*nh+j]       = state->nosehoover_vxi[i*nh+j];
1569             }
1570             state_local->therm_integral[i] = state->therm_integral[i];
1571         }
1572         for (int i = 0; i < state_local->nnhpres; i++)
1573         {
1574             for (int j = 0; j < nh; j++)
1575             {
1576                 state_local->nhpres_xi[i*nh+j]        = state->nhpres_xi[i*nh+j];
1577                 state_local->nhpres_vxi[i*nh+j]       = state->nhpres_vxi[i*nh+j];
1578             }
1579         }
1580         state_local->baros_integral = state->baros_integral;
1581     }
1582     dd_bcast(dd, ((efptNR)*sizeof(real)), state_local->lambda.data());
1583     dd_bcast(dd, sizeof(int), &state_local->fep_state);
1584     dd_bcast(dd, sizeof(real), &state_local->veta);
1585     dd_bcast(dd, sizeof(real), &state_local->vol0);
1586     dd_bcast(dd, sizeof(state_local->box), state_local->box);
1587     dd_bcast(dd, sizeof(state_local->box_rel), state_local->box_rel);
1588     dd_bcast(dd, sizeof(state_local->boxv), state_local->boxv);
1589     dd_bcast(dd, sizeof(state_local->svir_prev), state_local->svir_prev);
1590     dd_bcast(dd, sizeof(state_local->fvir_prev), state_local->fvir_prev);
1591     dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_xi.data());
1592     dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_vxi.data());
1593     dd_bcast(dd, state_local->ngtc*sizeof(double), state_local->therm_integral.data());
1594     dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_xi.data());
1595     dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_vxi.data());
1596
1597     /* communicate df_history -- required for restarting from checkpoint */
1598     dd_distribute_dfhist(dd, state_local->dfhist);
1599
1600     dd_resize_state(state_local, f, dd->nat_home);
1601
1602     if (state_local->flags & (1 << estX))
1603     {
1604         const rvec *xGlobal = (DDMASTER(dd) ? as_rvec_array(state->x.data()) : nullptr);
1605         dd_distribute_vec(dd, cgs, xGlobal, as_rvec_array(state_local->x.data()));
1606     }
1607     if (state_local->flags & (1 << estV))
1608     {
1609         const rvec *vGlobal = (DDMASTER(dd) ? as_rvec_array(state->v.data()) : nullptr);
1610         dd_distribute_vec(dd, cgs, vGlobal, as_rvec_array(state_local->v.data()));
1611     }
1612     if (state_local->flags & (1 << estCGP))
1613     {
1614         const rvec *cgpGlobal = (DDMASTER(dd) ? as_rvec_array(state->cg_p.data()) : nullptr);
1615         dd_distribute_vec(dd, cgs, cgpGlobal, as_rvec_array(state_local->cg_p.data()));
1616     }
1617 }
1618
1619 static char dim2char(int dim)
1620 {
1621     char c = '?';
1622
1623     switch (dim)
1624     {
1625         case XX: c = 'X'; break;
1626         case YY: c = 'Y'; break;
1627         case ZZ: c = 'Z'; break;
1628         default: gmx_fatal(FARGS, "Unknown dim %d", dim);
1629     }
1630
1631     return c;
1632 }
1633
1634 static void write_dd_grid_pdb(const char *fn, gmx_int64_t step,
1635                               gmx_domdec_t *dd, matrix box, gmx_ddbox_t *ddbox)
1636 {
1637     rvec   grid_s[2], *grid_r = nullptr, cx, r;
1638     char   fname[STRLEN], buf[22];
1639     FILE  *out;
1640     int    a, i, d, z, y, x;
1641     matrix tric;
1642     real   vol;
1643
1644     copy_rvec(dd->comm->cell_x0, grid_s[0]);
1645     copy_rvec(dd->comm->cell_x1, grid_s[1]);
1646
1647     if (DDMASTER(dd))
1648     {
1649         snew(grid_r, 2*dd->nnodes);
1650     }
1651
1652     dd_gather(dd, 2*sizeof(rvec), grid_s, DDMASTER(dd) ? grid_r : nullptr);
1653
1654     if (DDMASTER(dd))
1655     {
1656         for (d = 0; d < DIM; d++)
1657         {
1658             for (i = 0; i < DIM; i++)
1659             {
1660                 if (d == i)
1661                 {
1662                     tric[d][i] = 1;
1663                 }
1664                 else
1665                 {
1666                     if (d < ddbox->npbcdim && dd->nc[d] > 1)
1667                     {
1668                         tric[d][i] = box[i][d]/box[i][i];
1669                     }
1670                     else
1671                     {
1672                         tric[d][i] = 0;
1673                     }
1674                 }
1675             }
1676         }
1677         sprintf(fname, "%s_%s.pdb", fn, gmx_step_str(step, buf));
1678         out = gmx_fio_fopen(fname, "w");
1679         gmx_write_pdb_box(out, dd->bScrewPBC ? epbcSCREW : epbcXYZ, box);
1680         a = 1;
1681         for (i = 0; i < dd->nnodes; i++)
1682         {
1683             vol = dd->nnodes/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
1684             for (d = 0; d < DIM; d++)
1685             {
1686                 vol *= grid_r[i*2+1][d] - grid_r[i*2][d];
1687             }
1688             for (z = 0; z < 2; z++)
1689             {
1690                 for (y = 0; y < 2; y++)
1691                 {
1692                     for (x = 0; x < 2; x++)
1693                     {
1694                         cx[XX] = grid_r[i*2+x][XX];
1695                         cx[YY] = grid_r[i*2+y][YY];
1696                         cx[ZZ] = grid_r[i*2+z][ZZ];
1697                         mvmul(tric, cx, r);
1698                         gmx_fprintf_pdb_atomline(out, epdbATOM, a++, "CA", ' ', "GLY", ' ', i+1, ' ',
1699                                                  10*r[XX], 10*r[YY], 10*r[ZZ], 1.0, vol, "");
1700                     }
1701                 }
1702             }
1703             for (d = 0; d < DIM; d++)
1704             {
1705                 for (x = 0; x < 4; x++)
1706                 {
1707                     switch (d)
1708                     {
1709                         case 0: y = 1 + i*8 + 2*x; break;
1710                         case 1: y = 1 + i*8 + 2*x - (x % 2); break;
1711                         case 2: y = 1 + i*8 + x; break;
1712                     }
1713                     fprintf(out, "%6s%5d%5d\n", "CONECT", y, y+(1<<d));
1714                 }
1715             }
1716         }
1717         gmx_fio_fclose(out);
1718         sfree(grid_r);
1719     }
1720 }
1721
1722 void write_dd_pdb(const char *fn, gmx_int64_t step, const char *title,
1723                   const gmx_mtop_t *mtop, t_commrec *cr,
1724                   int natoms, rvec x[], matrix box)
1725 {
1726     char          fname[STRLEN], buf[22];
1727     FILE         *out;
1728     int           i, ii, resnr, c;
1729     const char   *atomname, *resname;
1730     real          b;
1731     gmx_domdec_t *dd;
1732
1733     dd = cr->dd;
1734     if (natoms == -1)
1735     {
1736         natoms = dd->comm->nat[ddnatVSITE];
1737     }
1738
1739     sprintf(fname, "%s_%s_n%d.pdb", fn, gmx_step_str(step, buf), cr->sim_nodeid);
1740
1741     out = gmx_fio_fopen(fname, "w");
1742
1743     fprintf(out, "TITLE     %s\n", title);
1744     gmx_write_pdb_box(out, dd->bScrewPBC ? epbcSCREW : epbcXYZ, box);
1745     int molb = 0;
1746     for (i = 0; i < natoms; i++)
1747     {
1748         ii = dd->gatindex[i];
1749         mtopGetAtomAndResidueName(mtop, ii, &molb, &atomname, &resnr, &resname, nullptr);
1750         if (i < dd->comm->nat[ddnatZONE])
1751         {
1752             c = 0;
1753             while (i >= dd->cgindex[dd->comm->zones.cg_range[c+1]])
1754             {
1755                 c++;
1756             }
1757             b = c;
1758         }
1759         else if (i < dd->comm->nat[ddnatVSITE])
1760         {
1761             b = dd->comm->zones.n;
1762         }
1763         else
1764         {
1765             b = dd->comm->zones.n + 1;
1766         }
1767         gmx_fprintf_pdb_atomline(out, epdbATOM, ii+1, atomname, ' ', resname, ' ', resnr, ' ',
1768                                  10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ], 1.0, b, "");
1769     }
1770     fprintf(out, "TER\n");
1771
1772     gmx_fio_fclose(out);
1773 }
1774
1775 real dd_cutoff_multibody(const gmx_domdec_t *dd)
1776 {
1777     gmx_domdec_comm_t *comm;
1778     int                di;
1779     real               r;
1780
1781     comm = dd->comm;
1782
1783     r = -1;
1784     if (comm->bInterCGBondeds)
1785     {
1786         if (comm->cutoff_mbody > 0)
1787         {
1788             r = comm->cutoff_mbody;
1789         }
1790         else
1791         {
1792             /* cutoff_mbody=0 means we do not have DLB */
1793             r = comm->cellsize_min[dd->dim[0]];
1794             for (di = 1; di < dd->ndim; di++)
1795             {
1796                 r = std::min(r, comm->cellsize_min[dd->dim[di]]);
1797             }
1798             if (comm->bBondComm)
1799             {
1800                 r = std::max(r, comm->cutoff_mbody);
1801             }
1802             else
1803             {
1804                 r = std::min(r, comm->cutoff);
1805             }
1806         }
1807     }
1808
1809     return r;
1810 }
1811
1812 real dd_cutoff_twobody(const gmx_domdec_t *dd)
1813 {
1814     real r_mb;
1815
1816     r_mb = dd_cutoff_multibody(dd);
1817
1818     return std::max(dd->comm->cutoff, r_mb);
1819 }
1820
1821
1822 static void dd_cart_coord2pmecoord(const gmx_domdec_t *dd, const ivec coord,
1823                                    ivec coord_pme)
1824 {
1825     int nc, ntot;
1826
1827     nc   = dd->nc[dd->comm->cartpmedim];
1828     ntot = dd->comm->ntot[dd->comm->cartpmedim];
1829     copy_ivec(coord, coord_pme);
1830     coord_pme[dd->comm->cartpmedim] =
1831         nc + (coord[dd->comm->cartpmedim]*(ntot - nc) + (ntot - nc)/2)/nc;
1832 }
1833
1834 static int ddindex2pmeindex(const gmx_domdec_t *dd, int ddindex)
1835 {
1836     int npp, npme;
1837
1838     npp  = dd->nnodes;
1839     npme = dd->comm->npmenodes;
1840
1841     /* Here we assign a PME node to communicate with this DD node
1842      * by assuming that the major index of both is x.
1843      * We add cr->npmenodes/2 to obtain an even distribution.
1844      */
1845     return (ddindex*npme + npme/2)/npp;
1846 }
1847
1848 static int *dd_interleaved_pme_ranks(const gmx_domdec_t *dd)
1849 {
1850     int *pme_rank;
1851     int  n, i, p0, p1;
1852
1853     snew(pme_rank, dd->comm->npmenodes);
1854     n = 0;
1855     for (i = 0; i < dd->nnodes; i++)
1856     {
1857         p0 = ddindex2pmeindex(dd, i);
1858         p1 = ddindex2pmeindex(dd, i+1);
1859         if (i+1 == dd->nnodes || p1 > p0)
1860         {
1861             if (debug)
1862             {
1863                 fprintf(debug, "pme_rank[%d] = %d\n", n, i+1+n);
1864             }
1865             pme_rank[n] = i + 1 + n;
1866             n++;
1867         }
1868     }
1869
1870     return pme_rank;
1871 }
1872
1873 static int gmx_ddcoord2pmeindex(t_commrec *cr, int x, int y, int z)
1874 {
1875     gmx_domdec_t *dd;
1876     ivec          coords;
1877     int           slab;
1878
1879     dd = cr->dd;
1880     /*
1881        if (dd->comm->bCartesian) {
1882        gmx_ddindex2xyz(dd->nc,ddindex,coords);
1883        dd_coords2pmecoords(dd,coords,coords_pme);
1884        copy_ivec(dd->ntot,nc);
1885        nc[dd->cartpmedim]         -= dd->nc[dd->cartpmedim];
1886        coords_pme[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
1887
1888        slab = (coords_pme[XX]*nc[YY] + coords_pme[YY])*nc[ZZ] + coords_pme[ZZ];
1889        } else {
1890        slab = (ddindex*cr->npmenodes + cr->npmenodes/2)/dd->nnodes;
1891        }
1892      */
1893     coords[XX] = x;
1894     coords[YY] = y;
1895     coords[ZZ] = z;
1896     slab       = ddindex2pmeindex(dd, dd_index(dd->nc, coords));
1897
1898     return slab;
1899 }
1900
1901 static int ddcoord2simnodeid(t_commrec *cr, int x, int y, int z)
1902 {
1903     gmx_domdec_comm_t *comm;
1904     ivec               coords;
1905     int                ddindex, nodeid = -1;
1906
1907     comm = cr->dd->comm;
1908
1909     coords[XX] = x;
1910     coords[YY] = y;
1911     coords[ZZ] = z;
1912     if (comm->bCartesianPP_PME)
1913     {
1914 #if GMX_MPI
1915         MPI_Cart_rank(cr->mpi_comm_mysim, coords, &nodeid);
1916 #endif
1917     }
1918     else
1919     {
1920         ddindex = dd_index(cr->dd->nc, coords);
1921         if (comm->bCartesianPP)
1922         {
1923             nodeid = comm->ddindex2simnodeid[ddindex];
1924         }
1925         else
1926         {
1927             if (comm->pmenodes)
1928             {
1929                 nodeid = ddindex + gmx_ddcoord2pmeindex(cr, x, y, z);
1930             }
1931             else
1932             {
1933                 nodeid = ddindex;
1934             }
1935         }
1936     }
1937
1938     return nodeid;
1939 }
1940
1941 static int dd_simnode2pmenode(const gmx_domdec_t         *dd,
1942                               const t_commrec gmx_unused *cr,
1943                               int                         sim_nodeid)
1944 {
1945     int pmenode = -1;
1946
1947     const gmx_domdec_comm_t *comm = dd->comm;
1948
1949     /* This assumes a uniform x domain decomposition grid cell size */
1950     if (comm->bCartesianPP_PME)
1951     {
1952 #if GMX_MPI
1953         ivec coord, coord_pme;
1954         MPI_Cart_coords(cr->mpi_comm_mysim, sim_nodeid, DIM, coord);
1955         if (coord[comm->cartpmedim] < dd->nc[comm->cartpmedim])
1956         {
1957             /* This is a PP node */
1958             dd_cart_coord2pmecoord(dd, coord, coord_pme);
1959             MPI_Cart_rank(cr->mpi_comm_mysim, coord_pme, &pmenode);
1960         }
1961 #endif
1962     }
1963     else if (comm->bCartesianPP)
1964     {
1965         if (sim_nodeid < dd->nnodes)
1966         {
1967             pmenode = dd->nnodes + ddindex2pmeindex(dd, sim_nodeid);
1968         }
1969     }
1970     else
1971     {
1972         /* This assumes DD cells with identical x coordinates
1973          * are numbered sequentially.
1974          */
1975         if (dd->comm->pmenodes == nullptr)
1976         {
1977             if (sim_nodeid < dd->nnodes)
1978             {
1979                 /* The DD index equals the nodeid */
1980                 pmenode = dd->nnodes + ddindex2pmeindex(dd, sim_nodeid);
1981             }
1982         }
1983         else
1984         {
1985             int i = 0;
1986             while (sim_nodeid > dd->comm->pmenodes[i])
1987             {
1988                 i++;
1989             }
1990             if (sim_nodeid < dd->comm->pmenodes[i])
1991             {
1992                 pmenode = dd->comm->pmenodes[i];
1993             }
1994         }
1995     }
1996
1997     return pmenode;
1998 }
1999
2000 void get_pme_nnodes(const gmx_domdec_t *dd,
2001                     int *npmenodes_x, int *npmenodes_y)
2002 {
2003     if (dd != nullptr)
2004     {
2005         *npmenodes_x = dd->comm->npmenodes_x;
2006         *npmenodes_y = dd->comm->npmenodes_y;
2007     }
2008     else
2009     {
2010         *npmenodes_x = 1;
2011         *npmenodes_y = 1;
2012     }
2013 }
2014
2015 std::vector<int> get_pme_ddranks(t_commrec *cr, int pmenodeid)
2016 {
2017     gmx_domdec_t *dd;
2018     int           x, y, z;
2019     ivec          coord, coord_pme;
2020
2021     dd = cr->dd;
2022
2023     std::vector<int> ddranks;
2024     ddranks.reserve((dd->nnodes+cr->npmenodes-1)/cr->npmenodes);
2025
2026     for (x = 0; x < dd->nc[XX]; x++)
2027     {
2028         for (y = 0; y < dd->nc[YY]; y++)
2029         {
2030             for (z = 0; z < dd->nc[ZZ]; z++)
2031             {
2032                 if (dd->comm->bCartesianPP_PME)
2033                 {
2034                     coord[XX] = x;
2035                     coord[YY] = y;
2036                     coord[ZZ] = z;
2037                     dd_cart_coord2pmecoord(dd, coord, coord_pme);
2038                     if (dd->ci[XX] == coord_pme[XX] &&
2039                         dd->ci[YY] == coord_pme[YY] &&
2040                         dd->ci[ZZ] == coord_pme[ZZ])
2041                     {
2042                         ddranks.push_back(ddcoord2simnodeid(cr, x, y, z));
2043                     }
2044                 }
2045                 else
2046                 {
2047                     /* The slab corresponds to the nodeid in the PME group */
2048                     if (gmx_ddcoord2pmeindex(cr, x, y, z) == pmenodeid)
2049                     {
2050                         ddranks.push_back(ddcoord2simnodeid(cr, x, y, z));
2051                     }
2052                 }
2053             }
2054         }
2055     }
2056     return ddranks;
2057 }
2058
2059 static gmx_bool receive_vir_ener(const gmx_domdec_t *dd, const t_commrec *cr)
2060 {
2061     gmx_bool bReceive = TRUE;
2062
2063     if (cr->npmenodes < dd->nnodes)
2064     {
2065         gmx_domdec_comm_t *comm = dd->comm;
2066         if (comm->bCartesianPP_PME)
2067         {
2068 #if GMX_MPI
2069             int  pmenode = dd_simnode2pmenode(dd, cr, cr->sim_nodeid);
2070             ivec coords;
2071             MPI_Cart_coords(cr->mpi_comm_mysim, cr->sim_nodeid, DIM, coords);
2072             coords[comm->cartpmedim]++;
2073             if (coords[comm->cartpmedim] < dd->nc[comm->cartpmedim])
2074             {
2075                 int rank;
2076                 MPI_Cart_rank(cr->mpi_comm_mysim, coords, &rank);
2077                 if (dd_simnode2pmenode(dd, cr, rank) == pmenode)
2078                 {
2079                     /* This is not the last PP node for pmenode */
2080                     bReceive = FALSE;
2081                 }
2082             }
2083 #else
2084             GMX_RELEASE_ASSERT(false, "Without MPI we should not have Cartesian PP-PME with #PMEnodes < #DDnodes");
2085 #endif
2086         }
2087         else
2088         {
2089             int pmenode = dd_simnode2pmenode(dd, cr, cr->sim_nodeid);
2090             if (cr->sim_nodeid+1 < cr->nnodes &&
2091                 dd_simnode2pmenode(dd, cr, cr->sim_nodeid+1) == pmenode)
2092             {
2093                 /* This is not the last PP node for pmenode */
2094                 bReceive = FALSE;
2095             }
2096         }
2097     }
2098
2099     return bReceive;
2100 }
2101
2102 static void set_zones_ncg_home(gmx_domdec_t *dd)
2103 {
2104     gmx_domdec_zones_t *zones;
2105     int                 i;
2106
2107     zones = &dd->comm->zones;
2108
2109     zones->cg_range[0] = 0;
2110     for (i = 1; i < zones->n+1; i++)
2111     {
2112         zones->cg_range[i] = dd->ncg_home;
2113     }
2114     /* zone_ncg1[0] should always be equal to ncg_home */
2115     dd->comm->zone_ncg1[0] = dd->ncg_home;
2116 }
2117
2118 static void rebuild_cgindex(gmx_domdec_t *dd,
2119                             const int *gcgs_index, const t_state *state)
2120 {
2121     int * gmx_restrict dd_cg_gl = dd->index_gl;
2122     int * gmx_restrict cgindex  = dd->cgindex;
2123     int                nat      = 0;
2124
2125     /* Copy back the global charge group indices from state
2126      * and rebuild the local charge group to atom index.
2127      */
2128     cgindex[0] = nat;
2129     for (unsigned int i = 0; i < state->cg_gl.size(); i++)
2130     {
2131         cgindex[i]  = nat;
2132         int cg_gl   = state->cg_gl[i];
2133         dd_cg_gl[i] = cg_gl;
2134         nat        += gcgs_index[cg_gl+1] - gcgs_index[cg_gl];
2135     }
2136     cgindex[state->cg_gl.size()] = nat;
2137
2138     dd->ncg_home = state->cg_gl.size();
2139     dd->nat_home = nat;
2140
2141     set_zones_ncg_home(dd);
2142 }
2143
2144 static int ddcginfo(const cginfo_mb_t *cginfo_mb, int cg)
2145 {
2146     while (cg >= cginfo_mb->cg_end)
2147     {
2148         cginfo_mb++;
2149     }
2150
2151     return cginfo_mb->cginfo[(cg - cginfo_mb->cg_start) % cginfo_mb->cg_mod];
2152 }
2153
2154 static void dd_set_cginfo(int *index_gl, int cg0, int cg1,
2155                           t_forcerec *fr, char *bLocalCG)
2156 {
2157     cginfo_mb_t *cginfo_mb;
2158     int         *cginfo;
2159     int          cg;
2160
2161     if (fr != nullptr)
2162     {
2163         cginfo_mb = fr->cginfo_mb;
2164         cginfo    = fr->cginfo;
2165
2166         for (cg = cg0; cg < cg1; cg++)
2167         {
2168             cginfo[cg] = ddcginfo(cginfo_mb, index_gl[cg]);
2169         }
2170     }
2171
2172     if (bLocalCG != nullptr)
2173     {
2174         for (cg = cg0; cg < cg1; cg++)
2175         {
2176             bLocalCG[index_gl[cg]] = TRUE;
2177         }
2178     }
2179 }
2180
2181 static void make_dd_indices(gmx_domdec_t *dd,
2182                             const int *gcgs_index, int cg_start)
2183 {
2184     int          nzone, zone, zone1, cg0, cg1, cg1_p1, cg, cg_gl, a, a_gl;
2185     int         *zone2cg, *zone_ncg1, *index_gl, *gatindex;
2186     gmx_bool     bCGs;
2187
2188     if (dd->nat_tot > dd->gatindex_nalloc)
2189     {
2190         dd->gatindex_nalloc = over_alloc_dd(dd->nat_tot);
2191         srenew(dd->gatindex, dd->gatindex_nalloc);
2192     }
2193
2194     nzone      = dd->comm->zones.n;
2195     zone2cg    = dd->comm->zones.cg_range;
2196     zone_ncg1  = dd->comm->zone_ncg1;
2197     index_gl   = dd->index_gl;
2198     gatindex   = dd->gatindex;
2199     bCGs       = dd->comm->bCGs;
2200
2201     if (zone2cg[1] != dd->ncg_home)
2202     {
2203         gmx_incons("dd->ncg_zone is not up to date");
2204     }
2205
2206     /* Make the local to global and global to local atom index */
2207     a = dd->cgindex[cg_start];
2208     for (zone = 0; zone < nzone; zone++)
2209     {
2210         if (zone == 0)
2211         {
2212             cg0 = cg_start;
2213         }
2214         else
2215         {
2216             cg0 = zone2cg[zone];
2217         }
2218         cg1    = zone2cg[zone+1];
2219         cg1_p1 = cg0 + zone_ncg1[zone];
2220
2221         for (cg = cg0; cg < cg1; cg++)
2222         {
2223             zone1 = zone;
2224             if (cg >= cg1_p1)
2225             {
2226                 /* Signal that this cg is from more than one pulse away */
2227                 zone1 += nzone;
2228             }
2229             cg_gl = index_gl[cg];
2230             if (bCGs)
2231             {
2232                 for (a_gl = gcgs_index[cg_gl]; a_gl < gcgs_index[cg_gl+1]; a_gl++)
2233                 {
2234                     gatindex[a] = a_gl;
2235                     ga2la_set(dd->ga2la, a_gl, a, zone1);
2236                     a++;
2237                 }
2238             }
2239             else
2240             {
2241                 gatindex[a] = cg_gl;
2242                 ga2la_set(dd->ga2la, cg_gl, a, zone1);
2243                 a++;
2244             }
2245         }
2246     }
2247 }
2248
2249 static int check_bLocalCG(gmx_domdec_t *dd, int ncg_sys, const char *bLocalCG,
2250                           const char *where)
2251 {
2252     int i, ngl, nerr;
2253
2254     nerr = 0;
2255     if (bLocalCG == nullptr)
2256     {
2257         return nerr;
2258     }
2259     for (i = 0; i < dd->ncg_tot; i++)
2260     {
2261         if (!bLocalCG[dd->index_gl[i]])
2262         {
2263             fprintf(stderr,
2264                     "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);
2265             nerr++;
2266         }
2267     }
2268     ngl = 0;
2269     for (i = 0; i < ncg_sys; i++)
2270     {
2271         if (bLocalCG[i])
2272         {
2273             ngl++;
2274         }
2275     }
2276     if (ngl != dd->ncg_tot)
2277     {
2278         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);
2279         nerr++;
2280     }
2281
2282     return nerr;
2283 }
2284
2285 static void check_index_consistency(gmx_domdec_t *dd,
2286                                     int natoms_sys, int ncg_sys,
2287                                     const char *where)
2288 {
2289     int   nerr, ngl, i, a, cell;
2290     int  *have;
2291
2292     nerr = 0;
2293
2294     if (dd->comm->DD_debug > 1)
2295     {
2296         snew(have, natoms_sys);
2297         for (a = 0; a < dd->nat_tot; a++)
2298         {
2299             if (have[dd->gatindex[a]] > 0)
2300             {
2301                 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);
2302             }
2303             else
2304             {
2305                 have[dd->gatindex[a]] = a + 1;
2306             }
2307         }
2308         sfree(have);
2309     }
2310
2311     snew(have, dd->nat_tot);
2312
2313     ngl  = 0;
2314     for (i = 0; i < natoms_sys; i++)
2315     {
2316         if (ga2la_get(dd->ga2la, i, &a, &cell))
2317         {
2318             if (a >= dd->nat_tot)
2319             {
2320                 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);
2321                 nerr++;
2322             }
2323             else
2324             {
2325                 have[a] = 1;
2326                 if (dd->gatindex[a] != i)
2327                 {
2328                     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);
2329                     nerr++;
2330                 }
2331             }
2332             ngl++;
2333         }
2334     }
2335     if (ngl != dd->nat_tot)
2336     {
2337         fprintf(stderr,
2338                 "DD rank %d, %s: %d global atom indices, %d local atoms\n",
2339                 dd->rank, where, ngl, dd->nat_tot);
2340     }
2341     for (a = 0; a < dd->nat_tot; a++)
2342     {
2343         if (have[a] == 0)
2344         {
2345             fprintf(stderr,
2346                     "DD rank %d, %s: local atom %d, global %d has no global index\n",
2347                     dd->rank, where, a+1, dd->gatindex[a]+1);
2348         }
2349     }
2350     sfree(have);
2351
2352     nerr += check_bLocalCG(dd, ncg_sys, dd->comm->bLocalCG, where);
2353
2354     if (nerr > 0)
2355     {
2356         gmx_fatal(FARGS, "DD rank %d, %s: %d atom/cg index inconsistencies",
2357                   dd->rank, where, nerr);
2358     }
2359 }
2360
2361 static void clear_dd_indices(gmx_domdec_t *dd, int cg_start, int a_start)
2362 {
2363     int   i;
2364     char *bLocalCG;
2365
2366     if (a_start == 0)
2367     {
2368         /* Clear the whole list without searching */
2369         ga2la_clear(dd->ga2la);
2370     }
2371     else
2372     {
2373         for (i = a_start; i < dd->nat_tot; i++)
2374         {
2375             ga2la_del(dd->ga2la, dd->gatindex[i]);
2376         }
2377     }
2378
2379     bLocalCG = dd->comm->bLocalCG;
2380     if (bLocalCG)
2381     {
2382         for (i = cg_start; i < dd->ncg_tot; i++)
2383         {
2384             bLocalCG[dd->index_gl[i]] = FALSE;
2385         }
2386     }
2387
2388     dd_clear_local_vsite_indices(dd);
2389
2390     if (dd->constraints)
2391     {
2392         dd_clear_local_constraint_indices(dd);
2393     }
2394 }
2395
2396 /* This function should be used for moving the domain boudaries during DLB,
2397  * for obtaining the minimum cell size. It checks the initially set limit
2398  * comm->cellsize_min, for bonded and initial non-bonded cut-offs,
2399  * and, possibly, a longer cut-off limit set for PME load balancing.
2400  */
2401 static real cellsize_min_dlb(gmx_domdec_comm_t *comm, int dim_ind, int dim)
2402 {
2403     real cellsize_min;
2404
2405     cellsize_min = comm->cellsize_min[dim];
2406
2407     if (!comm->bVacDLBNoLimit)
2408     {
2409         /* The cut-off might have changed, e.g. by PME load balacning,
2410          * from the value used to set comm->cellsize_min, so check it.
2411          */
2412         cellsize_min = std::max(cellsize_min, comm->cutoff/comm->cd[dim_ind].np_dlb);
2413
2414         if (comm->bPMELoadBalDLBLimits)
2415         {
2416             /* Check for the cut-off limit set by the PME load balancing */
2417             cellsize_min = std::max(cellsize_min, comm->PMELoadBal_max_cutoff/comm->cd[dim_ind].np_dlb);
2418         }
2419     }
2420
2421     return cellsize_min;
2422 }
2423
2424 static real grid_jump_limit(gmx_domdec_comm_t *comm, real cutoff,
2425                             int dim_ind)
2426 {
2427     real grid_jump_limit;
2428
2429     /* The distance between the boundaries of cells at distance
2430      * x+-1,y+-1 or y+-1,z+-1 is limited by the cut-off restrictions
2431      * and by the fact that cells should not be shifted by more than
2432      * half their size, such that cg's only shift by one cell
2433      * at redecomposition.
2434      */
2435     grid_jump_limit = comm->cellsize_limit;
2436     if (!comm->bVacDLBNoLimit)
2437     {
2438         if (comm->bPMELoadBalDLBLimits)
2439         {
2440             cutoff = std::max(cutoff, comm->PMELoadBal_max_cutoff);
2441         }
2442         grid_jump_limit = std::max(grid_jump_limit,
2443                                    cutoff/comm->cd[dim_ind].np);
2444     }
2445
2446     return grid_jump_limit;
2447 }
2448
2449 static gmx_bool check_grid_jump(gmx_int64_t     step,
2450                                 gmx_domdec_t   *dd,
2451                                 real            cutoff,
2452                                 gmx_ddbox_t    *ddbox,
2453                                 gmx_bool        bFatal)
2454 {
2455     gmx_domdec_comm_t *comm;
2456     int                d, dim;
2457     real               limit, bfac;
2458     gmx_bool           bInvalid;
2459
2460     bInvalid = FALSE;
2461
2462     comm = dd->comm;
2463
2464     for (d = 1; d < dd->ndim; d++)
2465     {
2466         dim   = dd->dim[d];
2467         limit = grid_jump_limit(comm, cutoff, d);
2468         bfac  = ddbox->box_size[dim];
2469         if (ddbox->tric_dir[dim])
2470         {
2471             bfac *= ddbox->skew_fac[dim];
2472         }
2473         if ((comm->cell_f1[d] - comm->cell_f_max0[d])*bfac <  limit ||
2474                                                               (comm->cell_f0[d] - comm->cell_f_min1[d])*bfac > -limit)
2475         {
2476             bInvalid = TRUE;
2477
2478             if (bFatal)
2479             {
2480                 char buf[22];
2481
2482                 /* This error should never be triggered under normal
2483                  * circumstances, but you never know ...
2484                  */
2485                 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.",
2486                           gmx_step_str(step, buf),
2487                           dim2char(dim), dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
2488             }
2489         }
2490     }
2491
2492     return bInvalid;
2493 }
2494
2495 static int dd_load_count(gmx_domdec_comm_t *comm)
2496 {
2497     return (comm->eFlop ? comm->flop_n : comm->cycl_n[ddCyclF]);
2498 }
2499
2500 static float dd_force_load(gmx_domdec_comm_t *comm)
2501 {
2502     float load;
2503
2504     if (comm->eFlop)
2505     {
2506         load = comm->flop;
2507         if (comm->eFlop > 1)
2508         {
2509             load *= 1.0 + (comm->eFlop - 1)*(0.1*rand()/RAND_MAX - 0.05);
2510         }
2511     }
2512     else
2513     {
2514         load = comm->cycl[ddCyclF];
2515         if (comm->cycl_n[ddCyclF] > 1)
2516         {
2517             /* Subtract the maximum of the last n cycle counts
2518              * to get rid of possible high counts due to other sources,
2519              * for instance system activity, that would otherwise
2520              * affect the dynamic load balancing.
2521              */
2522             load -= comm->cycl_max[ddCyclF];
2523         }
2524
2525 #if GMX_MPI
2526         if (comm->cycl_n[ddCyclWaitGPU] && comm->nrank_gpu_shared > 1)
2527         {
2528             float gpu_wait, gpu_wait_sum;
2529
2530             gpu_wait = comm->cycl[ddCyclWaitGPU];
2531             if (comm->cycl_n[ddCyclF] > 1)
2532             {
2533                 /* We should remove the WaitGPU time of the same MD step
2534                  * as the one with the maximum F time, since the F time
2535                  * and the wait time are not independent.
2536                  * Furthermore, the step for the max F time should be chosen
2537                  * the same on all ranks that share the same GPU.
2538                  * But to keep the code simple, we remove the average instead.
2539                  * The main reason for artificially long times at some steps
2540                  * is spurious CPU activity or MPI time, so we don't expect
2541                  * that changes in the GPU wait time matter a lot here.
2542                  */
2543                 gpu_wait *= (comm->cycl_n[ddCyclF] - 1)/(float)comm->cycl_n[ddCyclF];
2544             }
2545             /* Sum the wait times over the ranks that share the same GPU */
2546             MPI_Allreduce(&gpu_wait, &gpu_wait_sum, 1, MPI_FLOAT, MPI_SUM,
2547                           comm->mpi_comm_gpu_shared);
2548             /* Replace the wait time by the average over the ranks */
2549             load += -gpu_wait + gpu_wait_sum/comm->nrank_gpu_shared;
2550         }
2551 #endif
2552     }
2553
2554     return load;
2555 }
2556
2557 static void set_slb_pme_dim_f(gmx_domdec_t *dd, int dim, real **dim_f)
2558 {
2559     gmx_domdec_comm_t *comm;
2560     int                i;
2561
2562     comm = dd->comm;
2563
2564     snew(*dim_f, dd->nc[dim]+1);
2565     (*dim_f)[0] = 0;
2566     for (i = 1; i < dd->nc[dim]; i++)
2567     {
2568         if (comm->slb_frac[dim])
2569         {
2570             (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
2571         }
2572         else
2573         {
2574             (*dim_f)[i] = (real)i/(real)dd->nc[dim];
2575         }
2576     }
2577     (*dim_f)[dd->nc[dim]] = 1;
2578 }
2579
2580 static void init_ddpme(gmx_domdec_t *dd, gmx_ddpme_t *ddpme, int dimind)
2581 {
2582     int  pmeindex, slab, nso, i;
2583     ivec xyz;
2584
2585     if (dimind == 0 && dd->dim[0] == YY && dd->comm->npmenodes_x == 1)
2586     {
2587         ddpme->dim = YY;
2588     }
2589     else
2590     {
2591         ddpme->dim = dimind;
2592     }
2593     ddpme->dim_match = (ddpme->dim == dd->dim[dimind]);
2594
2595     ddpme->nslab = (ddpme->dim == 0 ?
2596                     dd->comm->npmenodes_x :
2597                     dd->comm->npmenodes_y);
2598
2599     if (ddpme->nslab <= 1)
2600     {
2601         return;
2602     }
2603
2604     nso = dd->comm->npmenodes/ddpme->nslab;
2605     /* Determine for each PME slab the PP location range for dimension dim */
2606     snew(ddpme->pp_min, ddpme->nslab);
2607     snew(ddpme->pp_max, ddpme->nslab);
2608     for (slab = 0; slab < ddpme->nslab; slab++)
2609     {
2610         ddpme->pp_min[slab] = dd->nc[dd->dim[dimind]] - 1;
2611         ddpme->pp_max[slab] = 0;
2612     }
2613     for (i = 0; i < dd->nnodes; i++)
2614     {
2615         ddindex2xyz(dd->nc, i, xyz);
2616         /* For y only use our y/z slab.
2617          * This assumes that the PME x grid size matches the DD grid size.
2618          */
2619         if (dimind == 0 || xyz[XX] == dd->ci[XX])
2620         {
2621             pmeindex = ddindex2pmeindex(dd, i);
2622             if (dimind == 0)
2623             {
2624                 slab = pmeindex/nso;
2625             }
2626             else
2627             {
2628                 slab = pmeindex % ddpme->nslab;
2629             }
2630             ddpme->pp_min[slab] = std::min(ddpme->pp_min[slab], xyz[dimind]);
2631             ddpme->pp_max[slab] = std::max(ddpme->pp_max[slab], xyz[dimind]);
2632         }
2633     }
2634
2635     set_slb_pme_dim_f(dd, ddpme->dim, &ddpme->slb_dim_f);
2636 }
2637
2638 int dd_pme_maxshift_x(const gmx_domdec_t *dd)
2639 {
2640     if (dd->comm->ddpme[0].dim == XX)
2641     {
2642         return dd->comm->ddpme[0].maxshift;
2643     }
2644     else
2645     {
2646         return 0;
2647     }
2648 }
2649
2650 int dd_pme_maxshift_y(const gmx_domdec_t *dd)
2651 {
2652     if (dd->comm->ddpme[0].dim == YY)
2653     {
2654         return dd->comm->ddpme[0].maxshift;
2655     }
2656     else if (dd->comm->npmedecompdim >= 2 && dd->comm->ddpme[1].dim == YY)
2657     {
2658         return dd->comm->ddpme[1].maxshift;
2659     }
2660     else
2661     {
2662         return 0;
2663     }
2664 }
2665
2666 static void set_pme_maxshift(gmx_domdec_t *dd, gmx_ddpme_t *ddpme,
2667                              gmx_bool bUniform, const gmx_ddbox_t *ddbox,
2668                              const real *cell_f)
2669 {
2670     gmx_domdec_comm_t *comm;
2671     int                nc, ns, s;
2672     int               *xmin, *xmax;
2673     real               range, pme_boundary;
2674     int                sh;
2675
2676     comm = dd->comm;
2677     nc   = dd->nc[ddpme->dim];
2678     ns   = ddpme->nslab;
2679
2680     if (!ddpme->dim_match)
2681     {
2682         /* PP decomposition is not along dim: the worst situation */
2683         sh = ns/2;
2684     }
2685     else if (ns <= 3 || (bUniform && ns == nc))
2686     {
2687         /* The optimal situation */
2688         sh = 1;
2689     }
2690     else
2691     {
2692         /* We need to check for all pme nodes which nodes they
2693          * could possibly need to communicate with.
2694          */
2695         xmin = ddpme->pp_min;
2696         xmax = ddpme->pp_max;
2697         /* Allow for atoms to be maximally 2/3 times the cut-off
2698          * out of their DD cell. This is a reasonable balance between
2699          * between performance and support for most charge-group/cut-off
2700          * combinations.
2701          */
2702         range  = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
2703         /* Avoid extra communication when we are exactly at a boundary */
2704         range *= 0.999;
2705
2706         sh = 1;
2707         for (s = 0; s < ns; s++)
2708         {
2709             /* PME slab s spreads atoms between box frac. s/ns and (s+1)/ns */
2710             pme_boundary = (real)s/ns;
2711             while (sh+1 < ns &&
2712                    ((s-(sh+1) >= 0 &&
2713                      cell_f[xmax[s-(sh+1)   ]+1]     + range > pme_boundary) ||
2714                     (s-(sh+1) <  0 &&
2715                      cell_f[xmax[s-(sh+1)+ns]+1] - 1 + range > pme_boundary)))
2716             {
2717                 sh++;
2718             }
2719             pme_boundary = (real)(s+1)/ns;
2720             while (sh+1 < ns &&
2721                    ((s+(sh+1) <  ns &&
2722                      cell_f[xmin[s+(sh+1)   ]  ]     - range < pme_boundary) ||
2723                     (s+(sh+1) >= ns &&
2724                      cell_f[xmin[s+(sh+1)-ns]  ] + 1 - range < pme_boundary)))
2725             {
2726                 sh++;
2727             }
2728         }
2729     }
2730
2731     ddpme->maxshift = sh;
2732
2733     if (debug)
2734     {
2735         fprintf(debug, "PME slab communication range for dim %d is %d\n",
2736                 ddpme->dim, ddpme->maxshift);
2737     }
2738 }
2739
2740 static void check_box_size(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
2741 {
2742     int d, dim;
2743
2744     for (d = 0; d < dd->ndim; d++)
2745     {
2746         dim = dd->dim[d];
2747         if (dim < ddbox->nboundeddim &&
2748             ddbox->box_size[dim]*ddbox->skew_fac[dim] <
2749             dd->nc[dim]*dd->comm->cellsize_limit*DD_CELL_MARGIN)
2750         {
2751             gmx_fatal(FARGS, "The %c-size of the box (%f) times the triclinic skew factor (%f) is smaller than the number of DD cells (%d) times the smallest allowed cell size (%f)\n",
2752                       dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim],
2753                       dd->nc[dim], dd->comm->cellsize_limit);
2754         }
2755     }
2756 }
2757
2758 enum {
2759     setcellsizeslbLOCAL, setcellsizeslbMASTER, setcellsizeslbPULSE_ONLY
2760 };
2761
2762 /* Set the domain boundaries. Use for static (or no) load balancing,
2763  * and also for the starting state for dynamic load balancing.
2764  * setmode determine if and where the boundaries are stored, use enum above.
2765  * Returns the number communication pulses in npulse.
2766  */
2767 static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, const gmx_ddbox_t *ddbox,
2768                                   int setmode, ivec npulse)
2769 {
2770     gmx_domdec_comm_t *comm;
2771     int                d, j;
2772     rvec               cellsize_min;
2773     real              *cell_x, cell_dx, cellsize;
2774
2775     comm = dd->comm;
2776
2777     for (d = 0; d < DIM; d++)
2778     {
2779         cellsize_min[d] = ddbox->box_size[d]*ddbox->skew_fac[d];
2780         npulse[d]       = 1;
2781         if (dd->nc[d] == 1 || comm->slb_frac[d] == nullptr)
2782         {
2783             /* Uniform grid */
2784             cell_dx = ddbox->box_size[d]/dd->nc[d];
2785             switch (setmode)
2786             {
2787                 case setcellsizeslbMASTER:
2788                     for (j = 0; j < dd->nc[d]+1; j++)
2789                     {
2790                         dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
2791                     }
2792                     break;
2793                 case setcellsizeslbLOCAL:
2794                     comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d]  )*cell_dx;
2795                     comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
2796                     break;
2797                 default:
2798                     break;
2799             }
2800             cellsize = cell_dx*ddbox->skew_fac[d];
2801             while (cellsize*npulse[d] < comm->cutoff)
2802             {
2803                 npulse[d]++;
2804             }
2805             cellsize_min[d] = cellsize;
2806         }
2807         else
2808         {
2809             /* Statically load balanced grid */
2810             /* Also when we are not doing a master distribution we determine
2811              * all cell borders in a loop to obtain identical values
2812              * to the master distribution case and to determine npulse.
2813              */
2814             if (setmode == setcellsizeslbMASTER)
2815             {
2816                 cell_x = dd->ma->cell_x[d];
2817             }
2818             else
2819             {
2820                 snew(cell_x, dd->nc[d]+1);
2821             }
2822             cell_x[0] = ddbox->box0[d];
2823             for (j = 0; j < dd->nc[d]; j++)
2824             {
2825                 cell_dx     = ddbox->box_size[d]*comm->slb_frac[d][j];
2826                 cell_x[j+1] = cell_x[j] + cell_dx;
2827                 cellsize    = cell_dx*ddbox->skew_fac[d];
2828                 while (cellsize*npulse[d] < comm->cutoff &&
2829                        npulse[d] < dd->nc[d]-1)
2830                 {
2831                     npulse[d]++;
2832                 }
2833                 cellsize_min[d] = std::min(cellsize_min[d], cellsize);
2834             }
2835             if (setmode == setcellsizeslbLOCAL)
2836             {
2837                 comm->cell_x0[d] = cell_x[dd->ci[d]];
2838                 comm->cell_x1[d] = cell_x[dd->ci[d]+1];
2839             }
2840             if (setmode != setcellsizeslbMASTER)
2841             {
2842                 sfree(cell_x);
2843             }
2844         }
2845         /* The following limitation is to avoid that a cell would receive
2846          * some of its own home charge groups back over the periodic boundary.
2847          * Double charge groups cause trouble with the global indices.
2848          */
2849         if (d < ddbox->npbcdim &&
2850             dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
2851         {
2852             char error_string[STRLEN];
2853
2854             sprintf(error_string,
2855                     "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",
2856                     dim2char(d), ddbox->box_size[d], ddbox->skew_fac[d],
2857                     comm->cutoff,
2858                     dd->nc[d], dd->nc[d],
2859                     dd->nnodes > dd->nc[d] ? "cells" : "ranks");
2860
2861             if (setmode == setcellsizeslbLOCAL)
2862             {
2863                 gmx_fatal_collective(FARGS, dd->mpi_comm_all, DDMASTER(dd),
2864                                      error_string);
2865             }
2866             else
2867             {
2868                 gmx_fatal(FARGS, error_string);
2869             }
2870         }
2871     }
2872
2873     if (!isDlbOn(comm))
2874     {
2875         copy_rvec(cellsize_min, comm->cellsize_min);
2876     }
2877
2878     for (d = 0; d < comm->npmedecompdim; d++)
2879     {
2880         set_pme_maxshift(dd, &comm->ddpme[d],
2881                          comm->slb_frac[dd->dim[d]] == nullptr, ddbox,
2882                          comm->ddpme[d].slb_dim_f);
2883     }
2884 }
2885
2886
2887 static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
2888                                                   int d, int dim, domdec_root_t *root,
2889                                                   const gmx_ddbox_t *ddbox,
2890                                                   gmx_bool bUniform, gmx_int64_t step, real cellsize_limit_f, int range[])
2891 {
2892     gmx_domdec_comm_t *comm;
2893     int                ncd, i, j, nmin, nmin_old;
2894     gmx_bool           bLimLo, bLimHi;
2895     real              *cell_size;
2896     real               fac, halfway, cellsize_limit_f_i, region_size;
2897     gmx_bool           bPBC, bLastHi = FALSE;
2898     int                nrange[] = {range[0], range[1]};
2899
2900     region_size = root->cell_f[range[1]]-root->cell_f[range[0]];
2901
2902     comm = dd->comm;
2903
2904     ncd = dd->nc[dim];
2905
2906     bPBC = (dim < ddbox->npbcdim);
2907
2908     cell_size = root->buf_ncd;
2909
2910     if (debug)
2911     {
2912         fprintf(debug, "enforce_limits: %d %d\n", range[0], range[1]);
2913     }
2914
2915     /* First we need to check if the scaling does not make cells
2916      * smaller than the smallest allowed size.
2917      * We need to do this iteratively, since if a cell is too small,
2918      * it needs to be enlarged, which makes all the other cells smaller,
2919      * which could in turn make another cell smaller than allowed.
2920      */
2921     for (i = range[0]; i < range[1]; i++)
2922     {
2923         root->bCellMin[i] = FALSE;
2924     }
2925     nmin = 0;
2926     do
2927     {
2928         nmin_old = nmin;
2929         /* We need the total for normalization */
2930         fac = 0;
2931         for (i = range[0]; i < range[1]; i++)
2932         {
2933             if (root->bCellMin[i] == FALSE)
2934             {
2935                 fac += cell_size[i];
2936             }
2937         }
2938         fac = ( region_size - nmin*cellsize_limit_f)/fac; /* substracting cells already set to cellsize_limit_f */
2939         /* Determine the cell boundaries */
2940         for (i = range[0]; i < range[1]; i++)
2941         {
2942             if (root->bCellMin[i] == FALSE)
2943             {
2944                 cell_size[i] *= fac;
2945                 if (!bPBC && (i == 0 || i == dd->nc[dim] -1))
2946                 {
2947                     cellsize_limit_f_i = 0;
2948                 }
2949                 else
2950                 {
2951                     cellsize_limit_f_i = cellsize_limit_f;
2952                 }
2953                 if (cell_size[i] < cellsize_limit_f_i)
2954                 {
2955                     root->bCellMin[i] = TRUE;
2956                     cell_size[i]      = cellsize_limit_f_i;
2957                     nmin++;
2958                 }
2959             }
2960             root->cell_f[i+1] = root->cell_f[i] + cell_size[i];
2961         }
2962     }
2963     while (nmin > nmin_old);
2964
2965     i            = range[1]-1;
2966     cell_size[i] = root->cell_f[i+1] - root->cell_f[i];
2967     /* For this check we should not use DD_CELL_MARGIN,
2968      * but a slightly smaller factor,
2969      * since rounding could get use below the limit.
2970      */
2971     if (bPBC && cell_size[i] < cellsize_limit_f*DD_CELL_MARGIN2/DD_CELL_MARGIN)
2972     {
2973         char buf[22];
2974         gmx_fatal(FARGS, "step %s: the dynamic load balancing could not balance dimension %c: box size %f, triclinic skew factor %f, #cells %d, minimum cell size %f\n",
2975                   gmx_step_str(step, buf),
2976                   dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim],
2977                   ncd, comm->cellsize_min[dim]);
2978     }
2979
2980     root->bLimited = (nmin > 0) || (range[0] > 0) || (range[1] < ncd);
2981
2982     if (!bUniform)
2983     {
2984         /* Check if the boundary did not displace more than halfway
2985          * each of the cells it bounds, as this could cause problems,
2986          * especially when the differences between cell sizes are large.
2987          * If changes are applied, they will not make cells smaller
2988          * than the cut-off, as we check all the boundaries which
2989          * might be affected by a change and if the old state was ok,
2990          * the cells will at most be shrunk back to their old size.
2991          */
2992         for (i = range[0]+1; i < range[1]; i++)
2993         {
2994             halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i-1]);
2995             if (root->cell_f[i] < halfway)
2996             {
2997                 root->cell_f[i] = halfway;
2998                 /* Check if the change also causes shifts of the next boundaries */
2999                 for (j = i+1; j < range[1]; j++)
3000                 {
3001                     if (root->cell_f[j] < root->cell_f[j-1] + cellsize_limit_f)
3002                     {
3003                         root->cell_f[j] =  root->cell_f[j-1] + cellsize_limit_f;
3004                     }
3005                 }
3006             }
3007             halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i+1]);
3008             if (root->cell_f[i] > halfway)
3009             {
3010                 root->cell_f[i] = halfway;
3011                 /* Check if the change also causes shifts of the next boundaries */
3012                 for (j = i-1; j >= range[0]+1; j--)
3013                 {
3014                     if (root->cell_f[j] > root->cell_f[j+1] - cellsize_limit_f)
3015                     {
3016                         root->cell_f[j] = root->cell_f[j+1] - cellsize_limit_f;
3017                     }
3018                 }
3019             }
3020         }
3021     }
3022
3023     /* nrange is defined as [lower, upper) range for new call to enforce_limits */
3024     /* find highest violation of LimLo (a) and the following violation of LimHi (thus the lowest following) (b)
3025      * then call enforce_limits for (oldb,a), (a,b). In the next step: (b,nexta). oldb and nexta can be the boundaries.
3026      * for a and b nrange is used */
3027     if (d > 0)
3028     {
3029         /* Take care of the staggering of the cell boundaries */
3030         if (bUniform)
3031         {
3032             for (i = range[0]; i < range[1]; i++)
3033             {
3034                 root->cell_f_max0[i] = root->cell_f[i];
3035                 root->cell_f_min1[i] = root->cell_f[i+1];
3036             }
3037         }
3038         else
3039         {
3040             for (i = range[0]+1; i < range[1]; i++)
3041             {
3042                 bLimLo = (root->cell_f[i] < root->bound_min[i]);
3043                 bLimHi = (root->cell_f[i] > root->bound_max[i]);
3044                 if (bLimLo && bLimHi)
3045                 {
3046                     /* Both limits violated, try the best we can */
3047                     /* For this case we split the original range (range) in two parts and care about the other limitiations in the next iteration. */
3048                     root->cell_f[i] = 0.5*(root->bound_min[i] + root->bound_max[i]);
3049                     nrange[0]       = range[0];
3050                     nrange[1]       = i;
3051                     dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3052
3053                     nrange[0] = i;
3054                     nrange[1] = range[1];
3055                     dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3056
3057                     return;
3058                 }
3059                 else if (bLimLo)
3060                 {
3061                     /* root->cell_f[i] = root->bound_min[i]; */
3062                     nrange[1] = i;  /* only store violation location. There could be a LimLo violation following with an higher index */
3063                     bLastHi   = FALSE;
3064                 }
3065                 else if (bLimHi && !bLastHi)
3066                 {
3067                     bLastHi = TRUE;
3068                     if (nrange[1] < range[1])   /* found a LimLo before */
3069                     {
3070                         root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
3071                         dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3072                         nrange[0] = nrange[1];
3073                     }
3074                     root->cell_f[i] = root->bound_max[i];
3075                     nrange[1]       = i;
3076                     dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3077                     nrange[0] = i;
3078                     nrange[1] = range[1];
3079                 }
3080             }
3081             if (nrange[1] < range[1])   /* found last a LimLo */
3082             {
3083                 root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
3084                 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3085                 nrange[0] = nrange[1];
3086                 nrange[1] = range[1];
3087                 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3088             }
3089             else if (nrange[0] > range[0]) /* found at least one LimHi */
3090             {
3091                 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3092             }
3093         }
3094     }
3095 }
3096
3097
3098 static void set_dd_cell_sizes_dlb_root(gmx_domdec_t *dd,
3099                                        int d, int dim, domdec_root_t *root,
3100                                        const gmx_ddbox_t *ddbox,
3101                                        gmx_bool bDynamicBox,
3102                                        gmx_bool bUniform, gmx_int64_t step)
3103 {
3104     gmx_domdec_comm_t *comm;
3105     int                ncd, d1, i, pos;
3106     real              *cell_size;
3107     real               load_aver, load_i, imbalance, change, change_max, sc;
3108     real               cellsize_limit_f, dist_min_f, dist_min_f_hard, space;
3109     real               change_limit;
3110     real               relax = 0.5;
3111     gmx_bool           bPBC;
3112     int                range[] = { 0, 0 };
3113
3114     comm = dd->comm;
3115
3116     /* Convert the maximum change from the input percentage to a fraction */
3117     change_limit = comm->dlb_scale_lim*0.01;
3118
3119     ncd = dd->nc[dim];
3120
3121     bPBC = (dim < ddbox->npbcdim);
3122
3123     cell_size = root->buf_ncd;
3124
3125     /* Store the original boundaries */
3126     for (i = 0; i < ncd+1; i++)
3127     {
3128         root->old_cell_f[i] = root->cell_f[i];
3129     }
3130     if (bUniform)
3131     {
3132         for (i = 0; i < ncd; i++)
3133         {
3134             cell_size[i] = 1.0/ncd;
3135         }
3136     }
3137     else if (dd_load_count(comm) > 0)
3138     {
3139         load_aver  = comm->load[d].sum_m/ncd;
3140         change_max = 0;
3141         for (i = 0; i < ncd; i++)
3142         {
3143             /* Determine the relative imbalance of cell i */
3144             load_i    = comm->load[d].load[i*comm->load[d].nload+2];
3145             imbalance = (load_i - load_aver)/(load_aver > 0 ? load_aver : 1);
3146             /* Determine the change of the cell size using underrelaxation */
3147             change     = -relax*imbalance;
3148             change_max = std::max(change_max, std::max(change, -change));
3149         }
3150         /* Limit the amount of scaling.
3151          * We need to use the same rescaling for all cells in one row,
3152          * otherwise the load balancing might not converge.
3153          */
3154         sc = relax;
3155         if (change_max > change_limit)
3156         {
3157             sc *= change_limit/change_max;
3158         }
3159         for (i = 0; i < ncd; i++)
3160         {
3161             /* Determine the relative imbalance of cell i */
3162             load_i    = comm->load[d].load[i*comm->load[d].nload+2];
3163             imbalance = (load_i - load_aver)/(load_aver > 0 ? load_aver : 1);
3164             /* Determine the change of the cell size using underrelaxation */
3165             change       = -sc*imbalance;
3166             cell_size[i] = (root->cell_f[i+1]-root->cell_f[i])*(1 + change);
3167         }
3168     }
3169
3170     cellsize_limit_f  = cellsize_min_dlb(comm, d, dim)/ddbox->box_size[dim];
3171     cellsize_limit_f *= DD_CELL_MARGIN;
3172     dist_min_f_hard   = grid_jump_limit(comm, comm->cutoff, d)/ddbox->box_size[dim];
3173     dist_min_f        = dist_min_f_hard * DD_CELL_MARGIN;
3174     if (ddbox->tric_dir[dim])
3175     {
3176         cellsize_limit_f /= ddbox->skew_fac[dim];
3177         dist_min_f       /= ddbox->skew_fac[dim];
3178     }
3179     if (bDynamicBox && d > 0)
3180     {
3181         dist_min_f *= DD_PRES_SCALE_MARGIN;
3182     }
3183     if (d > 0 && !bUniform)
3184     {
3185         /* Make sure that the grid is not shifted too much */
3186         for (i = 1; i < ncd; i++)
3187         {
3188             if (root->cell_f_min1[i] - root->cell_f_max0[i-1] < 2 * dist_min_f_hard)
3189             {
3190                 gmx_incons("Inconsistent DD boundary staggering limits!");
3191             }
3192             root->bound_min[i] = root->cell_f_max0[i-1] + dist_min_f;
3193             space              = root->cell_f[i] - (root->cell_f_max0[i-1] + dist_min_f);
3194             if (space > 0)
3195             {
3196                 root->bound_min[i] += 0.5*space;
3197             }
3198             root->bound_max[i] = root->cell_f_min1[i] - dist_min_f;
3199             space              = root->cell_f[i] - (root->cell_f_min1[i] - dist_min_f);
3200             if (space < 0)
3201             {
3202                 root->bound_max[i] += 0.5*space;
3203             }
3204             if (debug)
3205             {
3206                 fprintf(debug,
3207                         "dim %d boundary %d %.3f < %.3f < %.3f < %.3f < %.3f\n",
3208                         d, i,
3209                         root->cell_f_max0[i-1] + dist_min_f,
3210                         root->bound_min[i], root->cell_f[i], root->bound_max[i],
3211                         root->cell_f_min1[i] - dist_min_f);
3212             }
3213         }
3214     }
3215     range[1]          = ncd;
3216     root->cell_f[0]   = 0;
3217     root->cell_f[ncd] = 1;
3218     dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, range);
3219
3220
3221     /* After the checks above, the cells should obey the cut-off
3222      * restrictions, but it does not hurt to check.
3223      */
3224     for (i = 0; i < ncd; i++)
3225     {
3226         if (debug)
3227         {
3228             fprintf(debug, "Relative bounds dim %d  cell %d: %f %f\n",
3229                     dim, i, root->cell_f[i], root->cell_f[i+1]);
3230         }
3231
3232         if ((bPBC || (i != 0 && i != dd->nc[dim]-1)) &&
3233             root->cell_f[i+1] - root->cell_f[i] <
3234             cellsize_limit_f/DD_CELL_MARGIN)
3235         {
3236             char buf[22];
3237             fprintf(stderr,
3238                     "\nWARNING step %s: direction %c, cell %d too small: %f\n",
3239                     gmx_step_str(step, buf), dim2char(dim), i,
3240                     (root->cell_f[i+1] - root->cell_f[i])
3241                     *ddbox->box_size[dim]*ddbox->skew_fac[dim]);
3242         }
3243     }
3244
3245     pos = ncd + 1;
3246     /* Store the cell boundaries of the lower dimensions at the end */
3247     for (d1 = 0; d1 < d; d1++)
3248     {
3249         root->cell_f[pos++] = comm->cell_f0[d1];
3250         root->cell_f[pos++] = comm->cell_f1[d1];
3251     }
3252
3253     if (d < comm->npmedecompdim)
3254     {
3255         /* The master determines the maximum shift for
3256          * the coordinate communication between separate PME nodes.
3257          */
3258         set_pme_maxshift(dd, &comm->ddpme[d], bUniform, ddbox, root->cell_f);
3259     }
3260     root->cell_f[pos++] = comm->ddpme[0].maxshift;
3261     if (d >= 1)
3262     {
3263         root->cell_f[pos++] = comm->ddpme[1].maxshift;
3264     }
3265 }
3266
3267 static void relative_to_absolute_cell_bounds(gmx_domdec_t      *dd,
3268                                              const gmx_ddbox_t *ddbox,
3269                                              int                dimind)
3270 {
3271     gmx_domdec_comm_t *comm;
3272     int                dim;
3273
3274     comm = dd->comm;
3275
3276     /* Set the cell dimensions */
3277     dim                = dd->dim[dimind];
3278     comm->cell_x0[dim] = comm->cell_f0[dimind]*ddbox->box_size[dim];
3279     comm->cell_x1[dim] = comm->cell_f1[dimind]*ddbox->box_size[dim];
3280     if (dim >= ddbox->nboundeddim)
3281     {
3282         comm->cell_x0[dim] += ddbox->box0[dim];
3283         comm->cell_x1[dim] += ddbox->box0[dim];
3284     }
3285 }
3286
3287 static void distribute_dd_cell_sizes_dlb(gmx_domdec_t *dd,
3288                                          int d, int dim, real *cell_f_row,
3289                                          const gmx_ddbox_t *ddbox)
3290 {
3291     gmx_domdec_comm_t *comm;
3292     int                d1, pos;
3293
3294     comm = dd->comm;
3295
3296 #if GMX_MPI
3297     /* Each node would only need to know two fractions,
3298      * but it is probably cheaper to broadcast the whole array.
3299      */
3300     MPI_Bcast(cell_f_row, DD_CELL_F_SIZE(dd, d)*sizeof(real), MPI_BYTE,
3301               0, comm->mpi_comm_load[d]);
3302 #endif
3303     /* Copy the fractions for this dimension from the buffer */
3304     comm->cell_f0[d] = cell_f_row[dd->ci[dim]  ];
3305     comm->cell_f1[d] = cell_f_row[dd->ci[dim]+1];
3306     /* The whole array was communicated, so set the buffer position */
3307     pos = dd->nc[dim] + 1;
3308     for (d1 = 0; d1 <= d; d1++)
3309     {
3310         if (d1 < d)
3311         {
3312             /* Copy the cell fractions of the lower dimensions */
3313             comm->cell_f0[d1] = cell_f_row[pos++];
3314             comm->cell_f1[d1] = cell_f_row[pos++];
3315         }
3316         relative_to_absolute_cell_bounds(dd, ddbox, d1);
3317     }
3318     /* Convert the communicated shift from float to int */
3319     comm->ddpme[0].maxshift = (int)(cell_f_row[pos++] + 0.5);
3320     if (d >= 1)
3321     {
3322         comm->ddpme[1].maxshift = (int)(cell_f_row[pos++] + 0.5);
3323     }
3324 }
3325
3326 static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
3327                                          const gmx_ddbox_t *ddbox,
3328                                          gmx_bool bDynamicBox,
3329                                          gmx_bool bUniform, gmx_int64_t step)
3330 {
3331     gmx_domdec_comm_t *comm;
3332     int                d, dim, d1;
3333     gmx_bool           bRowMember, bRowRoot;
3334     real              *cell_f_row;
3335
3336     comm = dd->comm;
3337
3338     for (d = 0; d < dd->ndim; d++)
3339     {
3340         dim        = dd->dim[d];
3341         bRowMember = TRUE;
3342         bRowRoot   = TRUE;
3343         for (d1 = d; d1 < dd->ndim; d1++)
3344         {
3345             if (dd->ci[dd->dim[d1]] > 0)
3346             {
3347                 if (d1 != d)
3348                 {
3349                     bRowMember = FALSE;
3350                 }
3351                 bRowRoot = FALSE;
3352             }
3353         }
3354         if (bRowMember)
3355         {
3356             if (bRowRoot)
3357             {
3358                 set_dd_cell_sizes_dlb_root(dd, d, dim, comm->root[d],
3359                                            ddbox, bDynamicBox, bUniform, step);
3360                 cell_f_row = comm->root[d]->cell_f;
3361             }
3362             else
3363             {
3364                 cell_f_row = comm->cell_f_row;
3365             }
3366             distribute_dd_cell_sizes_dlb(dd, d, dim, cell_f_row, ddbox);
3367         }
3368     }
3369 }
3370
3371 static void set_dd_cell_sizes_dlb_nochange(gmx_domdec_t      *dd,
3372                                            const gmx_ddbox_t *ddbox)
3373 {
3374     int d;
3375
3376     /* This function assumes the box is static and should therefore
3377      * not be called when the box has changed since the last
3378      * call to dd_partition_system.
3379      */
3380     for (d = 0; d < dd->ndim; d++)
3381     {
3382         relative_to_absolute_cell_bounds(dd, ddbox, d);
3383     }
3384 }
3385
3386
3387
3388 static void set_dd_cell_sizes_dlb(gmx_domdec_t *dd,
3389                                   const gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3390                                   gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
3391                                   gmx_wallcycle_t wcycle)
3392 {
3393     gmx_domdec_comm_t *comm;
3394     int                dim;
3395
3396     comm = dd->comm;
3397
3398     if (bDoDLB)
3399     {
3400         wallcycle_start(wcycle, ewcDDCOMMBOUND);
3401         set_dd_cell_sizes_dlb_change(dd, ddbox, bDynamicBox, bUniform, step);
3402         wallcycle_stop(wcycle, ewcDDCOMMBOUND);
3403     }
3404     else if (bDynamicBox)
3405     {
3406         set_dd_cell_sizes_dlb_nochange(dd, ddbox);
3407     }
3408
3409     /* Set the dimensions for which no DD is used */
3410     for (dim = 0; dim < DIM; dim++)
3411     {
3412         if (dd->nc[dim] == 1)
3413         {
3414             comm->cell_x0[dim] = 0;
3415             comm->cell_x1[dim] = ddbox->box_size[dim];
3416             if (dim >= ddbox->nboundeddim)
3417             {
3418                 comm->cell_x0[dim] += ddbox->box0[dim];
3419                 comm->cell_x1[dim] += ddbox->box0[dim];
3420             }
3421         }
3422     }
3423 }
3424
3425 static void realloc_comm_ind(gmx_domdec_t *dd, ivec npulse)
3426 {
3427     int                    d, np, i;
3428     gmx_domdec_comm_dim_t *cd;
3429
3430     for (d = 0; d < dd->ndim; d++)
3431     {
3432         cd = &dd->comm->cd[d];
3433         np = npulse[dd->dim[d]];
3434         if (np > cd->np_nalloc)
3435         {
3436             if (debug)
3437             {
3438                 fprintf(debug, "(Re)allocing cd for %c to %d pulses\n",
3439                         dim2char(dd->dim[d]), np);
3440             }
3441             if (DDMASTER(dd) && cd->np_nalloc > 0)
3442             {
3443                 fprintf(stderr, "\nIncreasing the number of cell to communicate in dimension %c to %d for the first time\n", dim2char(dd->dim[d]), np);
3444             }
3445             srenew(cd->ind, np);
3446             for (i = cd->np_nalloc; i < np; i++)
3447             {
3448                 cd->ind[i].index  = nullptr;
3449                 cd->ind[i].nalloc = 0;
3450             }
3451             cd->np_nalloc = np;
3452         }
3453         cd->np = np;
3454     }
3455 }
3456
3457
3458 static void set_dd_cell_sizes(gmx_domdec_t *dd,
3459                               gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3460                               gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
3461                               gmx_wallcycle_t wcycle)
3462 {
3463     gmx_domdec_comm_t *comm;
3464     int                d;
3465     ivec               npulse;
3466
3467     comm = dd->comm;
3468
3469     /* Copy the old cell boundaries for the cg displacement check */
3470     copy_rvec(comm->cell_x0, comm->old_cell_x0);
3471     copy_rvec(comm->cell_x1, comm->old_cell_x1);
3472
3473     if (isDlbOn(comm))
3474     {
3475         if (DDMASTER(dd))
3476         {
3477             check_box_size(dd, ddbox);
3478         }
3479         set_dd_cell_sizes_dlb(dd, ddbox, bDynamicBox, bUniform, bDoDLB, step, wcycle);
3480     }
3481     else
3482     {
3483         set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbLOCAL, npulse);
3484         realloc_comm_ind(dd, npulse);
3485     }
3486
3487     if (debug)
3488     {
3489         for (d = 0; d < DIM; d++)
3490         {
3491             fprintf(debug, "cell_x[%d] %f - %f skew_fac %f\n",
3492                     d, comm->cell_x0[d], comm->cell_x1[d], ddbox->skew_fac[d]);
3493         }
3494     }
3495 }
3496
3497 static void comm_dd_ns_cell_sizes(gmx_domdec_t *dd,
3498                                   gmx_ddbox_t *ddbox,
3499                                   rvec cell_ns_x0, rvec cell_ns_x1,
3500                                   gmx_int64_t step)
3501 {
3502     gmx_domdec_comm_t *comm;
3503     int                dim_ind, dim;
3504
3505     comm = dd->comm;
3506
3507     for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
3508     {
3509         dim = dd->dim[dim_ind];
3510
3511         /* Without PBC we don't have restrictions on the outer cells */
3512         if (!(dim >= ddbox->npbcdim &&
3513               (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1)) &&
3514             isDlbOn(comm) &&
3515             (comm->cell_x1[dim] - comm->cell_x0[dim])*ddbox->skew_fac[dim] <
3516             comm->cellsize_min[dim])
3517         {
3518             char buf[22];
3519             gmx_fatal(FARGS, "step %s: The %c-size (%f) times the triclinic skew factor (%f) is smaller than the smallest allowed cell size (%f) for domain decomposition grid cell %d %d %d",
3520                       gmx_step_str(step, buf), dim2char(dim),
3521                       comm->cell_x1[dim] - comm->cell_x0[dim],
3522                       ddbox->skew_fac[dim],
3523                       dd->comm->cellsize_min[dim],
3524                       dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
3525         }
3526     }
3527
3528     if ((isDlbOn(dd->comm) && dd->ndim > 1) || ddbox->nboundeddim < DIM)
3529     {
3530         /* Communicate the boundaries and update cell_ns_x0/1 */
3531         dd_move_cellx(dd, ddbox, cell_ns_x0, cell_ns_x1);
3532         if (isDlbOn(dd->comm) && dd->ndim > 1)
3533         {
3534             check_grid_jump(step, dd, dd->comm->cutoff, ddbox, TRUE);
3535         }
3536     }
3537 }
3538
3539 static void make_tric_corr_matrix(int npbcdim, const matrix box, matrix tcm)
3540 {
3541     if (YY < npbcdim)
3542     {
3543         tcm[YY][XX] = -box[YY][XX]/box[YY][YY];
3544     }
3545     else
3546     {
3547         tcm[YY][XX] = 0;
3548     }
3549     if (ZZ < npbcdim)
3550     {
3551         tcm[ZZ][XX] = -(box[ZZ][YY]*tcm[YY][XX] + box[ZZ][XX])/box[ZZ][ZZ];
3552         tcm[ZZ][YY] = -box[ZZ][YY]/box[ZZ][ZZ];
3553     }
3554     else
3555     {
3556         tcm[ZZ][XX] = 0;
3557         tcm[ZZ][YY] = 0;
3558     }
3559 }
3560
3561 static void check_screw_box(const matrix box)
3562 {
3563     /* Mathematical limitation */
3564     if (box[YY][XX] != 0 || box[ZZ][XX] != 0)
3565     {
3566         gmx_fatal(FARGS, "With screw pbc the unit cell can not have non-zero off-diagonal x-components");
3567     }
3568
3569     /* Limitation due to the asymmetry of the eighth shell method */
3570     if (box[ZZ][YY] != 0)
3571     {
3572         gmx_fatal(FARGS, "pbc=screw with non-zero box_zy is not supported");
3573     }
3574 }
3575
3576 static void distribute_cg(FILE *fplog,
3577                           const matrix box, ivec tric_dir, t_block *cgs, rvec pos[],
3578                           gmx_domdec_t *dd)
3579 {
3580     gmx_domdec_master_t *ma;
3581     int                **tmp_ind = nullptr, *tmp_nalloc = nullptr;
3582     int                  i, icg, j, k, k0, k1, d;
3583     matrix               tcm;
3584     rvec                 cg_cm;
3585     ivec                 ind;
3586     real                 nrcg, inv_ncg, pos_d;
3587     int                 *cgindex;
3588     gmx_bool             bScrew;
3589
3590     ma = dd->ma;
3591
3592     snew(tmp_nalloc, dd->nnodes);
3593     snew(tmp_ind, dd->nnodes);
3594     for (i = 0; i < dd->nnodes; i++)
3595     {
3596         tmp_nalloc[i] = over_alloc_large(cgs->nr/dd->nnodes+1);
3597         snew(tmp_ind[i], tmp_nalloc[i]);
3598     }
3599
3600     /* Clear the count */
3601     for (i = 0; i < dd->nnodes; i++)
3602     {
3603         ma->ncg[i] = 0;
3604         ma->nat[i] = 0;
3605     }
3606
3607     make_tric_corr_matrix(dd->npbcdim, box, tcm);
3608
3609     cgindex = cgs->index;
3610
3611     /* Compute the center of geometry for all charge groups */
3612     for (icg = 0; icg < cgs->nr; icg++)
3613     {
3614         k0      = cgindex[icg];
3615         k1      = cgindex[icg+1];
3616         nrcg    = k1 - k0;
3617         if (nrcg == 1)
3618         {
3619             copy_rvec(pos[k0], cg_cm);
3620         }
3621         else
3622         {
3623             inv_ncg = 1.0/nrcg;
3624
3625             clear_rvec(cg_cm);
3626             for (k = k0; (k < k1); k++)
3627             {
3628                 rvec_inc(cg_cm, pos[k]);
3629             }
3630             for (d = 0; (d < DIM); d++)
3631             {
3632                 cg_cm[d] *= inv_ncg;
3633             }
3634         }
3635         /* Put the charge group in the box and determine the cell index */
3636         for (d = DIM-1; d >= 0; d--)
3637         {
3638             pos_d = cg_cm[d];
3639             if (d < dd->npbcdim)
3640             {
3641                 bScrew = (dd->bScrewPBC && d == XX);
3642                 if (tric_dir[d] && dd->nc[d] > 1)
3643                 {
3644                     /* Use triclinic coordintates for this dimension */
3645                     for (j = d+1; j < DIM; j++)
3646                     {
3647                         pos_d += cg_cm[j]*tcm[j][d];
3648                     }
3649                 }
3650                 while (pos_d >= box[d][d])
3651                 {
3652                     pos_d -= box[d][d];
3653                     rvec_dec(cg_cm, box[d]);
3654                     if (bScrew)
3655                     {
3656                         cg_cm[YY] = box[YY][YY] - cg_cm[YY];
3657                         cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
3658                     }
3659                     for (k = k0; (k < k1); k++)
3660                     {
3661                         rvec_dec(pos[k], box[d]);
3662                         if (bScrew)
3663                         {
3664                             pos[k][YY] = box[YY][YY] - pos[k][YY];
3665                             pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
3666                         }
3667                     }
3668                 }
3669                 while (pos_d < 0)
3670                 {
3671                     pos_d += box[d][d];
3672                     rvec_inc(cg_cm, box[d]);
3673                     if (bScrew)
3674                     {
3675                         cg_cm[YY] = box[YY][YY] - cg_cm[YY];
3676                         cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
3677                     }
3678                     for (k = k0; (k < k1); k++)
3679                     {
3680                         rvec_inc(pos[k], box[d]);
3681                         if (bScrew)
3682                         {
3683                             pos[k][YY] = box[YY][YY] - pos[k][YY];
3684                             pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
3685                         }
3686                     }
3687                 }
3688             }
3689             /* This could be done more efficiently */
3690             ind[d] = 0;
3691             while (ind[d]+1 < dd->nc[d] && pos_d >= ma->cell_x[d][ind[d]+1])
3692             {
3693                 ind[d]++;
3694             }
3695         }
3696         i = dd_index(dd->nc, ind);
3697         if (ma->ncg[i] == tmp_nalloc[i])
3698         {
3699             tmp_nalloc[i] = over_alloc_large(ma->ncg[i]+1);
3700             srenew(tmp_ind[i], tmp_nalloc[i]);
3701         }
3702         tmp_ind[i][ma->ncg[i]] = icg;
3703         ma->ncg[i]++;
3704         ma->nat[i] += cgindex[icg+1] - cgindex[icg];
3705     }
3706
3707     k1 = 0;
3708     for (i = 0; i < dd->nnodes; i++)
3709     {
3710         ma->index[i] = k1;
3711         for (k = 0; k < ma->ncg[i]; k++)
3712         {
3713             ma->cg[k1++] = tmp_ind[i][k];
3714         }
3715     }
3716     ma->index[dd->nnodes] = k1;
3717
3718     for (i = 0; i < dd->nnodes; i++)
3719     {
3720         sfree(tmp_ind[i]);
3721     }
3722     sfree(tmp_ind);
3723     sfree(tmp_nalloc);
3724
3725     if (fplog)
3726     {
3727         // Use double for the sums to avoid natoms^2 overflowing
3728         // (65537^2 > 2^32)
3729         int    nat_sum, nat_min, nat_max;
3730         double nat2_sum;
3731
3732         nat_sum  = 0;
3733         nat2_sum = 0;
3734         nat_min  = ma->nat[0];
3735         nat_max  = ma->nat[0];
3736         for (i = 0; i < dd->nnodes; i++)
3737         {
3738             nat_sum  += ma->nat[i];
3739             // cast to double to avoid integer overflows when squaring
3740             nat2_sum += gmx::square(static_cast<double>(ma->nat[i]));
3741             nat_min   = std::min(nat_min, ma->nat[i]);
3742             nat_max   = std::max(nat_max, ma->nat[i]);
3743         }
3744         nat_sum  /= dd->nnodes;
3745         nat2_sum /= dd->nnodes;
3746
3747         fprintf(fplog, "Atom distribution over %d domains: av %d stddev %d min %d max %d\n",
3748                 dd->nnodes,
3749                 nat_sum,
3750                 static_cast<int>(std::sqrt(nat2_sum - gmx::square(static_cast<double>(nat_sum)) + 0.5)),
3751                 nat_min, nat_max);
3752     }
3753 }
3754
3755 static void get_cg_distribution(FILE *fplog, gmx_domdec_t *dd,
3756                                 t_block *cgs, const matrix box, gmx_ddbox_t *ddbox,
3757                                 rvec pos[])
3758 {
3759     gmx_domdec_master_t *ma = nullptr;
3760     ivec                 npulse;
3761     int                  i, cg_gl;
3762     int                 *ibuf, buf2[2] = { 0, 0 };
3763     gmx_bool             bMaster = DDMASTER(dd);
3764
3765     if (bMaster)
3766     {
3767         ma = dd->ma;
3768
3769         if (dd->bScrewPBC)
3770         {
3771             check_screw_box(box);
3772         }
3773
3774         set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbMASTER, npulse);
3775
3776         distribute_cg(fplog, box, ddbox->tric_dir, cgs, pos, dd);
3777         for (i = 0; i < dd->nnodes; i++)
3778         {
3779             ma->ibuf[2*i]   = ma->ncg[i];
3780             ma->ibuf[2*i+1] = ma->nat[i];
3781         }
3782         ibuf = ma->ibuf;
3783     }
3784     else
3785     {
3786         ibuf = nullptr;
3787     }
3788     dd_scatter(dd, 2*sizeof(int), ibuf, buf2);
3789
3790     dd->ncg_home = buf2[0];
3791     dd->nat_home = buf2[1];
3792     dd->ncg_tot  = dd->ncg_home;
3793     dd->nat_tot  = dd->nat_home;
3794     if (dd->ncg_home > dd->cg_nalloc || dd->cg_nalloc == 0)
3795     {
3796         dd->cg_nalloc = over_alloc_dd(dd->ncg_home);
3797         srenew(dd->index_gl, dd->cg_nalloc);
3798         srenew(dd->cgindex, dd->cg_nalloc+1);
3799     }
3800     if (bMaster)
3801     {
3802         for (i = 0; i < dd->nnodes; i++)
3803         {
3804             ma->ibuf[i]            = ma->ncg[i]*sizeof(int);
3805             ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
3806         }
3807     }
3808
3809     dd_scatterv(dd,
3810                 bMaster ? ma->ibuf : nullptr,
3811                 bMaster ? ma->ibuf+dd->nnodes : nullptr,
3812                 bMaster ? ma->cg : nullptr,
3813                 dd->ncg_home*sizeof(int), dd->index_gl);
3814
3815     /* Determine the home charge group sizes */
3816     dd->cgindex[0] = 0;
3817     for (i = 0; i < dd->ncg_home; i++)
3818     {
3819         cg_gl            = dd->index_gl[i];
3820         dd->cgindex[i+1] =
3821             dd->cgindex[i] + cgs->index[cg_gl+1] - cgs->index[cg_gl];
3822     }
3823
3824     if (debug)
3825     {
3826         fprintf(debug, "Home charge groups:\n");
3827         for (i = 0; i < dd->ncg_home; i++)
3828         {
3829             fprintf(debug, " %d", dd->index_gl[i]);
3830             if (i % 10 == 9)
3831             {
3832                 fprintf(debug, "\n");
3833             }
3834         }
3835         fprintf(debug, "\n");
3836     }
3837 }
3838
3839 static int compact_and_copy_vec_at(int ncg, int *move,
3840                                    int *cgindex,
3841                                    int nvec, int vec,
3842                                    rvec *src, gmx_domdec_comm_t *comm,
3843                                    gmx_bool bCompact)
3844 {
3845     int m, icg, i, i0, i1, nrcg;
3846     int home_pos;
3847     int pos_vec[DIM*2];
3848
3849     home_pos = 0;
3850
3851     for (m = 0; m < DIM*2; m++)
3852     {
3853         pos_vec[m] = 0;
3854     }
3855
3856     i0 = 0;
3857     for (icg = 0; icg < ncg; icg++)
3858     {
3859         i1 = cgindex[icg+1];
3860         m  = move[icg];
3861         if (m == -1)
3862         {
3863             if (bCompact)
3864             {
3865                 /* Compact the home array in place */
3866                 for (i = i0; i < i1; i++)
3867                 {
3868                     copy_rvec(src[i], src[home_pos++]);
3869                 }
3870             }
3871         }
3872         else
3873         {
3874             /* Copy to the communication buffer */
3875             nrcg        = i1 - i0;
3876             pos_vec[m] += 1 + vec*nrcg;
3877             for (i = i0; i < i1; i++)
3878             {
3879                 copy_rvec(src[i], comm->cgcm_state[m][pos_vec[m]++]);
3880             }
3881             pos_vec[m] += (nvec - vec - 1)*nrcg;
3882         }
3883         if (!bCompact)
3884         {
3885             home_pos += i1 - i0;
3886         }
3887         i0 = i1;
3888     }
3889
3890     return home_pos;
3891 }
3892
3893 static int compact_and_copy_vec_cg(int ncg, int *move,
3894                                    int *cgindex,
3895                                    int nvec, rvec *src, gmx_domdec_comm_t *comm,
3896                                    gmx_bool bCompact)
3897 {
3898     int m, icg, i0, i1, nrcg;
3899     int home_pos;
3900     int pos_vec[DIM*2];
3901
3902     home_pos = 0;
3903
3904     for (m = 0; m < DIM*2; m++)
3905     {
3906         pos_vec[m] = 0;
3907     }
3908
3909     i0 = 0;
3910     for (icg = 0; icg < ncg; icg++)
3911     {
3912         i1 = cgindex[icg+1];
3913         m  = move[icg];
3914         if (m == -1)
3915         {
3916             if (bCompact)
3917             {
3918                 /* Compact the home array in place */
3919                 copy_rvec(src[icg], src[home_pos++]);
3920             }
3921         }
3922         else
3923         {
3924             nrcg = i1 - i0;
3925             /* Copy to the communication buffer */
3926             copy_rvec(src[icg], comm->cgcm_state[m][pos_vec[m]]);
3927             pos_vec[m] += 1 + nrcg*nvec;
3928         }
3929         i0 = i1;
3930     }
3931     if (!bCompact)
3932     {
3933         home_pos = ncg;
3934     }
3935
3936     return home_pos;
3937 }
3938
3939 static int compact_ind(int ncg, int *move,
3940                        int *index_gl, int *cgindex,
3941                        int *gatindex,
3942                        gmx_ga2la_t *ga2la, char *bLocalCG,
3943                        int *cginfo)
3944 {
3945     int cg, nat, a0, a1, a, a_gl;
3946     int home_pos;
3947
3948     home_pos = 0;
3949     nat      = 0;
3950     for (cg = 0; cg < ncg; cg++)
3951     {
3952         a0 = cgindex[cg];
3953         a1 = cgindex[cg+1];
3954         if (move[cg] == -1)
3955         {
3956             /* Compact the home arrays in place.
3957              * Anything that can be done here avoids access to global arrays.
3958              */
3959             cgindex[home_pos] = nat;
3960             for (a = a0; a < a1; a++)
3961             {
3962                 a_gl          = gatindex[a];
3963                 gatindex[nat] = a_gl;
3964                 /* The cell number stays 0, so we don't need to set it */
3965                 ga2la_change_la(ga2la, a_gl, nat);
3966                 nat++;
3967             }
3968             index_gl[home_pos] = index_gl[cg];
3969             cginfo[home_pos]   = cginfo[cg];
3970             /* The charge group remains local, so bLocalCG does not change */
3971             home_pos++;
3972         }
3973         else
3974         {
3975             /* Clear the global indices */
3976             for (a = a0; a < a1; a++)
3977             {
3978                 ga2la_del(ga2la, gatindex[a]);
3979             }
3980             if (bLocalCG)
3981             {
3982                 bLocalCG[index_gl[cg]] = FALSE;
3983             }
3984         }
3985     }
3986     cgindex[home_pos] = nat;
3987
3988     return home_pos;
3989 }
3990
3991 static void clear_and_mark_ind(int ncg, int *move,
3992                                int *index_gl, int *cgindex, int *gatindex,
3993                                gmx_ga2la_t *ga2la, char *bLocalCG,
3994                                int *cell_index)
3995 {
3996     int cg, a0, a1, a;
3997
3998     for (cg = 0; cg < ncg; cg++)
3999     {
4000         if (move[cg] >= 0)
4001         {
4002             a0 = cgindex[cg];
4003             a1 = cgindex[cg+1];
4004             /* Clear the global indices */
4005             for (a = a0; a < a1; a++)
4006             {
4007                 ga2la_del(ga2la, gatindex[a]);
4008             }
4009             if (bLocalCG)
4010             {
4011                 bLocalCG[index_gl[cg]] = FALSE;
4012             }
4013             /* Signal that this cg has moved using the ns cell index.
4014              * Here we set it to -1. fill_grid will change it
4015              * from -1 to NSGRID_SIGNAL_MOVED_FAC*grid->ncells.
4016              */
4017             cell_index[cg] = -1;
4018         }
4019     }
4020 }
4021
4022 static void print_cg_move(FILE *fplog,
4023                           gmx_domdec_t *dd,
4024                           gmx_int64_t step, int cg, int dim, int dir,
4025                           gmx_bool bHaveCgcmOld, real limitd,
4026                           rvec cm_old, rvec cm_new, real pos_d)
4027 {
4028     gmx_domdec_comm_t *comm;
4029     char               buf[22];
4030
4031     comm = dd->comm;
4032
4033     fprintf(fplog, "\nStep %s:\n", gmx_step_str(step, buf));
4034     if (limitd > 0)
4035     {
4036         fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition (%f) in direction %c\n",
4037                 dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
4038                 ddglatnr(dd, dd->cgindex[cg]), limitd, dim2char(dim));
4039     }
4040     else
4041     {
4042         /* We don't have a limiting distance available: don't print it */
4043         fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition in direction %c\n",
4044                 dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
4045                 ddglatnr(dd, dd->cgindex[cg]), dim2char(dim));
4046     }
4047     fprintf(fplog, "distance out of cell %f\n",
4048             dir == 1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
4049     if (bHaveCgcmOld)
4050     {
4051         fprintf(fplog, "Old coordinates: %8.3f %8.3f %8.3f\n",
4052                 cm_old[XX], cm_old[YY], cm_old[ZZ]);
4053     }
4054     fprintf(fplog, "New coordinates: %8.3f %8.3f %8.3f\n",
4055             cm_new[XX], cm_new[YY], cm_new[ZZ]);
4056     fprintf(fplog, "Old cell boundaries in direction %c: %8.3f %8.3f\n",
4057             dim2char(dim),
4058             comm->old_cell_x0[dim], comm->old_cell_x1[dim]);
4059     fprintf(fplog, "New cell boundaries in direction %c: %8.3f %8.3f\n",
4060             dim2char(dim),
4061             comm->cell_x0[dim], comm->cell_x1[dim]);
4062 }
4063
4064 static void cg_move_error(FILE *fplog,
4065                           gmx_domdec_t *dd,
4066                           gmx_int64_t step, int cg, int dim, int dir,
4067                           gmx_bool bHaveCgcmOld, real limitd,
4068                           rvec cm_old, rvec cm_new, real pos_d)
4069 {
4070     if (fplog)
4071     {
4072         print_cg_move(fplog, dd, step, cg, dim, dir,
4073                       bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
4074     }
4075     print_cg_move(stderr, dd, step, cg, dim, dir,
4076                   bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
4077     gmx_fatal(FARGS,
4078               "%s moved too far between two domain decomposition steps\n"
4079               "This usually means that your system is not well equilibrated",
4080               dd->comm->bCGs ? "A charge group" : "An atom");
4081 }
4082
4083 static void rotate_state_atom(t_state *state, int a)
4084 {
4085     if (state->flags & (1 << estX))
4086     {
4087         /* Rotate the complete state; for a rectangular box only */
4088         state->x[a][YY] = state->box[YY][YY] - state->x[a][YY];
4089         state->x[a][ZZ] = state->box[ZZ][ZZ] - state->x[a][ZZ];
4090     }
4091     if (state->flags & (1 << estV))
4092     {
4093         state->v[a][YY] = -state->v[a][YY];
4094         state->v[a][ZZ] = -state->v[a][ZZ];
4095     }
4096     if (state->flags & (1 << estCGP))
4097     {
4098         state->cg_p[a][YY] = -state->cg_p[a][YY];
4099         state->cg_p[a][ZZ] = -state->cg_p[a][ZZ];
4100     }
4101 }
4102
4103 static int *get_moved(gmx_domdec_comm_t *comm, int natoms)
4104 {
4105     if (natoms > comm->moved_nalloc)
4106     {
4107         /* Contents should be preserved here */
4108         comm->moved_nalloc = over_alloc_dd(natoms);
4109         srenew(comm->moved, comm->moved_nalloc);
4110     }
4111
4112     return comm->moved;
4113 }
4114
4115 static void calc_cg_move(FILE *fplog, gmx_int64_t step,
4116                          gmx_domdec_t *dd,
4117                          t_state *state,
4118                          ivec tric_dir, matrix tcm,
4119                          rvec cell_x0, rvec cell_x1,
4120                          rvec limitd, rvec limit0, rvec limit1,
4121                          const int *cgindex,
4122                          int cg_start, int cg_end,
4123                          rvec *cg_cm,
4124                          int *move)
4125 {
4126     int      npbcdim;
4127     int      cg, k, k0, k1, d, dim, d2;
4128     int      mc, nrcg;
4129     int      flag;
4130     gmx_bool bScrew;
4131     ivec     dev;
4132     real     inv_ncg, pos_d;
4133     rvec     cm_new;
4134
4135     npbcdim = dd->npbcdim;
4136
4137     for (cg = cg_start; cg < cg_end; cg++)
4138     {
4139         k0   = cgindex[cg];
4140         k1   = cgindex[cg+1];
4141         nrcg = k1 - k0;
4142         if (nrcg == 1)
4143         {
4144             copy_rvec(state->x[k0], cm_new);
4145         }
4146         else
4147         {
4148             inv_ncg = 1.0/nrcg;
4149
4150             clear_rvec(cm_new);
4151             for (k = k0; (k < k1); k++)
4152             {
4153                 rvec_inc(cm_new, state->x[k]);
4154             }
4155             for (d = 0; (d < DIM); d++)
4156             {
4157                 cm_new[d] = inv_ncg*cm_new[d];
4158             }
4159         }
4160
4161         clear_ivec(dev);
4162         /* Do pbc and check DD cell boundary crossings */
4163         for (d = DIM-1; d >= 0; d--)
4164         {
4165             if (dd->nc[d] > 1)
4166             {
4167                 bScrew = (dd->bScrewPBC && d == XX);
4168                 /* Determine the location of this cg in lattice coordinates */
4169                 pos_d = cm_new[d];
4170                 if (tric_dir[d])
4171                 {
4172                     for (d2 = d+1; d2 < DIM; d2++)
4173                     {
4174                         pos_d += cm_new[d2]*tcm[d2][d];
4175                     }
4176                 }
4177                 /* Put the charge group in the triclinic unit-cell */
4178                 if (pos_d >= cell_x1[d])
4179                 {
4180                     if (pos_d >= limit1[d])
4181                     {
4182                         cg_move_error(fplog, dd, step, cg, d, 1,
4183                                       cg_cm != as_rvec_array(state->x.data()), limitd[d],
4184                                       cg_cm[cg], cm_new, pos_d);
4185                     }
4186                     dev[d] = 1;
4187                     if (dd->ci[d] == dd->nc[d] - 1)
4188                     {
4189                         rvec_dec(cm_new, state->box[d]);
4190                         if (bScrew)
4191                         {
4192                             cm_new[YY] = state->box[YY][YY] - cm_new[YY];
4193                             cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
4194                         }
4195                         for (k = k0; (k < k1); k++)
4196                         {
4197                             rvec_dec(state->x[k], state->box[d]);
4198                             if (bScrew)
4199                             {
4200                                 rotate_state_atom(state, k);
4201                             }
4202                         }
4203                     }
4204                 }
4205                 else if (pos_d < cell_x0[d])
4206                 {
4207                     if (pos_d < limit0[d])
4208                     {
4209                         cg_move_error(fplog, dd, step, cg, d, -1,
4210                                       cg_cm != as_rvec_array(state->x.data()), limitd[d],
4211                                       cg_cm[cg], cm_new, pos_d);
4212                     }
4213                     dev[d] = -1;
4214                     if (dd->ci[d] == 0)
4215                     {
4216                         rvec_inc(cm_new, state->box[d]);
4217                         if (bScrew)
4218                         {
4219                             cm_new[YY] = state->box[YY][YY] - cm_new[YY];
4220                             cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
4221                         }
4222                         for (k = k0; (k < k1); k++)
4223                         {
4224                             rvec_inc(state->x[k], state->box[d]);
4225                             if (bScrew)
4226                             {
4227                                 rotate_state_atom(state, k);
4228                             }
4229                         }
4230                     }
4231                 }
4232             }
4233             else if (d < npbcdim)
4234             {
4235                 /* Put the charge group in the rectangular unit-cell */
4236                 while (cm_new[d] >= state->box[d][d])
4237                 {
4238                     rvec_dec(cm_new, state->box[d]);
4239                     for (k = k0; (k < k1); k++)
4240                     {
4241                         rvec_dec(state->x[k], state->box[d]);
4242                     }
4243                 }
4244                 while (cm_new[d] < 0)
4245                 {
4246                     rvec_inc(cm_new, state->box[d]);
4247                     for (k = k0; (k < k1); k++)
4248                     {
4249                         rvec_inc(state->x[k], state->box[d]);
4250                     }
4251                 }
4252             }
4253         }
4254
4255         copy_rvec(cm_new, cg_cm[cg]);
4256
4257         /* Determine where this cg should go */
4258         flag = 0;
4259         mc   = -1;
4260         for (d = 0; d < dd->ndim; d++)
4261         {
4262             dim = dd->dim[d];
4263             if (dev[dim] == 1)
4264             {
4265                 flag |= DD_FLAG_FW(d);
4266                 if (mc == -1)
4267                 {
4268                     mc = d*2;
4269                 }
4270             }
4271             else if (dev[dim] == -1)
4272             {
4273                 flag |= DD_FLAG_BW(d);
4274                 if (mc == -1)
4275                 {
4276                     if (dd->nc[dim] > 2)
4277                     {
4278                         mc = d*2 + 1;
4279                     }
4280                     else
4281                     {
4282                         mc = d*2;
4283                     }
4284                 }
4285             }
4286         }
4287         /* Temporarily store the flag in move */
4288         move[cg] = mc + flag;
4289     }
4290 }
4291
4292 static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
4293                                gmx_domdec_t *dd, ivec tric_dir,
4294                                t_state *state, PaddedRVecVector *f,
4295                                t_forcerec *fr,
4296                                gmx_bool bCompact,
4297                                t_nrnb *nrnb,
4298                                int *ncg_stay_home,
4299                                int *ncg_moved)
4300 {
4301     int               *move;
4302     int                npbcdim;
4303     int                ncg[DIM*2] = { 0 }, nat[DIM*2] = { 0 };
4304     int                i, cg, k, d, dim, dim2, dir, d2, d3;
4305     int                mc, cdd, nrcg, ncg_recv, nvs, nvr, nvec, vec;
4306     int                sbuf[2], rbuf[2];
4307     int                home_pos_cg, home_pos_at, buf_pos;
4308     int                flag;
4309     real               pos_d;
4310     matrix             tcm;
4311     rvec              *cg_cm = nullptr, cell_x0, cell_x1, limitd, limit0, limit1;
4312     int               *cgindex;
4313     cginfo_mb_t       *cginfo_mb;
4314     gmx_domdec_comm_t *comm;
4315     int               *moved;
4316     int                nthread, thread;
4317
4318     if (dd->bScrewPBC)
4319     {
4320         check_screw_box(state->box);
4321     }
4322
4323     comm  = dd->comm;
4324     if (fr->cutoff_scheme == ecutsGROUP)
4325     {
4326         cg_cm = fr->cg_cm;
4327     }
4328
4329     // Positions are always present, so there's nothing to flag
4330     bool bV   = state->flags & (1<<estV);
4331     bool bCGP = state->flags & (1<<estCGP);
4332
4333     if (dd->ncg_tot > comm->nalloc_int)
4334     {
4335         comm->nalloc_int = over_alloc_dd(dd->ncg_tot);
4336         srenew(comm->buf_int, comm->nalloc_int);
4337     }
4338     move = comm->buf_int;
4339
4340     npbcdim = dd->npbcdim;
4341
4342     for (d = 0; (d < DIM); d++)
4343     {
4344         limitd[d] = dd->comm->cellsize_min[d];
4345         if (d >= npbcdim && dd->ci[d] == 0)
4346         {
4347             cell_x0[d] = -GMX_FLOAT_MAX;
4348         }
4349         else
4350         {
4351             cell_x0[d] = comm->cell_x0[d];
4352         }
4353         if (d >= npbcdim && dd->ci[d] == dd->nc[d] - 1)
4354         {
4355             cell_x1[d] = GMX_FLOAT_MAX;
4356         }
4357         else
4358         {
4359             cell_x1[d] = comm->cell_x1[d];
4360         }
4361         if (d < npbcdim)
4362         {
4363             limit0[d] = comm->old_cell_x0[d] - limitd[d];
4364             limit1[d] = comm->old_cell_x1[d] + limitd[d];
4365         }
4366         else
4367         {
4368             /* We check after communication if a charge group moved
4369              * more than one cell. Set the pre-comm check limit to float_max.
4370              */
4371             limit0[d] = -GMX_FLOAT_MAX;
4372             limit1[d] =  GMX_FLOAT_MAX;
4373         }
4374     }
4375
4376     make_tric_corr_matrix(npbcdim, state->box, tcm);
4377
4378     cgindex = dd->cgindex;
4379
4380     nthread = gmx_omp_nthreads_get(emntDomdec);
4381
4382     /* Compute the center of geometry for all home charge groups
4383      * and put them in the box and determine where they should go.
4384      */
4385 #pragma omp parallel for num_threads(nthread) schedule(static)
4386     for (thread = 0; thread < nthread; thread++)
4387     {
4388         try
4389         {
4390             calc_cg_move(fplog, step, dd, state, tric_dir, tcm,
4391                          cell_x0, cell_x1, limitd, limit0, limit1,
4392                          cgindex,
4393                          ( thread   *dd->ncg_home)/nthread,
4394                          ((thread+1)*dd->ncg_home)/nthread,
4395                          fr->cutoff_scheme == ecutsGROUP ? cg_cm : as_rvec_array(state->x.data()),
4396                          move);
4397         }
4398         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
4399     }
4400
4401     for (cg = 0; cg < dd->ncg_home; cg++)
4402     {
4403         if (move[cg] >= 0)
4404         {
4405             mc       = move[cg];
4406             flag     = mc & ~DD_FLAG_NRCG;
4407             mc       = mc & DD_FLAG_NRCG;
4408             move[cg] = mc;
4409
4410             if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
4411             {
4412                 comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
4413                 srenew(comm->cggl_flag[mc], comm->cggl_flag_nalloc[mc]*DD_CGIBS);
4414             }
4415             comm->cggl_flag[mc][ncg[mc]*DD_CGIBS  ] = dd->index_gl[cg];
4416             /* We store the cg size in the lower 16 bits
4417              * and the place where the charge group should go
4418              * in the next 6 bits. This saves some communication volume.
4419              */
4420             nrcg = cgindex[cg+1] - cgindex[cg];
4421             comm->cggl_flag[mc][ncg[mc]*DD_CGIBS+1] = nrcg | flag;
4422             ncg[mc] += 1;
4423             nat[mc] += nrcg;
4424         }
4425     }
4426
4427     inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
4428     inc_nrnb(nrnb, eNR_RESETX, dd->ncg_home);
4429
4430     *ncg_moved = 0;
4431     for (i = 0; i < dd->ndim*2; i++)
4432     {
4433         *ncg_moved += ncg[i];
4434     }
4435
4436     nvec = 1;
4437     if (bV)
4438     {
4439         nvec++;
4440     }
4441     if (bCGP)
4442     {
4443         nvec++;
4444     }
4445
4446     /* Make sure the communication buffers are large enough */
4447     for (mc = 0; mc < dd->ndim*2; mc++)
4448     {
4449         nvr = ncg[mc] + nat[mc]*nvec;
4450         if (nvr > comm->cgcm_state_nalloc[mc])
4451         {
4452             comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr);
4453             srenew(comm->cgcm_state[mc], comm->cgcm_state_nalloc[mc]);
4454         }
4455     }
4456
4457     switch (fr->cutoff_scheme)
4458     {
4459         case ecutsGROUP:
4460             /* Recalculating cg_cm might be cheaper than communicating,
4461              * but that could give rise to rounding issues.
4462              */
4463             home_pos_cg =
4464                 compact_and_copy_vec_cg(dd->ncg_home, move, cgindex,
4465                                         nvec, cg_cm, comm, bCompact);
4466             break;
4467         case ecutsVERLET:
4468             /* Without charge groups we send the moved atom coordinates
4469              * over twice. This is so the code below can be used without
4470              * many conditionals for both for with and without charge groups.
4471              */
4472             home_pos_cg =
4473                 compact_and_copy_vec_cg(dd->ncg_home, move, cgindex,
4474                                         nvec, as_rvec_array(state->x.data()), comm, FALSE);
4475             if (bCompact)
4476             {
4477                 home_pos_cg -= *ncg_moved;
4478             }
4479             break;
4480         default:
4481             gmx_incons("unimplemented");
4482             home_pos_cg = 0;
4483     }
4484
4485     vec         = 0;
4486     home_pos_at =
4487         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4488                                 nvec, vec++, as_rvec_array(state->x.data()),
4489                                 comm, bCompact);
4490     if (bV)
4491     {
4492         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4493                                 nvec, vec++, as_rvec_array(state->v.data()),
4494                                 comm, bCompact);
4495     }
4496     if (bCGP)
4497     {
4498         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4499                                 nvec, vec++, as_rvec_array(state->cg_p.data()),
4500                                 comm, bCompact);
4501     }
4502
4503     if (bCompact)
4504     {
4505         compact_ind(dd->ncg_home, move,
4506                     dd->index_gl, dd->cgindex, dd->gatindex,
4507                     dd->ga2la, comm->bLocalCG,
4508                     fr->cginfo);
4509     }
4510     else
4511     {
4512         if (fr->cutoff_scheme == ecutsVERLET)
4513         {
4514             moved = get_moved(comm, dd->ncg_home);
4515
4516             for (k = 0; k < dd->ncg_home; k++)
4517             {
4518                 moved[k] = 0;
4519             }
4520         }
4521         else
4522         {
4523             moved = fr->ns->grid->cell_index;
4524         }
4525
4526         clear_and_mark_ind(dd->ncg_home, move,
4527                            dd->index_gl, dd->cgindex, dd->gatindex,
4528                            dd->ga2la, comm->bLocalCG,
4529                            moved);
4530     }
4531
4532     cginfo_mb = fr->cginfo_mb;
4533
4534     *ncg_stay_home = home_pos_cg;
4535     for (d = 0; d < dd->ndim; d++)
4536     {
4537         dim      = dd->dim[d];
4538         ncg_recv = 0;
4539         nvr      = 0;
4540         for (dir = 0; dir < (dd->nc[dim] == 2 ? 1 : 2); dir++)
4541         {
4542             cdd = d*2 + dir;
4543             /* Communicate the cg and atom counts */
4544             sbuf[0] = ncg[cdd];
4545             sbuf[1] = nat[cdd];
4546             if (debug)
4547             {
4548                 fprintf(debug, "Sending ddim %d dir %d: ncg %d nat %d\n",
4549                         d, dir, sbuf[0], sbuf[1]);
4550             }
4551             dd_sendrecv_int(dd, d, dir, sbuf, 2, rbuf, 2);
4552
4553             if ((ncg_recv+rbuf[0])*DD_CGIBS > comm->nalloc_int)
4554             {
4555                 comm->nalloc_int = over_alloc_dd((ncg_recv+rbuf[0])*DD_CGIBS);
4556                 srenew(comm->buf_int, comm->nalloc_int);
4557             }
4558
4559             /* Communicate the charge group indices, sizes and flags */
4560             dd_sendrecv_int(dd, d, dir,
4561                             comm->cggl_flag[cdd], sbuf[0]*DD_CGIBS,
4562                             comm->buf_int+ncg_recv*DD_CGIBS, rbuf[0]*DD_CGIBS);
4563
4564             nvs = ncg[cdd] + nat[cdd]*nvec;
4565             i   = rbuf[0]  + rbuf[1] *nvec;
4566             vec_rvec_check_alloc(&comm->vbuf, nvr+i);
4567
4568             /* Communicate cgcm and state */
4569             dd_sendrecv_rvec(dd, d, dir,
4570                              comm->cgcm_state[cdd], nvs,
4571                              comm->vbuf.v+nvr, i);
4572             ncg_recv += rbuf[0];
4573             nvr      += i;
4574         }
4575
4576         dd_check_alloc_ncg(fr, state, f, home_pos_cg + ncg_recv);
4577         if (fr->cutoff_scheme == ecutsGROUP)
4578         {
4579             /* Here we resize to more than necessary and shrink later */
4580             dd_resize_state(state, f, home_pos_at + ncg_recv*MAX_CGCGSIZE);
4581         }
4582
4583         /* Process the received charge groups */
4584         buf_pos = 0;
4585         for (cg = 0; cg < ncg_recv; cg++)
4586         {
4587             flag = comm->buf_int[cg*DD_CGIBS+1];
4588
4589             if (dim >= npbcdim && dd->nc[dim] > 2)
4590             {
4591                 /* No pbc in this dim and more than one domain boundary.
4592                  * We do a separate check if a charge group didn't move too far.
4593                  */
4594                 if (((flag & DD_FLAG_FW(d)) &&
4595                      comm->vbuf.v[buf_pos][dim] > cell_x1[dim]) ||
4596                     ((flag & DD_FLAG_BW(d)) &&
4597                      comm->vbuf.v[buf_pos][dim] < cell_x0[dim]))
4598                 {
4599                     cg_move_error(fplog, dd, step, cg, dim,
4600                                   (flag & DD_FLAG_FW(d)) ? 1 : 0,
4601                                   fr->cutoff_scheme == ecutsGROUP, 0,
4602                                   comm->vbuf.v[buf_pos],
4603                                   comm->vbuf.v[buf_pos],
4604                                   comm->vbuf.v[buf_pos][dim]);
4605                 }
4606             }
4607
4608             mc = -1;
4609             if (d < dd->ndim-1)
4610             {
4611                 /* Check which direction this cg should go */
4612                 for (d2 = d+1; (d2 < dd->ndim && mc == -1); d2++)
4613                 {
4614                     if (isDlbOn(dd->comm))
4615                     {
4616                         /* The cell boundaries for dimension d2 are not equal
4617                          * for each cell row of the lower dimension(s),
4618                          * therefore we might need to redetermine where
4619                          * this cg should go.
4620                          */
4621                         dim2 = dd->dim[d2];
4622                         /* If this cg crosses the box boundary in dimension d2
4623                          * we can use the communicated flag, so we do not
4624                          * have to worry about pbc.
4625                          */
4626                         if (!((dd->ci[dim2] == dd->nc[dim2]-1 &&
4627                                (flag & DD_FLAG_FW(d2))) ||
4628                               (dd->ci[dim2] == 0 &&
4629                                (flag & DD_FLAG_BW(d2)))))
4630                         {
4631                             /* Clear the two flags for this dimension */
4632                             flag &= ~(DD_FLAG_FW(d2) | DD_FLAG_BW(d2));
4633                             /* Determine the location of this cg
4634                              * in lattice coordinates
4635                              */
4636                             pos_d = comm->vbuf.v[buf_pos][dim2];
4637                             if (tric_dir[dim2])
4638                             {
4639                                 for (d3 = dim2+1; d3 < DIM; d3++)
4640                                 {
4641                                     pos_d +=
4642                                         comm->vbuf.v[buf_pos][d3]*tcm[d3][dim2];
4643                                 }
4644                             }
4645                             /* Check of we are not at the box edge.
4646                              * pbc is only handled in the first step above,
4647                              * but this check could move over pbc while
4648                              * the first step did not due to different rounding.
4649                              */
4650                             if (pos_d >= cell_x1[dim2] &&
4651                                 dd->ci[dim2] != dd->nc[dim2]-1)
4652                             {
4653                                 flag |= DD_FLAG_FW(d2);
4654                             }
4655                             else if (pos_d < cell_x0[dim2] &&
4656                                      dd->ci[dim2] != 0)
4657                             {
4658                                 flag |= DD_FLAG_BW(d2);
4659                             }
4660                             comm->buf_int[cg*DD_CGIBS+1] = flag;
4661                         }
4662                     }
4663                     /* Set to which neighboring cell this cg should go */
4664                     if (flag & DD_FLAG_FW(d2))
4665                     {
4666                         mc = d2*2;
4667                     }
4668                     else if (flag & DD_FLAG_BW(d2))
4669                     {
4670                         if (dd->nc[dd->dim[d2]] > 2)
4671                         {
4672                             mc = d2*2+1;
4673                         }
4674                         else
4675                         {
4676                             mc = d2*2;
4677                         }
4678                     }
4679                 }
4680             }
4681
4682             nrcg = flag & DD_FLAG_NRCG;
4683             if (mc == -1)
4684             {
4685                 if (home_pos_cg+1 > dd->cg_nalloc)
4686                 {
4687                     dd->cg_nalloc = over_alloc_dd(home_pos_cg+1);
4688                     srenew(dd->index_gl, dd->cg_nalloc);
4689                     srenew(dd->cgindex, dd->cg_nalloc+1);
4690                 }
4691                 /* Set the global charge group index and size */
4692                 dd->index_gl[home_pos_cg]  = comm->buf_int[cg*DD_CGIBS];
4693                 dd->cgindex[home_pos_cg+1] = dd->cgindex[home_pos_cg] + nrcg;
4694                 /* Copy the state from the buffer */
4695                 if (fr->cutoff_scheme == ecutsGROUP)
4696                 {
4697                     cg_cm = fr->cg_cm;
4698                     copy_rvec(comm->vbuf.v[buf_pos], cg_cm[home_pos_cg]);
4699                 }
4700                 buf_pos++;
4701
4702                 /* Set the cginfo */
4703                 fr->cginfo[home_pos_cg] = ddcginfo(cginfo_mb,
4704                                                    dd->index_gl[home_pos_cg]);
4705                 if (comm->bLocalCG)
4706                 {
4707                     comm->bLocalCG[dd->index_gl[home_pos_cg]] = TRUE;
4708                 }
4709
4710                 for (i = 0; i < nrcg; i++)
4711                 {
4712                     copy_rvec(comm->vbuf.v[buf_pos++],
4713                               state->x[home_pos_at+i]);
4714                 }
4715                 if (bV)
4716                 {
4717                     for (i = 0; i < nrcg; i++)
4718                     {
4719                         copy_rvec(comm->vbuf.v[buf_pos++],
4720                                   state->v[home_pos_at+i]);
4721                     }
4722                 }
4723                 if (bCGP)
4724                 {
4725                     for (i = 0; i < nrcg; i++)
4726                     {
4727                         copy_rvec(comm->vbuf.v[buf_pos++],
4728                                   state->cg_p[home_pos_at+i]);
4729                     }
4730                 }
4731                 home_pos_cg += 1;
4732                 home_pos_at += nrcg;
4733             }
4734             else
4735             {
4736                 /* Reallocate the buffers if necessary  */
4737                 if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
4738                 {
4739                     comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
4740                     srenew(comm->cggl_flag[mc], comm->cggl_flag_nalloc[mc]*DD_CGIBS);
4741                 }
4742                 nvr = ncg[mc] + nat[mc]*nvec;
4743                 if (nvr + 1 + nrcg*nvec > comm->cgcm_state_nalloc[mc])
4744                 {
4745                     comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr + 1 + nrcg*nvec);
4746                     srenew(comm->cgcm_state[mc], comm->cgcm_state_nalloc[mc]);
4747                 }
4748                 /* Copy from the receive to the send buffers */
4749                 memcpy(comm->cggl_flag[mc] + ncg[mc]*DD_CGIBS,
4750                        comm->buf_int + cg*DD_CGIBS,
4751                        DD_CGIBS*sizeof(int));
4752                 memcpy(comm->cgcm_state[mc][nvr],
4753                        comm->vbuf.v[buf_pos],
4754                        (1+nrcg*nvec)*sizeof(rvec));
4755                 buf_pos += 1 + nrcg*nvec;
4756                 ncg[mc] += 1;
4757                 nat[mc] += nrcg;
4758             }
4759         }
4760     }
4761
4762     /* With sorting (!bCompact) the indices are now only partially up to date
4763      * and ncg_home and nat_home are not the real count, since there are
4764      * "holes" in the arrays for the charge groups that moved to neighbors.
4765      */
4766     if (fr->cutoff_scheme == ecutsVERLET)
4767     {
4768         moved = get_moved(comm, home_pos_cg);
4769
4770         for (i = dd->ncg_home; i < home_pos_cg; i++)
4771         {
4772             moved[i] = 0;
4773         }
4774     }
4775     dd->ncg_home = home_pos_cg;
4776     dd->nat_home = home_pos_at;
4777
4778     if (fr->cutoff_scheme == ecutsGROUP && !bCompact)
4779     {
4780         /* We overallocated before, we need to set the right size here */
4781         dd_resize_state(state, f, dd->nat_home);
4782     }
4783
4784     if (debug)
4785     {
4786         fprintf(debug,
4787                 "Finished repartitioning: cgs moved out %d, new home %d\n",
4788                 *ncg_moved, dd->ncg_home-*ncg_moved);
4789
4790     }
4791 }
4792
4793 void dd_cycles_add(const gmx_domdec_t *dd, float cycles, int ddCycl)
4794 {
4795     /* Note that the cycles value can be incorrect, either 0 or some
4796      * extremely large value, when our thread migrated to another core
4797      * with an unsynchronized cycle counter. If this happens less often
4798      * that once per nstlist steps, this will not cause issues, since
4799      * we later subtract the maximum value from the sum over nstlist steps.
4800      * A zero count will slightly lower the total, but that's a small effect.
4801      * Note that the main purpose of the subtraction of the maximum value
4802      * is to avoid throwing off the load balancing when stalls occur due
4803      * e.g. system activity or network congestion.
4804      */
4805     dd->comm->cycl[ddCycl] += cycles;
4806     dd->comm->cycl_n[ddCycl]++;
4807     if (cycles > dd->comm->cycl_max[ddCycl])
4808     {
4809         dd->comm->cycl_max[ddCycl] = cycles;
4810     }
4811 }
4812
4813 static double force_flop_count(t_nrnb *nrnb)
4814 {
4815     int         i;
4816     double      sum;
4817     const char *name;
4818
4819     sum = 0;
4820     for (i = 0; i < eNR_NBKERNEL_FREE_ENERGY; i++)
4821     {
4822         /* To get closer to the real timings, we half the count
4823          * for the normal loops and again half it for water loops.
4824          */
4825         name = nrnb_str(i);
4826         if (strstr(name, "W3") != nullptr || strstr(name, "W4") != nullptr)
4827         {
4828             sum += nrnb->n[i]*0.25*cost_nrnb(i);
4829         }
4830         else
4831         {
4832             sum += nrnb->n[i]*0.50*cost_nrnb(i);
4833         }
4834     }
4835     for (i = eNR_NBKERNEL_FREE_ENERGY; i <= eNR_NB14; i++)
4836     {
4837         name = nrnb_str(i);
4838         if (strstr(name, "W3") != nullptr || strstr(name, "W4") != nullptr)
4839         {
4840             sum += nrnb->n[i]*cost_nrnb(i);
4841         }
4842     }
4843     for (i = eNR_BONDS; i <= eNR_WALLS; i++)
4844     {
4845         sum += nrnb->n[i]*cost_nrnb(i);
4846     }
4847
4848     return sum;
4849 }
4850
4851 void dd_force_flop_start(gmx_domdec_t *dd, t_nrnb *nrnb)
4852 {
4853     if (dd->comm->eFlop)
4854     {
4855         dd->comm->flop -= force_flop_count(nrnb);
4856     }
4857 }
4858 void dd_force_flop_stop(gmx_domdec_t *dd, t_nrnb *nrnb)
4859 {
4860     if (dd->comm->eFlop)
4861     {
4862         dd->comm->flop += force_flop_count(nrnb);
4863         dd->comm->flop_n++;
4864     }
4865 }
4866
4867 static void clear_dd_cycle_counts(gmx_domdec_t *dd)
4868 {
4869     int i;
4870
4871     for (i = 0; i < ddCyclNr; i++)
4872     {
4873         dd->comm->cycl[i]     = 0;
4874         dd->comm->cycl_n[i]   = 0;
4875         dd->comm->cycl_max[i] = 0;
4876     }
4877     dd->comm->flop   = 0;
4878     dd->comm->flop_n = 0;
4879 }
4880
4881 static void get_load_distribution(gmx_domdec_t *dd, gmx_wallcycle_t wcycle)
4882 {
4883     gmx_domdec_comm_t *comm;
4884     domdec_load_t     *load;
4885     domdec_root_t     *root = nullptr;
4886     int                d, dim, i, pos;
4887     float              cell_frac = 0, sbuf[DD_NLOAD_MAX];
4888     gmx_bool           bSepPME;
4889
4890     if (debug)
4891     {
4892         fprintf(debug, "get_load_distribution start\n");
4893     }
4894
4895     wallcycle_start(wcycle, ewcDDCOMMLOAD);
4896
4897     comm = dd->comm;
4898
4899     bSepPME = (dd->pme_nodeid >= 0);
4900
4901     if (dd->ndim == 0 && bSepPME)
4902     {
4903         /* Without decomposition, but with PME nodes, we need the load */
4904         comm->load[0].mdf = comm->cycl[ddCyclPPduringPME];
4905         comm->load[0].pme = comm->cycl[ddCyclPME];
4906     }
4907
4908     for (d = dd->ndim-1; d >= 0; d--)
4909     {
4910         dim = dd->dim[d];
4911         /* Check if we participate in the communication in this dimension */
4912         if (d == dd->ndim-1 ||
4913             (dd->ci[dd->dim[d+1]] == 0 && dd->ci[dd->dim[dd->ndim-1]] == 0))
4914         {
4915             load = &comm->load[d];
4916             if (isDlbOn(dd->comm))
4917             {
4918                 cell_frac = comm->cell_f1[d] - comm->cell_f0[d];
4919             }
4920             pos = 0;
4921             if (d == dd->ndim-1)
4922             {
4923                 sbuf[pos++] = dd_force_load(comm);
4924                 sbuf[pos++] = sbuf[0];
4925                 if (isDlbOn(dd->comm))
4926                 {
4927                     sbuf[pos++] = sbuf[0];
4928                     sbuf[pos++] = cell_frac;
4929                     if (d > 0)
4930                     {
4931                         sbuf[pos++] = comm->cell_f_max0[d];
4932                         sbuf[pos++] = comm->cell_f_min1[d];
4933                     }
4934                 }
4935                 if (bSepPME)
4936                 {
4937                     sbuf[pos++] = comm->cycl[ddCyclPPduringPME];
4938                     sbuf[pos++] = comm->cycl[ddCyclPME];
4939                 }
4940             }
4941             else
4942             {
4943                 sbuf[pos++] = comm->load[d+1].sum;
4944                 sbuf[pos++] = comm->load[d+1].max;
4945                 if (isDlbOn(dd->comm))
4946                 {
4947                     sbuf[pos++] = comm->load[d+1].sum_m;
4948                     sbuf[pos++] = comm->load[d+1].cvol_min*cell_frac;
4949                     sbuf[pos++] = comm->load[d+1].flags;
4950                     if (d > 0)
4951                     {
4952                         sbuf[pos++] = comm->cell_f_max0[d];
4953                         sbuf[pos++] = comm->cell_f_min1[d];
4954                     }
4955                 }
4956                 if (bSepPME)
4957                 {
4958                     sbuf[pos++] = comm->load[d+1].mdf;
4959                     sbuf[pos++] = comm->load[d+1].pme;
4960                 }
4961             }
4962             load->nload = pos;
4963             /* Communicate a row in DD direction d.
4964              * The communicators are setup such that the root always has rank 0.
4965              */
4966 #if GMX_MPI
4967             MPI_Gather(sbuf, load->nload*sizeof(float), MPI_BYTE,
4968                        load->load, load->nload*sizeof(float), MPI_BYTE,
4969                        0, comm->mpi_comm_load[d]);
4970 #endif
4971             if (dd->ci[dim] == dd->master_ci[dim])
4972             {
4973                 /* We are the root, process this row */
4974                 if (isDlbOn(comm))
4975                 {
4976                     root = comm->root[d];
4977                 }
4978                 load->sum      = 0;
4979                 load->max      = 0;
4980                 load->sum_m    = 0;
4981                 load->cvol_min = 1;
4982                 load->flags    = 0;
4983                 load->mdf      = 0;
4984                 load->pme      = 0;
4985                 pos            = 0;
4986                 for (i = 0; i < dd->nc[dim]; i++)
4987                 {
4988                     load->sum += load->load[pos++];
4989                     load->max  = std::max(load->max, load->load[pos]);
4990                     pos++;
4991                     if (isDlbOn(dd->comm))
4992                     {
4993                         if (root->bLimited)
4994                         {
4995                             /* This direction could not be load balanced properly,
4996                              * therefore we need to use the maximum iso the average load.
4997                              */
4998                             load->sum_m = std::max(load->sum_m, load->load[pos]);
4999                         }
5000                         else
5001                         {
5002                             load->sum_m += load->load[pos];
5003                         }
5004                         pos++;
5005                         load->cvol_min = std::min(load->cvol_min, load->load[pos]);
5006                         pos++;
5007                         if (d < dd->ndim-1)
5008                         {
5009                             load->flags = (int)(load->load[pos++] + 0.5);
5010                         }
5011                         if (d > 0)
5012                         {
5013                             root->cell_f_max0[i] = load->load[pos++];
5014                             root->cell_f_min1[i] = load->load[pos++];
5015                         }
5016                     }
5017                     if (bSepPME)
5018                     {
5019                         load->mdf = std::max(load->mdf, load->load[pos]);
5020                         pos++;
5021                         load->pme = std::max(load->pme, load->load[pos]);
5022                         pos++;
5023                     }
5024                 }
5025                 if (isDlbOn(comm) && root->bLimited)
5026                 {
5027                     load->sum_m *= dd->nc[dim];
5028                     load->flags |= (1<<d);
5029                 }
5030             }
5031         }
5032     }
5033
5034     if (DDMASTER(dd))
5035     {
5036         comm->nload      += dd_load_count(comm);
5037         comm->load_step  += comm->cycl[ddCyclStep];
5038         comm->load_sum   += comm->load[0].sum;
5039         comm->load_max   += comm->load[0].max;
5040         if (isDlbOn(comm))
5041         {
5042             for (d = 0; d < dd->ndim; d++)
5043             {
5044                 if (comm->load[0].flags & (1<<d))
5045                 {
5046                     comm->load_lim[d]++;
5047                 }
5048             }
5049         }
5050         if (bSepPME)
5051         {
5052             comm->load_mdf += comm->load[0].mdf;
5053             comm->load_pme += comm->load[0].pme;
5054         }
5055     }
5056
5057     wallcycle_stop(wcycle, ewcDDCOMMLOAD);
5058
5059     if (debug)
5060     {
5061         fprintf(debug, "get_load_distribution finished\n");
5062     }
5063 }
5064
5065 static float dd_force_load_fraction(gmx_domdec_t *dd)
5066 {
5067     /* Return the relative performance loss on the total run time
5068      * due to the force calculation load imbalance.
5069      */
5070     if (dd->comm->nload > 0 && dd->comm->load_step > 0)
5071     {
5072         return dd->comm->load_sum/(dd->comm->load_step*dd->nnodes);
5073     }
5074     else
5075     {
5076         return 0;
5077     }
5078 }
5079
5080 static float dd_force_imb_perf_loss(gmx_domdec_t *dd)
5081 {
5082     /* Return the relative performance loss on the total run time
5083      * due to the force calculation load imbalance.
5084      */
5085     if (dd->comm->nload > 0 && dd->comm->load_step > 0)
5086     {
5087         return
5088             (dd->comm->load_max*dd->nnodes - dd->comm->load_sum)/
5089             (dd->comm->load_step*dd->nnodes);
5090     }
5091     else
5092     {
5093         return 0;
5094     }
5095 }
5096
5097 static void print_dd_load_av(FILE *fplog, gmx_domdec_t *dd)
5098 {
5099     gmx_domdec_comm_t *comm = dd->comm;
5100
5101     /* Only the master rank prints loads and only if we measured loads */
5102     if (!DDMASTER(dd) || comm->nload == 0)
5103     {
5104         return;
5105     }
5106
5107     char  buf[STRLEN];
5108     int   numPpRanks   = dd->nnodes;
5109     int   numPmeRanks  = (dd->pme_nodeid >= 0) ? comm->npmenodes : 0;
5110     int   numRanks     = numPpRanks + numPmeRanks;
5111     float lossFraction = 0;
5112
5113     /* Print the average load imbalance and performance loss */
5114     if (dd->nnodes > 1 && comm->load_sum > 0)
5115     {
5116         float imbalance = comm->load_max*numPpRanks/comm->load_sum - 1;
5117         lossFraction    = dd_force_imb_perf_loss(dd);
5118
5119         std::string msg         = "\n Dynamic load balancing report:\n";
5120         std::string dlbStateStr = "";
5121
5122         switch (dd->comm->dlbState)
5123         {
5124             case edlbsOffUser:
5125                 dlbStateStr = "DLB was off during the run per user request.";
5126                 break;
5127             case edlbsOffForever:
5128                 /* Currectly this can happen due to performance loss observed, cell size
5129                  * limitations or incompatibility with other settings observed during
5130                  * determineInitialDlbState(). */
5131                 dlbStateStr = "DLB got disabled because it was unsuitable to use.";
5132                 break;
5133             case edlbsOffCanTurnOn:
5134                 dlbStateStr = "DLB was off during the run due to low measured imbalance.";
5135                 break;
5136             case edlbsOffTemporarilyLocked:
5137                 dlbStateStr = "DLB was locked at the end of the run due to unfinished PP-PME balancing.";
5138                 break;
5139             case edlbsOnCanTurnOff:
5140                 dlbStateStr = "DLB was turned on during the run due to measured imbalance.";
5141                 break;
5142             case edlbsOnUser:
5143                 dlbStateStr = "DLB was permanently on during the run per user request.";
5144                 break;
5145             default:
5146                 GMX_ASSERT(false, "Undocumented DLB state");
5147         }
5148
5149         msg += " " + dlbStateStr + "\n";
5150         msg += gmx::formatString(" Average load imbalance: %.1f%%.\n", imbalance*100);
5151         msg += gmx::formatString(" The balanceable part of the MD step is %d%%, load imbalance is computed from this.\n",
5152                                  static_cast<int>(dd_force_load_fraction(dd)*100 + 0.5));
5153         msg += gmx::formatString(" Part of the total run time spent waiting due to load imbalance: %.1f%%.\n",
5154                                  lossFraction*100);
5155         fprintf(fplog, "%s", msg.c_str());
5156         fprintf(stderr, "%s", msg.c_str());
5157     }
5158
5159     /* Print during what percentage of steps the  load balancing was limited */
5160     bool dlbWasLimited = false;
5161     if (isDlbOn(comm))
5162     {
5163         sprintf(buf, " Steps where the load balancing was limited by -rdd, -rcon and/or -dds:");
5164         for (int d = 0; d < dd->ndim; d++)
5165         {
5166             int limitPercentage = (200*comm->load_lim[d] + 1)/(2*comm->nload);
5167             sprintf(buf+strlen(buf), " %c %d %%",
5168                     dim2char(dd->dim[d]), limitPercentage);
5169             if (limitPercentage >= 50)
5170             {
5171                 dlbWasLimited = true;
5172             }
5173         }
5174         sprintf(buf + strlen(buf), "\n");
5175         fprintf(fplog, "%s", buf);
5176         fprintf(stderr, "%s", buf);
5177     }
5178
5179     /* Print the performance loss due to separate PME - PP rank imbalance */
5180     float lossFractionPme = 0;
5181     if (numPmeRanks > 0 && comm->load_mdf > 0 && comm->load_step > 0)
5182     {
5183         float pmeForceRatio = comm->load_pme/comm->load_mdf;
5184         lossFractionPme     = (comm->load_pme - comm->load_mdf)/comm->load_step;
5185         if (lossFractionPme <= 0)
5186         {
5187             lossFractionPme *= numPmeRanks/static_cast<float>(numRanks);
5188         }
5189         else
5190         {
5191             lossFractionPme *= numPpRanks/static_cast<float>(numRanks);
5192         }
5193         sprintf(buf, " Average PME mesh/force load: %5.3f\n", pmeForceRatio);
5194         fprintf(fplog, "%s", buf);
5195         fprintf(stderr, "%s", buf);
5196         sprintf(buf, " Part of the total run time spent waiting due to PP/PME imbalance: %.1f %%\n", fabs(lossFractionPme)*100);
5197         fprintf(fplog, "%s", buf);
5198         fprintf(stderr, "%s", buf);
5199     }
5200     fprintf(fplog, "\n");
5201     fprintf(stderr, "\n");
5202
5203     if (lossFraction >= DD_PERF_LOSS_WARN)
5204     {
5205         sprintf(buf,
5206                 "NOTE: %.1f %% of the available CPU time was lost due to load imbalance\n"
5207                 "      in the domain decomposition.\n", lossFraction*100);
5208         if (!isDlbOn(comm))
5209         {
5210             sprintf(buf+strlen(buf), "      You might want to use dynamic load balancing (option -dlb.)\n");
5211         }
5212         else if (dlbWasLimited)
5213         {
5214             sprintf(buf+strlen(buf), "      You might want to decrease the cell size limit (options -rdd, -rcon and/or -dds).\n");
5215         }
5216         fprintf(fplog, "%s\n", buf);
5217         fprintf(stderr, "%s\n", buf);
5218     }
5219     if (numPmeRanks > 0 && fabs(lossFractionPme) >= DD_PERF_LOSS_WARN)
5220     {
5221         sprintf(buf,
5222                 "NOTE: %.1f %% performance was lost because the PME ranks\n"
5223                 "      had %s work to do than the PP ranks.\n"
5224                 "      You might want to %s the number of PME ranks\n"
5225                 "      or %s the cut-off and the grid spacing.\n",
5226                 fabs(lossFractionPme*100),
5227                 (lossFractionPme < 0) ? "less"     : "more",
5228                 (lossFractionPme < 0) ? "decrease" : "increase",
5229                 (lossFractionPme < 0) ? "decrease" : "increase");
5230         fprintf(fplog, "%s\n", buf);
5231         fprintf(stderr, "%s\n", buf);
5232     }
5233 }
5234
5235 static float dd_vol_min(gmx_domdec_t *dd)
5236 {
5237     return dd->comm->load[0].cvol_min*dd->nnodes;
5238 }
5239
5240 static gmx_bool dd_load_flags(gmx_domdec_t *dd)
5241 {
5242     return dd->comm->load[0].flags;
5243 }
5244
5245 static float dd_f_imbal(gmx_domdec_t *dd)
5246 {
5247     if (dd->comm->load[0].sum > 0)
5248     {
5249         return dd->comm->load[0].max*dd->nnodes/dd->comm->load[0].sum - 1.0f;
5250     }
5251     else
5252     {
5253         /* Something is wrong in the cycle counting, report no load imbalance */
5254         return 0.0f;
5255     }
5256 }
5257
5258 float dd_pme_f_ratio(gmx_domdec_t *dd)
5259 {
5260     /* Should only be called on the DD master rank */
5261     assert(DDMASTER(dd));
5262
5263     if (dd->comm->load[0].mdf > 0 && dd->comm->cycl_n[ddCyclPME] > 0)
5264     {
5265         return dd->comm->load[0].pme/dd->comm->load[0].mdf;
5266     }
5267     else
5268     {
5269         return -1.0;
5270     }
5271 }
5272
5273 static void dd_print_load(FILE *fplog, gmx_domdec_t *dd, gmx_int64_t step)
5274 {
5275     int  flags, d;
5276     char buf[22];
5277
5278     flags = dd_load_flags(dd);
5279     if (flags)
5280     {
5281         fprintf(fplog,
5282                 "DD  load balancing is limited by minimum cell size in dimension");
5283         for (d = 0; d < dd->ndim; d++)
5284         {
5285             if (flags & (1<<d))
5286             {
5287                 fprintf(fplog, " %c", dim2char(dd->dim[d]));
5288             }
5289         }
5290         fprintf(fplog, "\n");
5291     }
5292     fprintf(fplog, "DD  step %s", gmx_step_str(step, buf));
5293     if (isDlbOn(dd->comm))
5294     {
5295         fprintf(fplog, "  vol min/aver %5.3f%c",
5296                 dd_vol_min(dd), flags ? '!' : ' ');
5297     }
5298     if (dd->nnodes > 1)
5299     {
5300         fprintf(fplog, " load imb.: force %4.1f%%", dd_f_imbal(dd)*100);
5301     }
5302     if (dd->comm->cycl_n[ddCyclPME])
5303     {
5304         fprintf(fplog, "  pme mesh/force %5.3f", dd_pme_f_ratio(dd));
5305     }
5306     fprintf(fplog, "\n\n");
5307 }
5308
5309 static void dd_print_load_verbose(gmx_domdec_t *dd)
5310 {
5311     if (isDlbOn(dd->comm))
5312     {
5313         fprintf(stderr, "vol %4.2f%c ",
5314                 dd_vol_min(dd), dd_load_flags(dd) ? '!' : ' ');
5315     }
5316     if (dd->nnodes > 1)
5317     {
5318         fprintf(stderr, "imb F %2d%% ", (int)(dd_f_imbal(dd)*100+0.5));
5319     }
5320     if (dd->comm->cycl_n[ddCyclPME])
5321     {
5322         fprintf(stderr, "pme/F %4.2f ", dd_pme_f_ratio(dd));
5323     }
5324 }
5325
5326 #if GMX_MPI
5327 static void make_load_communicator(gmx_domdec_t *dd, int dim_ind, ivec loc)
5328 {
5329     MPI_Comm           c_row;
5330     int                dim, i, rank;
5331     ivec               loc_c;
5332     domdec_root_t     *root;
5333     gmx_bool           bPartOfGroup = FALSE;
5334
5335     dim = dd->dim[dim_ind];
5336     copy_ivec(loc, loc_c);
5337     for (i = 0; i < dd->nc[dim]; i++)
5338     {
5339         loc_c[dim] = i;
5340         rank       = dd_index(dd->nc, loc_c);
5341         if (rank == dd->rank)
5342         {
5343             /* This process is part of the group */
5344             bPartOfGroup = TRUE;
5345         }
5346     }
5347     MPI_Comm_split(dd->mpi_comm_all, bPartOfGroup ? 0 : MPI_UNDEFINED, dd->rank,
5348                    &c_row);
5349     if (bPartOfGroup)
5350     {
5351         dd->comm->mpi_comm_load[dim_ind] = c_row;
5352         if (!isDlbDisabled(dd->comm))
5353         {
5354             if (dd->ci[dim] == dd->master_ci[dim])
5355             {
5356                 /* This is the root process of this row */
5357                 snew(dd->comm->root[dim_ind], 1);
5358                 root = dd->comm->root[dim_ind];
5359                 snew(root->cell_f, DD_CELL_F_SIZE(dd, dim_ind));
5360                 snew(root->old_cell_f, dd->nc[dim]+1);
5361                 snew(root->bCellMin, dd->nc[dim]);
5362                 if (dim_ind > 0)
5363                 {
5364                     snew(root->cell_f_max0, dd->nc[dim]);
5365                     snew(root->cell_f_min1, dd->nc[dim]);
5366                     snew(root->bound_min, dd->nc[dim]);
5367                     snew(root->bound_max, dd->nc[dim]);
5368                 }
5369                 snew(root->buf_ncd, dd->nc[dim]);
5370             }
5371             else
5372             {
5373                 /* This is not a root process, we only need to receive cell_f */
5374                 snew(dd->comm->cell_f_row, DD_CELL_F_SIZE(dd, dim_ind));
5375             }
5376         }
5377         if (dd->ci[dim] == dd->master_ci[dim])
5378         {
5379             snew(dd->comm->load[dim_ind].load, dd->nc[dim]*DD_NLOAD_MAX);
5380         }
5381     }
5382 }
5383 #endif
5384
5385 void dd_setup_dlb_resource_sharing(t_commrec            *cr,
5386                                    int                   gpu_id)
5387 {
5388 #if GMX_MPI
5389     int           physicalnode_id_hash;
5390     gmx_domdec_t *dd;
5391     MPI_Comm      mpi_comm_pp_physicalnode;
5392
5393     if (!thisRankHasDuty(cr, DUTY_PP) || gpu_id < 0)
5394     {
5395         /* Only ranks with short-ranged tasks (currently) use GPUs.
5396          * If we don't have GPUs assigned, there are no resources to share.
5397          */
5398         return;
5399     }
5400
5401     physicalnode_id_hash = gmx_physicalnode_id_hash();
5402
5403     dd = cr->dd;
5404
5405     if (debug)
5406     {
5407         fprintf(debug, "dd_setup_dd_dlb_gpu_sharing:\n");
5408         fprintf(debug, "DD PP rank %d physical node hash %d gpu_id %d\n",
5409                 dd->rank, physicalnode_id_hash, gpu_id);
5410     }
5411     /* Split the PP communicator over the physical nodes */
5412     /* TODO: See if we should store this (before), as it's also used for
5413      * for the nodecomm summution.
5414      */
5415     MPI_Comm_split(dd->mpi_comm_all, physicalnode_id_hash, dd->rank,
5416                    &mpi_comm_pp_physicalnode);
5417     MPI_Comm_split(mpi_comm_pp_physicalnode, gpu_id, dd->rank,
5418                    &dd->comm->mpi_comm_gpu_shared);
5419     MPI_Comm_free(&mpi_comm_pp_physicalnode);
5420     MPI_Comm_size(dd->comm->mpi_comm_gpu_shared, &dd->comm->nrank_gpu_shared);
5421
5422     if (debug)
5423     {
5424         fprintf(debug, "nrank_gpu_shared %d\n", dd->comm->nrank_gpu_shared);
5425     }
5426
5427     /* Note that some ranks could share a GPU, while others don't */
5428
5429     if (dd->comm->nrank_gpu_shared == 1)
5430     {
5431         MPI_Comm_free(&dd->comm->mpi_comm_gpu_shared);
5432     }
5433 #else
5434     GMX_UNUSED_VALUE(cr);
5435     GMX_UNUSED_VALUE(gpu_id);
5436 #endif
5437 }
5438
5439 static void make_load_communicators(gmx_domdec_t gmx_unused *dd)
5440 {
5441 #if GMX_MPI
5442     int  dim0, dim1, i, j;
5443     ivec loc;
5444
5445     if (debug)
5446     {
5447         fprintf(debug, "Making load communicators\n");
5448     }
5449
5450     snew(dd->comm->load,          std::max(dd->ndim, 1));
5451     snew(dd->comm->mpi_comm_load, std::max(dd->ndim, 1));
5452
5453     if (dd->ndim == 0)
5454     {
5455         return;
5456     }
5457
5458     clear_ivec(loc);
5459     make_load_communicator(dd, 0, loc);
5460     if (dd->ndim > 1)
5461     {
5462         dim0 = dd->dim[0];
5463         for (i = 0; i < dd->nc[dim0]; i++)
5464         {
5465             loc[dim0] = i;
5466             make_load_communicator(dd, 1, loc);
5467         }
5468     }
5469     if (dd->ndim > 2)
5470     {
5471         dim0 = dd->dim[0];
5472         for (i = 0; i < dd->nc[dim0]; i++)
5473         {
5474             loc[dim0] = i;
5475             dim1      = dd->dim[1];
5476             for (j = 0; j < dd->nc[dim1]; j++)
5477             {
5478                 loc[dim1] = j;
5479                 make_load_communicator(dd, 2, loc);
5480             }
5481         }
5482     }
5483
5484     if (debug)
5485     {
5486         fprintf(debug, "Finished making load communicators\n");
5487     }
5488 #endif
5489 }
5490
5491 /*! \brief Sets up the relation between neighboring domains and zones */
5492 static void setup_neighbor_relations(gmx_domdec_t *dd)
5493 {
5494     int                     d, dim, i, j, m;
5495     ivec                    tmp, s;
5496     gmx_domdec_zones_t     *zones;
5497     gmx_domdec_ns_ranges_t *izone;
5498
5499     for (d = 0; d < dd->ndim; d++)
5500     {
5501         dim = dd->dim[d];
5502         copy_ivec(dd->ci, tmp);
5503         tmp[dim]           = (tmp[dim] + 1) % dd->nc[dim];
5504         dd->neighbor[d][0] = ddcoord2ddnodeid(dd, tmp);
5505         copy_ivec(dd->ci, tmp);
5506         tmp[dim]           = (tmp[dim] - 1 + dd->nc[dim]) % dd->nc[dim];
5507         dd->neighbor[d][1] = ddcoord2ddnodeid(dd, tmp);
5508         if (debug)
5509         {
5510             fprintf(debug, "DD rank %d neighbor ranks in dir %d are + %d - %d\n",
5511                     dd->rank, dim,
5512                     dd->neighbor[d][0],
5513                     dd->neighbor[d][1]);
5514         }
5515     }
5516
5517     int nzone  = (1 << dd->ndim);
5518     int nizone = (1 << std::max(dd->ndim - 1, 0));
5519     assert(nizone >= 1 && nizone <= DD_MAXIZONE);
5520
5521     zones = &dd->comm->zones;
5522
5523     for (i = 0; i < nzone; i++)
5524     {
5525         m = 0;
5526         clear_ivec(zones->shift[i]);
5527         for (d = 0; d < dd->ndim; d++)
5528         {
5529             zones->shift[i][dd->dim[d]] = dd_zo[i][m++];
5530         }
5531     }
5532
5533     zones->n = nzone;
5534     for (i = 0; i < nzone; i++)
5535     {
5536         for (d = 0; d < DIM; d++)
5537         {
5538             s[d] = dd->ci[d] - zones->shift[i][d];
5539             if (s[d] < 0)
5540             {
5541                 s[d] += dd->nc[d];
5542             }
5543             else if (s[d] >= dd->nc[d])
5544             {
5545                 s[d] -= dd->nc[d];
5546             }
5547         }
5548     }
5549     zones->nizone = nizone;
5550     for (i = 0; i < zones->nizone; i++)
5551     {
5552         assert(ddNonbondedZonePairRanges[i][0] == i);
5553
5554         izone     = &zones->izone[i];
5555         /* dd_zp3 is for 3D decomposition, for fewer dimensions use only
5556          * j-zones up to nzone.
5557          */
5558         izone->j0 = std::min(ddNonbondedZonePairRanges[i][1], nzone);
5559         izone->j1 = std::min(ddNonbondedZonePairRanges[i][2], nzone);
5560         for (dim = 0; dim < DIM; dim++)
5561         {
5562             if (dd->nc[dim] == 1)
5563             {
5564                 /* All shifts should be allowed */
5565                 izone->shift0[dim] = -1;
5566                 izone->shift1[dim] = 1;
5567             }
5568             else
5569             {
5570                 /* Determine the min/max j-zone shift wrt the i-zone */
5571                 izone->shift0[dim] = 1;
5572                 izone->shift1[dim] = -1;
5573                 for (j = izone->j0; j < izone->j1; j++)
5574                 {
5575                     int shift_diff = zones->shift[j][dim] - zones->shift[i][dim];
5576                     if (shift_diff < izone->shift0[dim])
5577                     {
5578                         izone->shift0[dim] = shift_diff;
5579                     }
5580                     if (shift_diff > izone->shift1[dim])
5581                     {
5582                         izone->shift1[dim] = shift_diff;
5583                     }
5584                 }
5585             }
5586         }
5587     }
5588
5589     if (!isDlbDisabled(dd->comm))
5590     {
5591         snew(dd->comm->root, dd->ndim);
5592     }
5593
5594     if (dd->comm->bRecordLoad)
5595     {
5596         make_load_communicators(dd);
5597     }
5598 }
5599
5600 static void make_pp_communicator(FILE                 *fplog,
5601                                  gmx_domdec_t         *dd,
5602                                  t_commrec gmx_unused *cr,
5603                                  int gmx_unused        reorder)
5604 {
5605 #if GMX_MPI
5606     gmx_domdec_comm_t *comm;
5607     int                rank, *buf;
5608     ivec               periods;
5609     MPI_Comm           comm_cart;
5610
5611     comm = dd->comm;
5612
5613     if (comm->bCartesianPP)
5614     {
5615         /* Set up cartesian communication for the particle-particle part */
5616         if (fplog)
5617         {
5618             fprintf(fplog, "Will use a Cartesian communicator: %d x %d x %d\n",
5619                     dd->nc[XX], dd->nc[YY], dd->nc[ZZ]);
5620         }
5621
5622         for (int i = 0; i < DIM; i++)
5623         {
5624             periods[i] = TRUE;
5625         }
5626         MPI_Cart_create(cr->mpi_comm_mygroup, DIM, dd->nc, periods, reorder,
5627                         &comm_cart);
5628         /* We overwrite the old communicator with the new cartesian one */
5629         cr->mpi_comm_mygroup = comm_cart;
5630     }
5631
5632     dd->mpi_comm_all = cr->mpi_comm_mygroup;
5633     MPI_Comm_rank(dd->mpi_comm_all, &dd->rank);
5634
5635     if (comm->bCartesianPP_PME)
5636     {
5637         /* Since we want to use the original cartesian setup for sim,
5638          * and not the one after split, we need to make an index.
5639          */
5640         snew(comm->ddindex2ddnodeid, dd->nnodes);
5641         comm->ddindex2ddnodeid[dd_index(dd->nc, dd->ci)] = dd->rank;
5642         gmx_sumi(dd->nnodes, comm->ddindex2ddnodeid, cr);
5643         /* Get the rank of the DD master,
5644          * above we made sure that the master node is a PP node.
5645          */
5646         if (MASTER(cr))
5647         {
5648             rank = dd->rank;
5649         }
5650         else
5651         {
5652             rank = 0;
5653         }
5654         MPI_Allreduce(&rank, &dd->masterrank, 1, MPI_INT, MPI_SUM, dd->mpi_comm_all);
5655     }
5656     else if (comm->bCartesianPP)
5657     {
5658         if (cr->npmenodes == 0)
5659         {
5660             /* The PP communicator is also
5661              * the communicator for this simulation
5662              */
5663             cr->mpi_comm_mysim = cr->mpi_comm_mygroup;
5664         }
5665         cr->nodeid = dd->rank;
5666
5667         MPI_Cart_coords(dd->mpi_comm_all, dd->rank, DIM, dd->ci);
5668
5669         /* We need to make an index to go from the coordinates
5670          * to the nodeid of this simulation.
5671          */
5672         snew(comm->ddindex2simnodeid, dd->nnodes);
5673         snew(buf, dd->nnodes);
5674         if (thisRankHasDuty(cr, DUTY_PP))
5675         {
5676             buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
5677         }
5678         /* Communicate the ddindex to simulation nodeid index */
5679         MPI_Allreduce(buf, comm->ddindex2simnodeid, dd->nnodes, MPI_INT, MPI_SUM,
5680                       cr->mpi_comm_mysim);
5681         sfree(buf);
5682
5683         /* Determine the master coordinates and rank.
5684          * The DD master should be the same node as the master of this sim.
5685          */
5686         for (int i = 0; i < dd->nnodes; i++)
5687         {
5688             if (comm->ddindex2simnodeid[i] == 0)
5689             {
5690                 ddindex2xyz(dd->nc, i, dd->master_ci);
5691                 MPI_Cart_rank(dd->mpi_comm_all, dd->master_ci, &dd->masterrank);
5692             }
5693         }
5694         if (debug)
5695         {
5696             fprintf(debug, "The master rank is %d\n", dd->masterrank);
5697         }
5698     }
5699     else
5700     {
5701         /* No Cartesian communicators */
5702         /* We use the rank in dd->comm->all as DD index */
5703         ddindex2xyz(dd->nc, dd->rank, dd->ci);
5704         /* The simulation master nodeid is 0, so the DD master rank is also 0 */
5705         dd->masterrank = 0;
5706         clear_ivec(dd->master_ci);
5707     }
5708 #endif
5709
5710     if (fplog)
5711     {
5712         fprintf(fplog,
5713                 "Domain decomposition rank %d, coordinates %d %d %d\n\n",
5714                 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
5715     }
5716     if (debug)
5717     {
5718         fprintf(debug,
5719                 "Domain decomposition rank %d, coordinates %d %d %d\n\n",
5720                 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
5721     }
5722 }
5723
5724 static void receive_ddindex2simnodeid(gmx_domdec_t         *dd,
5725                                       t_commrec            *cr)
5726 {
5727 #if GMX_MPI
5728     gmx_domdec_comm_t *comm = dd->comm;
5729
5730     if (!comm->bCartesianPP_PME && comm->bCartesianPP)
5731     {
5732         int *buf;
5733         snew(comm->ddindex2simnodeid, dd->nnodes);
5734         snew(buf, dd->nnodes);
5735         if (thisRankHasDuty(cr, DUTY_PP))
5736         {
5737             buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
5738         }
5739         /* Communicate the ddindex to simulation nodeid index */
5740         MPI_Allreduce(buf, comm->ddindex2simnodeid, dd->nnodes, MPI_INT, MPI_SUM,
5741                       cr->mpi_comm_mysim);
5742         sfree(buf);
5743     }
5744 #else
5745     GMX_UNUSED_VALUE(dd);
5746     GMX_UNUSED_VALUE(cr);
5747 #endif
5748 }
5749
5750 static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
5751                                                      int ncg, int natoms)
5752 {
5753     gmx_domdec_master_t *ma;
5754     int                  i;
5755
5756     snew(ma, 1);
5757
5758     snew(ma->ncg, dd->nnodes);
5759     snew(ma->index, dd->nnodes+1);
5760     snew(ma->cg, ncg);
5761     snew(ma->nat, dd->nnodes);
5762     snew(ma->ibuf, dd->nnodes*2);
5763     snew(ma->cell_x, DIM);
5764     for (i = 0; i < DIM; i++)
5765     {
5766         snew(ma->cell_x[i], dd->nc[i]+1);
5767     }
5768
5769     if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
5770     {
5771         ma->vbuf = nullptr;
5772     }
5773     else
5774     {
5775         snew(ma->vbuf, natoms);
5776     }
5777
5778     return ma;
5779 }
5780
5781 static void split_communicator(FILE *fplog, t_commrec *cr, gmx_domdec_t *dd,
5782                                DdRankOrder gmx_unused rankOrder,
5783                                int gmx_unused reorder)
5784 {
5785     gmx_domdec_comm_t *comm;
5786     int                i;
5787     gmx_bool           bDiv[DIM];
5788 #if GMX_MPI
5789     MPI_Comm           comm_cart;
5790 #endif
5791
5792     comm = dd->comm;
5793
5794     if (comm->bCartesianPP)
5795     {
5796         for (i = 1; i < DIM; i++)
5797         {
5798             bDiv[i] = ((cr->npmenodes*dd->nc[i]) % (dd->nnodes) == 0);
5799         }
5800         if (bDiv[YY] || bDiv[ZZ])
5801         {
5802             comm->bCartesianPP_PME = TRUE;
5803             /* If we have 2D PME decomposition, which is always in x+y,
5804              * we stack the PME only nodes in z.
5805              * Otherwise we choose the direction that provides the thinnest slab
5806              * of PME only nodes as this will have the least effect
5807              * on the PP communication.
5808              * But for the PME communication the opposite might be better.
5809              */
5810             if (bDiv[ZZ] && (comm->npmenodes_y > 1 ||
5811                              !bDiv[YY] ||
5812                              dd->nc[YY] > dd->nc[ZZ]))
5813             {
5814                 comm->cartpmedim = ZZ;
5815             }
5816             else
5817             {
5818                 comm->cartpmedim = YY;
5819             }
5820             comm->ntot[comm->cartpmedim]
5821                 += (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
5822         }
5823         else if (fplog)
5824         {
5825             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]);
5826             fprintf(fplog,
5827                     "Will not use a Cartesian communicator for PP <-> PME\n\n");
5828         }
5829     }
5830
5831     if (comm->bCartesianPP_PME)
5832     {
5833 #if GMX_MPI
5834         int  rank;
5835         ivec periods;
5836
5837         if (fplog)
5838         {
5839             fprintf(fplog, "Will use a Cartesian communicator for PP <-> PME: %d x %d x %d\n", comm->ntot[XX], comm->ntot[YY], comm->ntot[ZZ]);
5840         }
5841
5842         for (i = 0; i < DIM; i++)
5843         {
5844             periods[i] = TRUE;
5845         }
5846         MPI_Cart_create(cr->mpi_comm_mysim, DIM, comm->ntot, periods, reorder,
5847                         &comm_cart);
5848         MPI_Comm_rank(comm_cart, &rank);
5849         if (MASTER(cr) && rank != 0)
5850         {
5851             gmx_fatal(FARGS, "MPI rank 0 was renumbered by MPI_Cart_create, we do not allow this");
5852         }
5853
5854         /* With this assigment we loose the link to the original communicator
5855          * which will usually be MPI_COMM_WORLD, unless have multisim.
5856          */
5857         cr->mpi_comm_mysim = comm_cart;
5858         cr->sim_nodeid     = rank;
5859
5860         MPI_Cart_coords(cr->mpi_comm_mysim, cr->sim_nodeid, DIM, dd->ci);
5861
5862         if (fplog)
5863         {
5864             fprintf(fplog, "Cartesian rank %d, coordinates %d %d %d\n\n",
5865                     cr->sim_nodeid, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
5866         }
5867
5868         if (dd->ci[comm->cartpmedim] < dd->nc[comm->cartpmedim])
5869         {
5870             cr->duty = DUTY_PP;
5871         }
5872         if (cr->npmenodes == 0 ||
5873             dd->ci[comm->cartpmedim] >= dd->nc[comm->cartpmedim])
5874         {
5875             cr->duty = DUTY_PME;
5876         }
5877
5878         /* Split the sim communicator into PP and PME only nodes */
5879         MPI_Comm_split(cr->mpi_comm_mysim,
5880                        getThisRankDuties(cr),
5881                        dd_index(comm->ntot, dd->ci),
5882                        &cr->mpi_comm_mygroup);
5883 #endif
5884     }
5885     else
5886     {
5887         switch (rankOrder)
5888         {
5889             case DdRankOrder::pp_pme:
5890                 if (fplog)
5891                 {
5892                     fprintf(fplog, "Order of the ranks: PP first, PME last\n");
5893                 }
5894                 break;
5895             case DdRankOrder::interleave:
5896                 /* Interleave the PP-only and PME-only ranks */
5897                 if (fplog)
5898                 {
5899                     fprintf(fplog, "Interleaving PP and PME ranks\n");
5900                 }
5901                 comm->pmenodes = dd_interleaved_pme_ranks(dd);
5902                 break;
5903             case DdRankOrder::cartesian:
5904                 break;
5905             default:
5906                 gmx_fatal(FARGS, "Invalid ddRankOrder=%d", static_cast<int>(rankOrder));
5907         }
5908
5909         if (dd_simnode2pmenode(dd, cr, cr->sim_nodeid) == -1)
5910         {
5911             cr->duty = DUTY_PME;
5912         }
5913         else
5914         {
5915             cr->duty = DUTY_PP;
5916         }
5917 #if GMX_MPI
5918         /* Split the sim communicator into PP and PME only nodes */
5919         MPI_Comm_split(cr->mpi_comm_mysim,
5920                        getThisRankDuties(cr),
5921                        cr->nodeid,
5922                        &cr->mpi_comm_mygroup);
5923         MPI_Comm_rank(cr->mpi_comm_mygroup, &cr->nodeid);
5924 #endif
5925     }
5926
5927     if (fplog)
5928     {
5929         fprintf(fplog, "This rank does only %s work.\n\n",
5930                 thisRankHasDuty(cr, DUTY_PP) ? "particle-particle" : "PME-mesh");
5931     }
5932 }
5933
5934 /*! \brief Generates the MPI communicators for domain decomposition */
5935 static void make_dd_communicators(FILE *fplog, t_commrec *cr,
5936                                   gmx_domdec_t *dd, DdRankOrder ddRankOrder)
5937 {
5938     gmx_domdec_comm_t *comm;
5939     int                CartReorder;
5940
5941     comm = dd->comm;
5942
5943     copy_ivec(dd->nc, comm->ntot);
5944
5945     comm->bCartesianPP     = (ddRankOrder == DdRankOrder::cartesian);
5946     comm->bCartesianPP_PME = FALSE;
5947
5948     /* Reorder the nodes by default. This might change the MPI ranks.
5949      * Real reordering is only supported on very few architectures,
5950      * Blue Gene is one of them.
5951      */
5952     CartReorder = (getenv("GMX_NO_CART_REORDER") == nullptr);
5953
5954     if (cr->npmenodes > 0)
5955     {
5956         /* Split the communicator into a PP and PME part */
5957         split_communicator(fplog, cr, dd, ddRankOrder, CartReorder);
5958         if (comm->bCartesianPP_PME)
5959         {
5960             /* We (possibly) reordered the nodes in split_communicator,
5961              * so it is no longer required in make_pp_communicator.
5962              */
5963             CartReorder = FALSE;
5964         }
5965     }
5966     else
5967     {
5968         /* All nodes do PP and PME */
5969 #if GMX_MPI
5970         /* We do not require separate communicators */
5971         cr->mpi_comm_mygroup = cr->mpi_comm_mysim;
5972 #endif
5973     }
5974
5975     if (thisRankHasDuty(cr, DUTY_PP))
5976     {
5977         /* Copy or make a new PP communicator */
5978         make_pp_communicator(fplog, dd, cr, CartReorder);
5979     }
5980     else
5981     {
5982         receive_ddindex2simnodeid(dd, cr);
5983     }
5984
5985     if (!thisRankHasDuty(cr, DUTY_PME))
5986     {
5987         /* Set up the commnuication to our PME node */
5988         dd->pme_nodeid           = dd_simnode2pmenode(dd, cr, cr->sim_nodeid);
5989         dd->pme_receive_vir_ener = receive_vir_ener(dd, cr);
5990         if (debug)
5991         {
5992             fprintf(debug, "My pme_nodeid %d receive ener %d\n",
5993                     dd->pme_nodeid, dd->pme_receive_vir_ener);
5994         }
5995     }
5996     else
5997     {
5998         dd->pme_nodeid = -1;
5999     }
6000
6001     if (DDMASTER(dd))
6002     {
6003         dd->ma = init_gmx_domdec_master_t(dd,
6004                                           comm->cgs_gl.nr,
6005                                           comm->cgs_gl.index[comm->cgs_gl.nr]);
6006     }
6007 }
6008
6009 static real *get_slb_frac(FILE *fplog, const char *dir, int nc, const char *size_string)
6010 {
6011     real  *slb_frac, tot;
6012     int    i, n;
6013     double dbl;
6014
6015     slb_frac = nullptr;
6016     if (nc > 1 && size_string != nullptr)
6017     {
6018         if (fplog)
6019         {
6020             fprintf(fplog, "Using static load balancing for the %s direction\n",
6021                     dir);
6022         }
6023         snew(slb_frac, nc);
6024         tot = 0;
6025         for (i = 0; i < nc; i++)
6026         {
6027             dbl = 0;
6028             sscanf(size_string, "%20lf%n", &dbl, &n);
6029             if (dbl == 0)
6030             {
6031                 gmx_fatal(FARGS, "Incorrect or not enough DD cell size entries for direction %s: '%s'", dir, size_string);
6032             }
6033             slb_frac[i]  = dbl;
6034             size_string += n;
6035             tot         += slb_frac[i];
6036         }
6037         /* Normalize */
6038         if (fplog)
6039         {
6040             fprintf(fplog, "Relative cell sizes:");
6041         }
6042         for (i = 0; i < nc; i++)
6043         {
6044             slb_frac[i] /= tot;
6045             if (fplog)
6046             {
6047                 fprintf(fplog, " %5.3f", slb_frac[i]);
6048             }
6049         }
6050         if (fplog)
6051         {
6052             fprintf(fplog, "\n");
6053         }
6054     }
6055
6056     return slb_frac;
6057 }
6058
6059 static int multi_body_bondeds_count(const gmx_mtop_t *mtop)
6060 {
6061     int                  n, nmol, ftype;
6062     gmx_mtop_ilistloop_t iloop;
6063     t_ilist             *il;
6064
6065     n     = 0;
6066     iloop = gmx_mtop_ilistloop_init(mtop);
6067     while (gmx_mtop_ilistloop_next(iloop, &il, &nmol))
6068     {
6069         for (ftype = 0; ftype < F_NRE; ftype++)
6070         {
6071             if ((interaction_function[ftype].flags & IF_BOND) &&
6072                 NRAL(ftype) >  2)
6073             {
6074                 n += nmol*il[ftype].nr/(1 + NRAL(ftype));
6075             }
6076         }
6077     }
6078
6079     return n;
6080 }
6081
6082 static int dd_getenv(FILE *fplog, const char *env_var, int def)
6083 {
6084     char *val;
6085     int   nst;
6086
6087     nst = def;
6088     val = getenv(env_var);
6089     if (val)
6090     {
6091         if (sscanf(val, "%20d", &nst) <= 0)
6092         {
6093             nst = 1;
6094         }
6095         if (fplog)
6096         {
6097             fprintf(fplog, "Found env.var. %s = %s, using value %d\n",
6098                     env_var, val, nst);
6099         }
6100     }
6101
6102     return nst;
6103 }
6104
6105 static void dd_warning(t_commrec *cr, FILE *fplog, const char *warn_string)
6106 {
6107     if (MASTER(cr))
6108     {
6109         fprintf(stderr, "\n%s\n", warn_string);
6110     }
6111     if (fplog)
6112     {
6113         fprintf(fplog, "\n%s\n", warn_string);
6114     }
6115 }
6116
6117 static void check_dd_restrictions(t_commrec *cr, const gmx_domdec_t *dd,
6118                                   const t_inputrec *ir, FILE *fplog)
6119 {
6120     if (ir->ePBC == epbcSCREW &&
6121         (dd->nc[XX] == 1 || dd->nc[YY] > 1 || dd->nc[ZZ] > 1))
6122     {
6123         gmx_fatal(FARGS, "With pbc=%s can only do domain decomposition in the x-direction", epbc_names[ir->ePBC]);
6124     }
6125
6126     if (ir->ns_type == ensSIMPLE)
6127     {
6128         gmx_fatal(FARGS, "Domain decomposition does not support simple neighbor searching, use grid searching or run with one MPI rank");
6129     }
6130
6131     if (ir->nstlist == 0)
6132     {
6133         gmx_fatal(FARGS, "Domain decomposition does not work with nstlist=0");
6134     }
6135
6136     if (ir->comm_mode == ecmANGULAR && ir->ePBC != epbcNONE)
6137     {
6138         dd_warning(cr, fplog, "comm-mode angular will give incorrect results when the comm group partially crosses a periodic boundary");
6139     }
6140 }
6141
6142 static real average_cellsize_min(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
6143 {
6144     int  di, d;
6145     real r;
6146
6147     r = ddbox->box_size[XX];
6148     for (di = 0; di < dd->ndim; di++)
6149     {
6150         d = dd->dim[di];
6151         /* Check using the initial average cell size */
6152         r = std::min(r, ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
6153     }
6154
6155     return r;
6156 }
6157
6158 /*! \brief Depending on the DLB initial value return the DLB switched off state or issue an error.
6159  */
6160 static int forceDlbOffOrBail(int                cmdlineDlbState,
6161                              const std::string &reasonStr,
6162                              t_commrec         *cr,
6163                              FILE              *fplog)
6164 {
6165     std::string dlbNotSupportedErr  = "Dynamic load balancing requested, but ";
6166     std::string dlbDisableNote      = "NOTE: disabling dynamic load balancing as ";
6167
6168     if (cmdlineDlbState == edlbsOnUser)
6169     {
6170         gmx_fatal(FARGS, (dlbNotSupportedErr + reasonStr).c_str());
6171     }
6172     else if (cmdlineDlbState == edlbsOffCanTurnOn)
6173     {
6174         dd_warning(cr, fplog, (dlbDisableNote + reasonStr + "\n").c_str());
6175     }
6176     return edlbsOffForever;
6177 }
6178
6179 /*! \brief Return the dynamic load balancer's initial state based on initial conditions and user inputs.
6180  *
6181  * This function parses the parameters of "-dlb" command line option setting
6182  * corresponding state values. Then it checks the consistency of the determined
6183  * state with other run parameters and settings. As a result, the initial state
6184  * may be altered or an error may be thrown if incompatibility of options is detected.
6185  *
6186  * \param [in] fplog       Pointer to mdrun log file.
6187  * \param [in] cr          Pointer to MPI communication object.
6188  * \param [in] dlbOption   Enum value for the DLB option.
6189  * \param [in] bRecordLoad True if the load balancer is recording load information.
6190  * \param [in] mdrunOptions  Options for mdrun.
6191  * \param [in] ir          Pointer mdrun to input parameters.
6192  * \returns                DLB initial/startup state.
6193  */
6194 static int determineInitialDlbState(FILE *fplog, t_commrec *cr,
6195                                     DlbOption dlbOption, gmx_bool bRecordLoad,
6196                                     const MdrunOptions &mdrunOptions,
6197                                     const t_inputrec *ir)
6198 {
6199     int dlbState = edlbsOffCanTurnOn;
6200
6201     switch (dlbOption)
6202     {
6203         case DlbOption::turnOnWhenUseful: dlbState = edlbsOffCanTurnOn; break;
6204         case DlbOption::no:               dlbState = edlbsOffUser;      break;
6205         case DlbOption::yes:              dlbState = edlbsOnUser;       break;
6206         default: gmx_incons("Invalid dlbOption enum value");
6207     }
6208
6209     /* Reruns don't support DLB: bail or override auto mode */
6210     if (mdrunOptions.rerun)
6211     {
6212         std::string reasonStr = "it is not supported in reruns.";
6213         return forceDlbOffOrBail(dlbState, reasonStr, cr, fplog);
6214     }
6215
6216     /* Unsupported integrators */
6217     if (!EI_DYNAMICS(ir->eI))
6218     {
6219         auto reasonStr = gmx::formatString("it is only supported with dynamics, not with integrator '%s'.", EI(ir->eI));
6220         return forceDlbOffOrBail(dlbState, reasonStr, cr, fplog);
6221     }
6222
6223     /* Without cycle counters we can't time work to balance on */
6224     if (!bRecordLoad)
6225     {
6226         std::string reasonStr = "cycle counters unsupported or not enabled in the operating system kernel.";
6227         return forceDlbOffOrBail(dlbState, reasonStr, cr, fplog);
6228     }
6229
6230     if (mdrunOptions.reproducible)
6231     {
6232         std::string reasonStr = "you started a reproducible run.";
6233         switch (dlbState)
6234         {
6235             case edlbsOffUser:
6236                 break;
6237             case edlbsOffForever:
6238                 GMX_RELEASE_ASSERT(false, "edlbsOffForever is not a valid initial state");
6239                 break;
6240             case edlbsOffCanTurnOn:
6241                 return forceDlbOffOrBail(dlbState, reasonStr, cr, fplog);
6242                 break;
6243             case edlbsOnCanTurnOff:
6244                 GMX_RELEASE_ASSERT(false, "edlbsOffCanTurnOff is not a valid initial state");
6245                 break;
6246             case edlbsOnUser:
6247                 return forceDlbOffOrBail(dlbState, reasonStr + " In load balanced runs binary reproducibility cannot be ensured.", cr, fplog);
6248                 break;
6249             default:
6250                 gmx_fatal(FARGS, "Death horror: undefined case (%d) for load balancing choice", dlbState);
6251                 break;
6252         }
6253     }
6254
6255     return dlbState;
6256 }
6257
6258 static void set_dd_dim(FILE *fplog, gmx_domdec_t *dd)
6259 {
6260     int dim;
6261
6262     dd->ndim = 0;
6263     if (getenv("GMX_DD_ORDER_ZYX") != nullptr)
6264     {
6265         /* Decomposition order z,y,x */
6266         if (fplog)
6267         {
6268             fprintf(fplog, "Using domain decomposition order z, y, x\n");
6269         }
6270         for (dim = DIM-1; dim >= 0; dim--)
6271         {
6272             if (dd->nc[dim] > 1)
6273             {
6274                 dd->dim[dd->ndim++] = dim;
6275             }
6276         }
6277     }
6278     else
6279     {
6280         /* Decomposition order x,y,z */
6281         for (dim = 0; dim < DIM; dim++)
6282         {
6283             if (dd->nc[dim] > 1)
6284             {
6285                 dd->dim[dd->ndim++] = dim;
6286             }
6287         }
6288     }
6289 }
6290
6291 static gmx_domdec_comm_t *init_dd_comm()
6292 {
6293     gmx_domdec_comm_t *comm;
6294     int                i;
6295
6296     snew(comm, 1);
6297     snew(comm->cggl_flag, DIM*2);
6298     snew(comm->cgcm_state, DIM*2);
6299     for (i = 0; i < DIM*2; i++)
6300     {
6301         comm->cggl_flag_nalloc[i]  = 0;
6302         comm->cgcm_state_nalloc[i] = 0;
6303     }
6304
6305     comm->nalloc_int = 0;
6306     comm->buf_int    = nullptr;
6307
6308     vec_rvec_init(&comm->vbuf);
6309
6310     comm->n_load_have    = 0;
6311     comm->n_load_collect = 0;
6312
6313     for (i = 0; i < ddnatNR-ddnatZONE; i++)
6314     {
6315         comm->sum_nat[i] = 0;
6316     }
6317     comm->ndecomp   = 0;
6318     comm->nload     = 0;
6319     comm->load_step = 0;
6320     comm->load_sum  = 0;
6321     comm->load_max  = 0;
6322     clear_ivec(comm->load_lim);
6323     comm->load_mdf  = 0;
6324     comm->load_pme  = 0;
6325
6326     /* This should be replaced by a unique pointer */
6327     comm->balanceRegion = ddBalanceRegionAllocate();
6328
6329     return comm;
6330 }
6331
6332 /*! \brief Set the cell size and interaction limits, as well as the DD grid */
6333 static void set_dd_limits_and_grid(FILE *fplog, t_commrec *cr, gmx_domdec_t *dd,
6334                                    const DomdecOptions &options,
6335                                    const MdrunOptions &mdrunOptions,
6336                                    const gmx_mtop_t *mtop,
6337                                    const t_inputrec *ir,
6338                                    const matrix box, const rvec *xGlobal,
6339                                    gmx_ddbox_t *ddbox,
6340                                    int *npme_x, int *npme_y)
6341 {
6342     real               r_bonded         = -1;
6343     real               r_bonded_limit   = -1;
6344     const real         tenPercentMargin = 1.1;
6345     gmx_domdec_comm_t *comm             = dd->comm;
6346
6347     snew(comm->cggl_flag, DIM*2);
6348     snew(comm->cgcm_state, DIM*2);
6349
6350     dd->npbcdim   = ePBC2npbcdim(ir->ePBC);
6351     dd->bScrewPBC = (ir->ePBC == epbcSCREW);
6352
6353     dd->pme_recv_f_alloc = 0;
6354     dd->pme_recv_f_buf   = nullptr;
6355
6356     /* Initialize to GPU share count to 0, might change later */
6357     comm->nrank_gpu_shared = 0;
6358
6359     comm->dlbState         = determineInitialDlbState(fplog, cr, options.dlbOption, comm->bRecordLoad, mdrunOptions, ir);
6360     dd_dlb_set_should_check_whether_to_turn_dlb_on(dd, TRUE);
6361     /* To consider turning DLB on after 2*nstlist steps we need to check
6362      * at partitioning count 3. Thus we need to increase the first count by 2.
6363      */
6364     comm->ddPartioningCountFirstDlbOff += 2;
6365
6366     if (fplog)
6367     {
6368         fprintf(fplog, "Dynamic load balancing: %s\n",
6369                 edlbs_names[comm->dlbState]);
6370     }
6371     comm->bPMELoadBalDLBLimits = FALSE;
6372
6373     /* Allocate the charge group/atom sorting struct */
6374     snew(comm->sort, 1);
6375
6376     comm->bCGs = (ncg_mtop(mtop) < mtop->natoms);
6377
6378     comm->bInterCGBondeds = ((ncg_mtop(mtop) > mtop->mols.nr) ||
6379                              mtop->bIntermolecularInteractions);
6380     if (comm->bInterCGBondeds)
6381     {
6382         comm->bInterCGMultiBody = (multi_body_bondeds_count(mtop) > 0);
6383     }
6384     else
6385     {
6386         comm->bInterCGMultiBody = FALSE;
6387     }
6388
6389     dd->bInterCGcons    = inter_charge_group_constraints(mtop);
6390     dd->bInterCGsettles = inter_charge_group_settles(mtop);
6391
6392     if (ir->rlist == 0)
6393     {
6394         /* Set the cut-off to some very large value,
6395          * so we don't need if statements everywhere in the code.
6396          * We use sqrt, since the cut-off is squared in some places.
6397          */
6398         comm->cutoff   = GMX_CUTOFF_INF;
6399     }
6400     else
6401     {
6402         comm->cutoff   = ir->rlist;
6403     }
6404     comm->cutoff_mbody = 0;
6405
6406     /* Determine the minimum cell size limit, affected by many factors */
6407     comm->cellsize_limit = 0;
6408     comm->bBondComm      = FALSE;
6409
6410     /* We do not allow home atoms to move beyond the neighboring domain
6411      * between domain decomposition steps, which limits the cell size.
6412      * Get an estimate of cell size limit due to atom displacement.
6413      * In most cases this is a large overestimate, because it assumes
6414      * non-interaction atoms.
6415      * We set the chance to 1 in a trillion steps.
6416      */
6417     constexpr real c_chanceThatAtomMovesBeyondDomain = 1e-12;
6418     const real     limitForAtomDisplacement          =
6419         minCellSizeForAtomDisplacement(*mtop, *ir, c_chanceThatAtomMovesBeyondDomain);
6420     if (fplog)
6421     {
6422         fprintf(fplog,
6423                 "Minimum cell size due to atom displacement: %.3f nm\n",
6424                 limitForAtomDisplacement);
6425     }
6426     comm->cellsize_limit = std::max(comm->cellsize_limit,
6427                                     limitForAtomDisplacement);
6428
6429     /* TODO: PME decomposition currently requires atoms not to be more than
6430      *       2/3 of comm->cutoff, which is >=rlist, outside of their domain.
6431      *       In nearly all cases, limitForAtomDisplacement will be smaller
6432      *       than 2/3*rlist, so the PME requirement is satisfied.
6433      *       But it would be better for both correctness and performance
6434      *       to use limitForAtomDisplacement instead of 2/3*comm->cutoff.
6435      *       Note that we would need to improve the pairlist buffer case.
6436      */
6437
6438     if (comm->bInterCGBondeds)
6439     {
6440         if (options.minimumCommunicationRange > 0)
6441         {
6442             comm->cutoff_mbody = options.minimumCommunicationRange;
6443             if (options.useBondedCommunication)
6444             {
6445                 comm->bBondComm = (comm->cutoff_mbody > comm->cutoff);
6446             }
6447             else
6448             {
6449                 comm->cutoff = std::max(comm->cutoff, comm->cutoff_mbody);
6450             }
6451             r_bonded_limit = comm->cutoff_mbody;
6452         }
6453         else if (ir->bPeriodicMols)
6454         {
6455             /* Can not easily determine the required cut-off */
6456             dd_warning(cr, fplog, "NOTE: Periodic molecules are present in this system. Because of this, the domain decomposition algorithm cannot easily determine the minimum cell size that it requires for treating bonded interactions. Instead, domain decomposition will assume that half the non-bonded cut-off will be a suitable lower bound.\n");
6457             comm->cutoff_mbody = comm->cutoff/2;
6458             r_bonded_limit     = comm->cutoff_mbody;
6459         }
6460         else
6461         {
6462             real r_2b, r_mb;
6463
6464             if (MASTER(cr))
6465             {
6466                 dd_bonded_cg_distance(fplog, mtop, ir, xGlobal, box,
6467                                       options.checkBondedInteractions,
6468                                       &r_2b, &r_mb);
6469             }
6470             gmx_bcast(sizeof(r_2b), &r_2b, cr);
6471             gmx_bcast(sizeof(r_mb), &r_mb, cr);
6472
6473             /* We use an initial margin of 10% for the minimum cell size,
6474              * except when we are just below the non-bonded cut-off.
6475              */
6476             if (options.useBondedCommunication)
6477             {
6478                 if (std::max(r_2b, r_mb) > comm->cutoff)
6479                 {
6480                     r_bonded        = std::max(r_2b, r_mb);
6481                     r_bonded_limit  = tenPercentMargin*r_bonded;
6482                     comm->bBondComm = TRUE;
6483                 }
6484                 else
6485                 {
6486                     r_bonded       = r_mb;
6487                     r_bonded_limit = std::min(tenPercentMargin*r_bonded, comm->cutoff);
6488                 }
6489                 /* We determine cutoff_mbody later */
6490             }
6491             else
6492             {
6493                 /* No special bonded communication,
6494                  * simply increase the DD cut-off.
6495                  */
6496                 r_bonded_limit     = tenPercentMargin*std::max(r_2b, r_mb);
6497                 comm->cutoff_mbody = r_bonded_limit;
6498                 comm->cutoff       = std::max(comm->cutoff, comm->cutoff_mbody);
6499             }
6500         }
6501         if (fplog)
6502         {
6503             fprintf(fplog,
6504                     "Minimum cell size due to bonded interactions: %.3f nm\n",
6505                     r_bonded_limit);
6506         }
6507         comm->cellsize_limit = std::max(comm->cellsize_limit, r_bonded_limit);
6508     }
6509
6510     real rconstr = 0;
6511     if (dd->bInterCGcons && options.constraintCommunicationRange <= 0)
6512     {
6513         /* There is a cell size limit due to the constraints (P-LINCS) */
6514         rconstr = constr_r_max(fplog, mtop, ir);
6515         if (fplog)
6516         {
6517             fprintf(fplog,
6518                     "Estimated maximum distance required for P-LINCS: %.3f nm\n",
6519                     rconstr);
6520             if (rconstr > comm->cellsize_limit)
6521             {
6522                 fprintf(fplog, "This distance will limit the DD cell size, you can override this with -rcon\n");
6523             }
6524         }
6525     }
6526     else if (options.constraintCommunicationRange > 0 && fplog)
6527     {
6528         /* Here we do not check for dd->bInterCGcons,
6529          * because one can also set a cell size limit for virtual sites only
6530          * and at this point we don't know yet if there are intercg v-sites.
6531          */
6532         fprintf(fplog,
6533                 "User supplied maximum distance required for P-LINCS: %.3f nm\n",
6534                 options.constraintCommunicationRange);
6535         rconstr = options.constraintCommunicationRange;
6536     }
6537     comm->cellsize_limit = std::max(comm->cellsize_limit, rconstr);
6538
6539     comm->cgs_gl = gmx_mtop_global_cgs(mtop);
6540
6541     if (options.numCells[XX] > 0)
6542     {
6543         copy_ivec(options.numCells, dd->nc);
6544         set_dd_dim(fplog, dd);
6545         set_ddbox_cr(cr, &dd->nc, ir, box, &comm->cgs_gl, xGlobal, ddbox);
6546
6547         if (options.numPmeRanks >= 0)
6548         {
6549             cr->npmenodes = options.numPmeRanks;
6550         }
6551         else
6552         {
6553             /* When the DD grid is set explicitly and -npme is set to auto,
6554              * don't use PME ranks. We check later if the DD grid is
6555              * compatible with the total number of ranks.
6556              */
6557             cr->npmenodes = 0;
6558         }
6559
6560         real acs = average_cellsize_min(dd, ddbox);
6561         if (acs < comm->cellsize_limit)
6562         {
6563             if (fplog)
6564             {
6565                 fprintf(fplog, "ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n", acs, comm->cellsize_limit);
6566             }
6567             gmx_fatal_collective(FARGS, cr->mpi_comm_mysim, MASTER(cr),
6568                                  "The initial cell size (%f) is smaller than the cell size limit (%f), change options -dd, -rdd or -rcon, see the log file for details",
6569                                  acs, comm->cellsize_limit);
6570         }
6571     }
6572     else
6573     {
6574         set_ddbox_cr(cr, nullptr, ir, box, &comm->cgs_gl, xGlobal, ddbox);
6575
6576         /* We need to choose the optimal DD grid and possibly PME nodes */
6577         real limit =
6578             dd_choose_grid(fplog, cr, dd, ir, mtop, box, ddbox,
6579                            options.numPmeRanks,
6580                            !isDlbDisabled(comm),
6581                            options.dlbScaling,
6582                            comm->cellsize_limit, comm->cutoff,
6583                            comm->bInterCGBondeds);
6584
6585         if (dd->nc[XX] == 0)
6586         {
6587             char     buf[STRLEN];
6588             gmx_bool bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
6589             sprintf(buf, "Change the number of ranks or mdrun option %s%s%s",
6590                     !bC ? "-rdd" : "-rcon",
6591                     comm->dlbState != edlbsOffUser ? " or -dds" : "",
6592                     bC ? " or your LINCS settings" : "");
6593
6594             gmx_fatal_collective(FARGS, cr->mpi_comm_mysim, MASTER(cr),
6595                                  "There is no domain decomposition for %d ranks that is compatible with the given box and a minimum cell size of %g nm\n"
6596                                  "%s\n"
6597                                  "Look in the log file for details on the domain decomposition",
6598                                  cr->nnodes-cr->npmenodes, limit, buf);
6599         }
6600         set_dd_dim(fplog, dd);
6601     }
6602
6603     if (fplog)
6604     {
6605         fprintf(fplog,
6606                 "Domain decomposition grid %d x %d x %d, separate PME ranks %d\n",
6607                 dd->nc[XX], dd->nc[YY], dd->nc[ZZ], cr->npmenodes);
6608     }
6609
6610     dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
6611     if (cr->nnodes - dd->nnodes != cr->npmenodes)
6612     {
6613         gmx_fatal_collective(FARGS, cr->mpi_comm_mysim, MASTER(cr),
6614                              "The size of the domain decomposition grid (%d) does not match the number of ranks (%d). The total number of ranks is %d",
6615                              dd->nnodes, cr->nnodes - cr->npmenodes, cr->nnodes);
6616     }
6617     if (cr->npmenodes > dd->nnodes)
6618     {
6619         gmx_fatal_collective(FARGS, cr->mpi_comm_mysim, MASTER(cr),
6620                              "The number of separate PME ranks (%d) is larger than the number of PP ranks (%d), this is not supported.", cr->npmenodes, dd->nnodes);
6621     }
6622     if (cr->npmenodes > 0)
6623     {
6624         comm->npmenodes = cr->npmenodes;
6625     }
6626     else
6627     {
6628         comm->npmenodes = dd->nnodes;
6629     }
6630
6631     if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
6632     {
6633         /* The following choices should match those
6634          * in comm_cost_est in domdec_setup.c.
6635          * Note that here the checks have to take into account
6636          * that the decomposition might occur in a different order than xyz
6637          * (for instance through the env.var. GMX_DD_ORDER_ZYX),
6638          * in which case they will not match those in comm_cost_est,
6639          * but since that is mainly for testing purposes that's fine.
6640          */
6641         if (dd->ndim >= 2 && dd->dim[0] == XX && dd->dim[1] == YY &&
6642             comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
6643             getenv("GMX_PMEONEDD") == nullptr)
6644         {
6645             comm->npmedecompdim = 2;
6646             comm->npmenodes_x   = dd->nc[XX];
6647             comm->npmenodes_y   = comm->npmenodes/comm->npmenodes_x;
6648         }
6649         else
6650         {
6651             /* In case nc is 1 in both x and y we could still choose to
6652              * decompose pme in y instead of x, but we use x for simplicity.
6653              */
6654             comm->npmedecompdim = 1;
6655             if (dd->dim[0] == YY)
6656             {
6657                 comm->npmenodes_x = 1;
6658                 comm->npmenodes_y = comm->npmenodes;
6659             }
6660             else
6661             {
6662                 comm->npmenodes_x = comm->npmenodes;
6663                 comm->npmenodes_y = 1;
6664             }
6665         }
6666         if (fplog)
6667         {
6668             fprintf(fplog, "PME domain decomposition: %d x %d x %d\n",
6669                     comm->npmenodes_x, comm->npmenodes_y, 1);
6670         }
6671     }
6672     else
6673     {
6674         comm->npmedecompdim = 0;
6675         comm->npmenodes_x   = 0;
6676         comm->npmenodes_y   = 0;
6677     }
6678
6679     /* Technically we don't need both of these,
6680      * but it simplifies code not having to recalculate it.
6681      */
6682     *npme_x = comm->npmenodes_x;
6683     *npme_y = comm->npmenodes_y;
6684
6685     snew(comm->slb_frac, DIM);
6686     if (isDlbDisabled(comm))
6687     {
6688         comm->slb_frac[XX] = get_slb_frac(fplog, "x", dd->nc[XX], options.cellSizeX);
6689         comm->slb_frac[YY] = get_slb_frac(fplog, "y", dd->nc[YY], options.cellSizeY);
6690         comm->slb_frac[ZZ] = get_slb_frac(fplog, "z", dd->nc[ZZ], options.cellSizeZ);
6691     }
6692
6693     if (comm->bInterCGBondeds && comm->cutoff_mbody == 0)
6694     {
6695         if (comm->bBondComm || !isDlbDisabled(comm))
6696         {
6697             /* Set the bonded communication distance to halfway
6698              * the minimum and the maximum,
6699              * since the extra communication cost is nearly zero.
6700              */
6701             real acs           = average_cellsize_min(dd, ddbox);
6702             comm->cutoff_mbody = 0.5*(r_bonded + acs);
6703             if (!isDlbDisabled(comm))
6704             {
6705                 /* Check if this does not limit the scaling */
6706                 comm->cutoff_mbody = std::min(comm->cutoff_mbody,
6707                                               options.dlbScaling*acs);
6708             }
6709             if (!comm->bBondComm)
6710             {
6711                 /* Without bBondComm do not go beyond the n.b. cut-off */
6712                 comm->cutoff_mbody = std::min(comm->cutoff_mbody, comm->cutoff);
6713                 if (comm->cellsize_limit >= comm->cutoff)
6714                 {
6715                     /* We don't loose a lot of efficieny
6716                      * when increasing it to the n.b. cut-off.
6717                      * It can even be slightly faster, because we need
6718                      * less checks for the communication setup.
6719                      */
6720                     comm->cutoff_mbody = comm->cutoff;
6721                 }
6722             }
6723             /* Check if we did not end up below our original limit */
6724             comm->cutoff_mbody = std::max(comm->cutoff_mbody, r_bonded_limit);
6725
6726             if (comm->cutoff_mbody > comm->cellsize_limit)
6727             {
6728                 comm->cellsize_limit = comm->cutoff_mbody;
6729             }
6730         }
6731         /* Without DLB and cutoff_mbody<cutoff, cutoff_mbody is dynamic */
6732     }
6733
6734     if (debug)
6735     {
6736         fprintf(debug, "Bonded atom communication beyond the cut-off: %d\n"
6737                 "cellsize limit %f\n",
6738                 comm->bBondComm, comm->cellsize_limit);
6739     }
6740
6741     if (MASTER(cr))
6742     {
6743         check_dd_restrictions(cr, dd, ir, fplog);
6744     }
6745 }
6746
6747 static void set_dlb_limits(gmx_domdec_t *dd)
6748
6749 {
6750     int d;
6751
6752     for (d = 0; d < dd->ndim; d++)
6753     {
6754         dd->comm->cd[d].np                 = dd->comm->cd[d].np_dlb;
6755         dd->comm->cellsize_min[dd->dim[d]] =
6756             dd->comm->cellsize_min_dlb[dd->dim[d]];
6757     }
6758 }
6759
6760
6761 static void turn_on_dlb(FILE *fplog, t_commrec *cr, gmx_int64_t step)
6762 {
6763     gmx_domdec_t      *dd;
6764     gmx_domdec_comm_t *comm;
6765     real               cellsize_min;
6766     int                d, nc, i;
6767
6768     dd   = cr->dd;
6769     comm = dd->comm;
6770
6771     cellsize_min = comm->cellsize_min[dd->dim[0]];
6772     for (d = 1; d < dd->ndim; d++)
6773     {
6774         cellsize_min = std::min(cellsize_min, comm->cellsize_min[dd->dim[d]]);
6775     }
6776
6777     /* Turn off DLB if we're too close to the cell size limit. */
6778     if (cellsize_min < comm->cellsize_limit*1.05)
6779     {
6780         auto str = gmx::formatString("step %" GMX_PRId64 " Measured %.1f %% performance loss due to load imbalance, "
6781                                      "but the minimum cell size is smaller than 1.05 times the cell size limit."
6782                                      "Will no longer try dynamic load balancing.\n", step, dd_force_imb_perf_loss(dd)*100);
6783         dd_warning(cr, fplog, str.c_str());
6784
6785         comm->dlbState = edlbsOffForever;
6786         return;
6787     }
6788
6789     char buf[STRLEN];
6790     sprintf(buf, "step %" GMX_PRId64 " Turning on dynamic load balancing, because the performance loss due to load imbalance is %.1f %%.\n", step, dd_force_imb_perf_loss(dd)*100);
6791     dd_warning(cr, fplog, buf);
6792     comm->dlbState = edlbsOnCanTurnOff;
6793
6794     /* Store the non-DLB performance, so we can check if DLB actually
6795      * improves performance.
6796      */
6797     GMX_RELEASE_ASSERT(comm->cycl_n[ddCyclStep] > 0, "When we turned on DLB, we should have measured cycles");
6798     comm->cyclesPerStepBeforeDLB = comm->cycl[ddCyclStep]/comm->cycl_n[ddCyclStep];
6799
6800     set_dlb_limits(dd);
6801
6802     /* We can set the required cell size info here,
6803      * so we do not need to communicate this.
6804      * The grid is completely uniform.
6805      */
6806     for (d = 0; d < dd->ndim; d++)
6807     {
6808         if (comm->root[d])
6809         {
6810             comm->load[d].sum_m = comm->load[d].sum;
6811
6812             nc = dd->nc[dd->dim[d]];
6813             for (i = 0; i < nc; i++)
6814             {
6815                 comm->root[d]->cell_f[i]    = i/(real)nc;
6816                 if (d > 0)
6817                 {
6818                     comm->root[d]->cell_f_max0[i] =  i   /(real)nc;
6819                     comm->root[d]->cell_f_min1[i] = (i+1)/(real)nc;
6820                 }
6821             }
6822             comm->root[d]->cell_f[nc] = 1.0;
6823         }
6824     }
6825 }
6826
6827 static void turn_off_dlb(FILE *fplog, t_commrec *cr, gmx_int64_t step)
6828 {
6829     gmx_domdec_t *dd = cr->dd;
6830
6831     char          buf[STRLEN];
6832     sprintf(buf, "step %" GMX_PRId64 " Turning off dynamic load balancing, because it is degrading performance.\n", step);
6833     dd_warning(cr, fplog, buf);
6834     dd->comm->dlbState                     = edlbsOffCanTurnOn;
6835     dd->comm->haveTurnedOffDlb             = true;
6836     dd->comm->ddPartioningCountFirstDlbOff = dd->ddp_count;
6837 }
6838
6839 static void turn_off_dlb_forever(FILE *fplog, t_commrec *cr, gmx_int64_t step)
6840 {
6841     GMX_RELEASE_ASSERT(cr->dd->comm->dlbState == edlbsOffCanTurnOn, "Can only turn off DLB forever when it was in the can-turn-on state");
6842     char buf[STRLEN];
6843     sprintf(buf, "step %" GMX_PRId64 " Will no longer try dynamic load balancing, as it degraded performance.\n", step);
6844     dd_warning(cr, fplog, buf);
6845     cr->dd->comm->dlbState = edlbsOffForever;
6846 }
6847
6848 static char *init_bLocalCG(const gmx_mtop_t *mtop)
6849 {
6850     int   ncg, cg;
6851     char *bLocalCG;
6852
6853     ncg = ncg_mtop(mtop);
6854     snew(bLocalCG, ncg);
6855     for (cg = 0; cg < ncg; cg++)
6856     {
6857         bLocalCG[cg] = FALSE;
6858     }
6859
6860     return bLocalCG;
6861 }
6862
6863 void dd_init_bondeds(FILE *fplog,
6864                      gmx_domdec_t *dd,
6865                      const gmx_mtop_t *mtop,
6866                      const gmx_vsite_t *vsite,
6867                      const t_inputrec *ir,
6868                      gmx_bool bBCheck, cginfo_mb_t *cginfo_mb)
6869 {
6870     gmx_domdec_comm_t *comm;
6871
6872     dd_make_reverse_top(fplog, dd, mtop, vsite, ir, bBCheck);
6873
6874     comm = dd->comm;
6875
6876     if (comm->bBondComm)
6877     {
6878         /* Communicate atoms beyond the cut-off for bonded interactions */
6879         comm = dd->comm;
6880
6881         comm->cglink = make_charge_group_links(mtop, dd, cginfo_mb);
6882
6883         comm->bLocalCG = init_bLocalCG(mtop);
6884     }
6885     else
6886     {
6887         /* Only communicate atoms based on cut-off */
6888         comm->cglink   = nullptr;
6889         comm->bLocalCG = nullptr;
6890     }
6891 }
6892
6893 static void print_dd_settings(FILE *fplog, gmx_domdec_t *dd,
6894                               const gmx_mtop_t *mtop, const t_inputrec *ir,
6895                               gmx_bool bDynLoadBal, real dlb_scale,
6896                               const gmx_ddbox_t *ddbox)
6897 {
6898     gmx_domdec_comm_t *comm;
6899     int                d;
6900     ivec               np;
6901     real               limit, shrink;
6902     char               buf[64];
6903
6904     if (fplog == nullptr)
6905     {
6906         return;
6907     }
6908
6909     comm = dd->comm;
6910
6911     if (bDynLoadBal)
6912     {
6913         fprintf(fplog, "The maximum number of communication pulses is:");
6914         for (d = 0; d < dd->ndim; d++)
6915         {
6916             fprintf(fplog, " %c %d", dim2char(dd->dim[d]), comm->cd[d].np_dlb);
6917         }
6918         fprintf(fplog, "\n");
6919         fprintf(fplog, "The minimum size for domain decomposition cells is %.3f nm\n", comm->cellsize_limit);
6920         fprintf(fplog, "The requested allowed shrink of DD cells (option -dds) is: %.2f\n", dlb_scale);
6921         fprintf(fplog, "The allowed shrink of domain decomposition cells is:");
6922         for (d = 0; d < DIM; d++)
6923         {
6924             if (dd->nc[d] > 1)
6925             {
6926                 if (d >= ddbox->npbcdim && dd->nc[d] == 2)
6927                 {
6928                     shrink = 0;
6929                 }
6930                 else
6931                 {
6932                     shrink =
6933                         comm->cellsize_min_dlb[d]/
6934                         (ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
6935                 }
6936                 fprintf(fplog, " %c %.2f", dim2char(d), shrink);
6937             }
6938         }
6939         fprintf(fplog, "\n");
6940     }
6941     else
6942     {
6943         set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbPULSE_ONLY, np);
6944         fprintf(fplog, "The initial number of communication pulses is:");
6945         for (d = 0; d < dd->ndim; d++)
6946         {
6947             fprintf(fplog, " %c %d", dim2char(dd->dim[d]), np[dd->dim[d]]);
6948         }
6949         fprintf(fplog, "\n");
6950         fprintf(fplog, "The initial domain decomposition cell size is:");
6951         for (d = 0; d < DIM; d++)
6952         {
6953             if (dd->nc[d] > 1)
6954             {
6955                 fprintf(fplog, " %c %.2f nm",
6956                         dim2char(d), dd->comm->cellsize_min[d]);
6957             }
6958         }
6959         fprintf(fplog, "\n\n");
6960     }
6961
6962     gmx_bool bInterCGVsites = count_intercg_vsites(mtop);
6963
6964     if (comm->bInterCGBondeds ||
6965         bInterCGVsites ||
6966         dd->bInterCGcons || dd->bInterCGsettles)
6967     {
6968         fprintf(fplog, "The maximum allowed distance for charge groups involved in interactions is:\n");
6969         fprintf(fplog, "%40s  %-7s %6.3f nm\n",
6970                 "non-bonded interactions", "", comm->cutoff);
6971
6972         if (bDynLoadBal)
6973         {
6974             limit = dd->comm->cellsize_limit;
6975         }
6976         else
6977         {
6978             if (dynamic_dd_box(ddbox, ir))
6979             {
6980                 fprintf(fplog, "(the following are initial values, they could change due to box deformation)\n");
6981             }
6982             limit = dd->comm->cellsize_min[XX];
6983             for (d = 1; d < DIM; d++)
6984             {
6985                 limit = std::min(limit, dd->comm->cellsize_min[d]);
6986             }
6987         }
6988
6989         if (comm->bInterCGBondeds)
6990         {
6991             fprintf(fplog, "%40s  %-7s %6.3f nm\n",
6992                     "two-body bonded interactions", "(-rdd)",
6993                     std::max(comm->cutoff, comm->cutoff_mbody));
6994             fprintf(fplog, "%40s  %-7s %6.3f nm\n",
6995                     "multi-body bonded interactions", "(-rdd)",
6996                     (comm->bBondComm || isDlbOn(dd->comm)) ? comm->cutoff_mbody : std::min(comm->cutoff, limit));
6997         }
6998         if (bInterCGVsites)
6999         {
7000             fprintf(fplog, "%40s  %-7s %6.3f nm\n",
7001                     "virtual site constructions", "(-rcon)", limit);
7002         }
7003         if (dd->bInterCGcons || dd->bInterCGsettles)
7004         {
7005             sprintf(buf, "atoms separated by up to %d constraints",
7006                     1+ir->nProjOrder);
7007             fprintf(fplog, "%40s  %-7s %6.3f nm\n",
7008                     buf, "(-rcon)", limit);
7009         }
7010         fprintf(fplog, "\n");
7011     }
7012
7013     fflush(fplog);
7014 }
7015
7016 static void set_cell_limits_dlb(gmx_domdec_t      *dd,
7017                                 real               dlb_scale,
7018                                 const t_inputrec  *ir,
7019                                 const gmx_ddbox_t *ddbox)
7020 {
7021     gmx_domdec_comm_t *comm;
7022     int                d, dim, npulse, npulse_d_max, npulse_d;
7023     gmx_bool           bNoCutOff;
7024
7025     comm = dd->comm;
7026
7027     bNoCutOff = (ir->rvdw == 0 || ir->rcoulomb == 0);
7028
7029     /* Determine the maximum number of comm. pulses in one dimension */
7030
7031     comm->cellsize_limit = std::max(comm->cellsize_limit, comm->cutoff_mbody);
7032
7033     /* Determine the maximum required number of grid pulses */
7034     if (comm->cellsize_limit >= comm->cutoff)
7035     {
7036         /* Only a single pulse is required */
7037         npulse = 1;
7038     }
7039     else if (!bNoCutOff && comm->cellsize_limit > 0)
7040     {
7041         /* We round down slightly here to avoid overhead due to the latency
7042          * of extra communication calls when the cut-off
7043          * would be only slightly longer than the cell size.
7044          * Later cellsize_limit is redetermined,
7045          * so we can not miss interactions due to this rounding.
7046          */
7047         npulse = (int)(0.96 + comm->cutoff/comm->cellsize_limit);
7048     }
7049     else
7050     {
7051         /* There is no cell size limit */
7052         npulse = std::max(dd->nc[XX]-1, std::max(dd->nc[YY]-1, dd->nc[ZZ]-1));
7053     }
7054
7055     if (!bNoCutOff && npulse > 1)
7056     {
7057         /* See if we can do with less pulses, based on dlb_scale */
7058         npulse_d_max = 0;
7059         for (d = 0; d < dd->ndim; d++)
7060         {
7061             dim      = dd->dim[d];
7062             npulse_d = (int)(1 + dd->nc[dim]*comm->cutoff
7063                              /(ddbox->box_size[dim]*ddbox->skew_fac[dim]*dlb_scale));
7064             npulse_d_max = std::max(npulse_d_max, npulse_d);
7065         }
7066         npulse = std::min(npulse, npulse_d_max);
7067     }
7068
7069     /* This env var can override npulse */
7070     d = dd_getenv(debug, "GMX_DD_NPULSE", 0);
7071     if (d > 0)
7072     {
7073         npulse = d;
7074     }
7075
7076     comm->maxpulse       = 1;
7077     comm->bVacDLBNoLimit = (ir->ePBC == epbcNONE);
7078     for (d = 0; d < dd->ndim; d++)
7079     {
7080         comm->cd[d].np_dlb    = std::min(npulse, dd->nc[dd->dim[d]]-1);
7081         comm->cd[d].np_nalloc = comm->cd[d].np_dlb;
7082         snew(comm->cd[d].ind, comm->cd[d].np_nalloc);
7083         comm->maxpulse = std::max(comm->maxpulse, comm->cd[d].np_dlb);
7084         if (comm->cd[d].np_dlb < dd->nc[dd->dim[d]]-1)
7085         {
7086             comm->bVacDLBNoLimit = FALSE;
7087         }
7088     }
7089
7090     /* cellsize_limit is set for LINCS in init_domain_decomposition */
7091     if (!comm->bVacDLBNoLimit)
7092     {
7093         comm->cellsize_limit = std::max(comm->cellsize_limit,
7094                                         comm->cutoff/comm->maxpulse);
7095     }
7096     comm->cellsize_limit = std::max(comm->cellsize_limit, comm->cutoff_mbody);
7097     /* Set the minimum cell size for each DD dimension */
7098     for (d = 0; d < dd->ndim; d++)
7099     {
7100         if (comm->bVacDLBNoLimit ||
7101             comm->cd[d].np_dlb*comm->cellsize_limit >= comm->cutoff)
7102         {
7103             comm->cellsize_min_dlb[dd->dim[d]] = comm->cellsize_limit;
7104         }
7105         else
7106         {
7107             comm->cellsize_min_dlb[dd->dim[d]] =
7108                 comm->cutoff/comm->cd[d].np_dlb;
7109         }
7110     }
7111     if (comm->cutoff_mbody <= 0)
7112     {
7113         comm->cutoff_mbody = std::min(comm->cutoff, comm->cellsize_limit);
7114     }
7115     if (isDlbOn(comm))
7116     {
7117         set_dlb_limits(dd);
7118     }
7119 }
7120
7121 gmx_bool dd_bonded_molpbc(const gmx_domdec_t *dd, int ePBC)
7122 {
7123     /* If each molecule is a single charge group
7124      * or we use domain decomposition for each periodic dimension,
7125      * we do not need to take pbc into account for the bonded interactions.
7126      */
7127     return (ePBC != epbcNONE && dd->comm->bInterCGBondeds &&
7128             !(dd->nc[XX] > 1 &&
7129               dd->nc[YY] > 1 &&
7130               (dd->nc[ZZ] > 1 || ePBC == epbcXY)));
7131 }
7132
7133 /*! \brief Sets grid size limits and PP-PME setup, prints settings to log */
7134 static void set_ddgrid_parameters(FILE *fplog, gmx_domdec_t *dd, real dlb_scale,
7135                                   const gmx_mtop_t *mtop, const t_inputrec *ir,
7136                                   const gmx_ddbox_t *ddbox)
7137 {
7138     gmx_domdec_comm_t *comm;
7139     int                natoms_tot;
7140     real               vol_frac;
7141
7142     comm = dd->comm;
7143
7144     if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
7145     {
7146         init_ddpme(dd, &comm->ddpme[0], 0);
7147         if (comm->npmedecompdim >= 2)
7148         {
7149             init_ddpme(dd, &comm->ddpme[1], 1);
7150         }
7151     }
7152     else
7153     {
7154         comm->npmenodes = 0;
7155         if (dd->pme_nodeid >= 0)
7156         {
7157             gmx_fatal_collective(FARGS, dd->mpi_comm_all, DDMASTER(dd),
7158                                  "Can not have separate PME ranks without PME electrostatics");
7159         }
7160     }
7161
7162     if (debug)
7163     {
7164         fprintf(debug, "The DD cut-off is %f\n", comm->cutoff);
7165     }
7166     if (!isDlbDisabled(comm))
7167     {
7168         set_cell_limits_dlb(dd, dlb_scale, ir, ddbox);
7169     }
7170
7171     print_dd_settings(fplog, dd, mtop, ir, isDlbOn(comm), dlb_scale, ddbox);
7172     if (comm->dlbState == edlbsOffCanTurnOn)
7173     {
7174         if (fplog)
7175         {
7176             fprintf(fplog, "When dynamic load balancing gets turned on, these settings will change to:\n");
7177         }
7178         print_dd_settings(fplog, dd, mtop, ir, TRUE, dlb_scale, ddbox);
7179     }
7180
7181     if (ir->ePBC == epbcNONE)
7182     {
7183         vol_frac = 1 - 1/(double)dd->nnodes;
7184     }
7185     else
7186     {
7187         vol_frac =
7188             (1 + comm_box_frac(dd->nc, comm->cutoff, ddbox))/(double)dd->nnodes;
7189     }
7190     if (debug)
7191     {
7192         fprintf(debug, "Volume fraction for all DD zones: %f\n", vol_frac);
7193     }
7194     natoms_tot = comm->cgs_gl.index[comm->cgs_gl.nr];
7195
7196     dd->ga2la = ga2la_init(natoms_tot, static_cast<int>(vol_frac*natoms_tot));
7197 }
7198
7199 /*! \brief Set some important DD parameters that can be modified by env.vars */
7200 static void set_dd_envvar_options(FILE *fplog, gmx_domdec_t *dd, int rank_mysim)
7201 {
7202     gmx_domdec_comm_t *comm = dd->comm;
7203
7204     dd->bSendRecv2      = dd_getenv(fplog, "GMX_DD_USE_SENDRECV2", 0);
7205     comm->dlb_scale_lim = dd_getenv(fplog, "GMX_DLB_MAX_BOX_SCALING", 10);
7206     comm->eFlop         = dd_getenv(fplog, "GMX_DLB_BASED_ON_FLOPS", 0);
7207     int recload         = dd_getenv(fplog, "GMX_DD_RECORD_LOAD", 1);
7208     comm->nstDDDump     = dd_getenv(fplog, "GMX_DD_NST_DUMP", 0);
7209     comm->nstDDDumpGrid = dd_getenv(fplog, "GMX_DD_NST_DUMP_GRID", 0);
7210     comm->DD_debug      = dd_getenv(fplog, "GMX_DD_DEBUG", 0);
7211
7212     if (dd->bSendRecv2 && fplog)
7213     {
7214         fprintf(fplog, "Will use two sequential MPI_Sendrecv calls instead of two simultaneous non-blocking MPI_Irecv and MPI_Isend pairs for constraint and vsite communication\n");
7215     }
7216
7217     if (comm->eFlop)
7218     {
7219         if (fplog)
7220         {
7221             fprintf(fplog, "Will load balance based on FLOP count\n");
7222         }
7223         if (comm->eFlop > 1)
7224         {
7225             srand(1 + rank_mysim);
7226         }
7227         comm->bRecordLoad = TRUE;
7228     }
7229     else
7230     {
7231         comm->bRecordLoad = (wallcycle_have_counter() && recload > 0);
7232     }
7233 }
7234
7235 DomdecOptions::DomdecOptions() :
7236     checkBondedInteractions(TRUE),
7237     useBondedCommunication(TRUE),
7238     numPmeRanks(-1),
7239     rankOrder(DdRankOrder::pp_pme),
7240     minimumCommunicationRange(0),
7241     constraintCommunicationRange(0),
7242     dlbOption(DlbOption::turnOnWhenUseful),
7243     dlbScaling(0.8),
7244     cellSizeX(nullptr),
7245     cellSizeY(nullptr),
7246     cellSizeZ(nullptr)
7247 {
7248     clear_ivec(numCells);
7249 }
7250
7251 gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
7252                                         const DomdecOptions &options,
7253                                         const MdrunOptions &mdrunOptions,
7254                                         const gmx_mtop_t *mtop,
7255                                         const t_inputrec *ir,
7256                                         const matrix box,
7257                                         const rvec *xGlobal,
7258                                         gmx_ddbox_t *ddbox,
7259                                         int *npme_x, int *npme_y)
7260 {
7261     gmx_domdec_t      *dd;
7262
7263     if (fplog)
7264     {
7265         fprintf(fplog,
7266                 "\nInitializing Domain Decomposition on %d ranks\n", cr->nnodes);
7267     }
7268
7269     snew(dd, 1);
7270
7271     dd->comm = init_dd_comm();
7272
7273     set_dd_envvar_options(fplog, dd, cr->nodeid);
7274
7275     set_dd_limits_and_grid(fplog, cr, dd, options, mdrunOptions,
7276                            mtop, ir,
7277                            box, xGlobal,
7278                            ddbox,
7279                            npme_x, npme_y);
7280
7281     make_dd_communicators(fplog, cr, dd, options.rankOrder);
7282
7283     if (thisRankHasDuty(cr, DUTY_PP))
7284     {
7285         set_ddgrid_parameters(fplog, dd, options.dlbScaling, mtop, ir, ddbox);
7286
7287         setup_neighbor_relations(dd);
7288     }
7289
7290     /* Set overallocation to avoid frequent reallocation of arrays */
7291     set_over_alloc_dd(TRUE);
7292
7293     /* Initialize DD paritioning counters */
7294     dd->comm->partition_step = INT_MIN;
7295     dd->ddp_count            = 0;
7296
7297     /* We currently don't know the number of threads yet, we set this later */
7298     dd->comm->nth = 0;
7299
7300     clear_dd_cycle_counts(dd);
7301
7302     return dd;
7303 }
7304
7305 static gmx_bool test_dd_cutoff(t_commrec *cr,
7306                                t_state *state, const t_inputrec *ir,
7307                                real cutoff_req)
7308 {
7309     gmx_domdec_t *dd;
7310     gmx_ddbox_t   ddbox;
7311     int           d, dim, np;
7312     real          inv_cell_size;
7313     int           LocallyLimited;
7314
7315     dd = cr->dd;
7316
7317     set_ddbox(dd, FALSE, cr, ir, state->box,
7318               TRUE, &dd->comm->cgs_gl, as_rvec_array(state->x.data()), &ddbox);
7319
7320     LocallyLimited = 0;
7321
7322     for (d = 0; d < dd->ndim; d++)
7323     {
7324         dim = dd->dim[d];
7325
7326         inv_cell_size = DD_CELL_MARGIN*dd->nc[dim]/ddbox.box_size[dim];
7327         if (dynamic_dd_box(&ddbox, ir))
7328         {
7329             inv_cell_size *= DD_PRES_SCALE_MARGIN;
7330         }
7331
7332         np = 1 + (int)(cutoff_req*inv_cell_size*ddbox.skew_fac[dim]);
7333
7334         if (!isDlbDisabled(dd->comm) && (dim < ddbox.npbcdim) && (dd->comm->cd[d].np_dlb > 0))
7335         {
7336             if (np > dd->comm->cd[d].np_dlb)
7337             {
7338                 return FALSE;
7339             }
7340
7341             /* If a current local cell size is smaller than the requested
7342              * cut-off, we could still fix it, but this gets very complicated.
7343              * Without fixing here, we might actually need more checks.
7344              */
7345             if ((dd->comm->cell_x1[dim] - dd->comm->cell_x0[dim])*ddbox.skew_fac[dim]*dd->comm->cd[d].np_dlb < cutoff_req)
7346             {
7347                 LocallyLimited = 1;
7348             }
7349         }
7350     }
7351
7352     if (!isDlbDisabled(dd->comm))
7353     {
7354         /* If DLB is not active yet, we don't need to check the grid jumps.
7355          * Actually we shouldn't, because then the grid jump data is not set.
7356          */
7357         if (isDlbOn(dd->comm) &&
7358             check_grid_jump(0, dd, cutoff_req, &ddbox, FALSE))
7359         {
7360             LocallyLimited = 1;
7361         }
7362
7363         gmx_sumi(1, &LocallyLimited, cr);
7364
7365         if (LocallyLimited > 0)
7366         {
7367             return FALSE;
7368         }
7369     }
7370
7371     return TRUE;
7372 }
7373
7374 gmx_bool change_dd_cutoff(t_commrec *cr, t_state *state, const t_inputrec *ir,
7375                           real cutoff_req)
7376 {
7377     gmx_bool bCutoffAllowed;
7378
7379     bCutoffAllowed = test_dd_cutoff(cr, state, ir, cutoff_req);
7380
7381     if (bCutoffAllowed)
7382     {
7383         cr->dd->comm->cutoff = cutoff_req;
7384     }
7385
7386     return bCutoffAllowed;
7387 }
7388
7389 void set_dd_dlb_max_cutoff(t_commrec *cr, real cutoff)
7390 {
7391     gmx_domdec_comm_t *comm;
7392
7393     comm = cr->dd->comm;
7394
7395     /* Turn on the DLB limiting (might have been on already) */
7396     comm->bPMELoadBalDLBLimits = TRUE;
7397
7398     /* Change the cut-off limit */
7399     comm->PMELoadBal_max_cutoff = cutoff;
7400
7401     if (debug)
7402     {
7403         fprintf(debug, "PME load balancing set a limit to the DLB staggering such that a %f cut-off will continue to fit\n",
7404                 comm->PMELoadBal_max_cutoff);
7405     }
7406 }
7407
7408 /* Sets whether we should later check the load imbalance data, so that
7409  * we can trigger dynamic load balancing if enough imbalance has
7410  * arisen.
7411  *
7412  * Used after PME load balancing unlocks DLB, so that the check
7413  * whether DLB will be useful can happen immediately.
7414  */
7415 static void dd_dlb_set_should_check_whether_to_turn_dlb_on(gmx_domdec_t *dd, gmx_bool bValue)
7416 {
7417     if (dd->comm->dlbState == edlbsOffCanTurnOn)
7418     {
7419         dd->comm->bCheckWhetherToTurnDlbOn = bValue;
7420
7421         if (bValue == TRUE)
7422         {
7423             /* Store the DD partitioning count, so we can ignore cycle counts
7424              * over the next nstlist steps, which are often slower.
7425              */
7426             dd->comm->ddPartioningCountFirstDlbOff = dd->ddp_count;
7427         }
7428     }
7429 }
7430
7431 /* Returns if we should check whether there has been enough load
7432  * imbalance to trigger dynamic load balancing.
7433  */
7434 static gmx_bool dd_dlb_get_should_check_whether_to_turn_dlb_on(gmx_domdec_t *dd)
7435 {
7436     if (dd->comm->dlbState != edlbsOffCanTurnOn)
7437     {
7438         return FALSE;
7439     }
7440
7441     if (dd->ddp_count <= dd->comm->ddPartioningCountFirstDlbOff)
7442     {
7443         /* We ignore the first nstlist steps at the start of the run
7444          * or after PME load balancing or after turning DLB off, since
7445          * these often have extra allocation or cache miss overhead.
7446          */
7447         return FALSE;
7448     }
7449
7450     if (dd->comm->cycl_n[ddCyclStep] == 0)
7451     {
7452         /* We can have zero timed steps when dd_partition_system is called
7453          * more than once at the same step, e.g. with replica exchange.
7454          * Turning on DLB would trigger an assertion failure later, but is
7455          * also useless right after exchanging replicas.
7456          */
7457         return FALSE;
7458     }
7459
7460     /* We should check whether we should use DLB directly after
7461      * unlocking DLB. */
7462     if (dd->comm->bCheckWhetherToTurnDlbOn)
7463     {
7464         /* This flag was set when the PME load-balancing routines
7465            unlocked DLB, and should now be cleared. */
7466         dd_dlb_set_should_check_whether_to_turn_dlb_on(dd, FALSE);
7467         return TRUE;
7468     }
7469     /* We check whether we should use DLB every c_checkTurnDlbOnInterval
7470      * partitionings (we do not do this every partioning, so that we
7471      * avoid excessive communication). */
7472     if (dd->comm->n_load_have % c_checkTurnDlbOnInterval == c_checkTurnDlbOnInterval - 1)
7473     {
7474         return TRUE;
7475     }
7476
7477     return FALSE;
7478 }
7479
7480 gmx_bool dd_dlb_is_on(const gmx_domdec_t *dd)
7481 {
7482     return isDlbOn(dd->comm);
7483 }
7484
7485 gmx_bool dd_dlb_is_locked(const gmx_domdec_t *dd)
7486 {
7487     return (dd->comm->dlbState == edlbsOffTemporarilyLocked);
7488 }
7489
7490 void dd_dlb_lock(gmx_domdec_t *dd)
7491 {
7492     /* We can only lock the DLB when it is set to auto, otherwise don't do anything */
7493     if (dd->comm->dlbState == edlbsOffCanTurnOn)
7494     {
7495         dd->comm->dlbState = edlbsOffTemporarilyLocked;
7496     }
7497 }
7498
7499 void dd_dlb_unlock(gmx_domdec_t *dd)
7500 {
7501     /* We can only lock the DLB when it is set to auto, otherwise don't do anything */
7502     if (dd->comm->dlbState == edlbsOffTemporarilyLocked)
7503     {
7504         dd->comm->dlbState = edlbsOffCanTurnOn;
7505         dd_dlb_set_should_check_whether_to_turn_dlb_on(dd, TRUE);
7506     }
7507 }
7508
7509 static void merge_cg_buffers(int ncell,
7510                              gmx_domdec_comm_dim_t *cd, int pulse,
7511                              int  *ncg_cell,
7512                              int  *index_gl, int  *recv_i,
7513                              rvec *cg_cm,    rvec *recv_vr,
7514                              int *cgindex,
7515                              cginfo_mb_t *cginfo_mb, int *cginfo)
7516 {
7517     gmx_domdec_ind_t *ind, *ind_p;
7518     int               p, cell, c, cg, cg0, cg1, cg_gl, nat;
7519     int               shift, shift_at;
7520
7521     ind = &cd->ind[pulse];
7522
7523     /* First correct the already stored data */
7524     shift = ind->nrecv[ncell];
7525     for (cell = ncell-1; cell >= 0; cell--)
7526     {
7527         shift -= ind->nrecv[cell];
7528         if (shift > 0)
7529         {
7530             /* Move the cg's present from previous grid pulses */
7531             cg0                = ncg_cell[ncell+cell];
7532             cg1                = ncg_cell[ncell+cell+1];
7533             cgindex[cg1+shift] = cgindex[cg1];
7534             for (cg = cg1-1; cg >= cg0; cg--)
7535             {
7536                 index_gl[cg+shift] = index_gl[cg];
7537                 copy_rvec(cg_cm[cg], cg_cm[cg+shift]);
7538                 cgindex[cg+shift] = cgindex[cg];
7539                 cginfo[cg+shift]  = cginfo[cg];
7540             }
7541             /* Correct the already stored send indices for the shift */
7542             for (p = 1; p <= pulse; p++)
7543             {
7544                 ind_p = &cd->ind[p];
7545                 cg0   = 0;
7546                 for (c = 0; c < cell; c++)
7547                 {
7548                     cg0 += ind_p->nsend[c];
7549                 }
7550                 cg1 = cg0 + ind_p->nsend[cell];
7551                 for (cg = cg0; cg < cg1; cg++)
7552                 {
7553                     ind_p->index[cg] += shift;
7554                 }
7555             }
7556         }
7557     }
7558
7559     /* Merge in the communicated buffers */
7560     shift    = 0;
7561     shift_at = 0;
7562     cg0      = 0;
7563     for (cell = 0; cell < ncell; cell++)
7564     {
7565         cg1 = ncg_cell[ncell+cell+1] + shift;
7566         if (shift_at > 0)
7567         {
7568             /* Correct the old cg indices */
7569             for (cg = ncg_cell[ncell+cell]; cg < cg1; cg++)
7570             {
7571                 cgindex[cg+1] += shift_at;
7572             }
7573         }
7574         for (cg = 0; cg < ind->nrecv[cell]; cg++)
7575         {
7576             /* Copy this charge group from the buffer */
7577             index_gl[cg1] = recv_i[cg0];
7578             copy_rvec(recv_vr[cg0], cg_cm[cg1]);
7579             /* Add it to the cgindex */
7580             cg_gl          = index_gl[cg1];
7581             cginfo[cg1]    = ddcginfo(cginfo_mb, cg_gl);
7582             nat            = GET_CGINFO_NATOMS(cginfo[cg1]);
7583             cgindex[cg1+1] = cgindex[cg1] + nat;
7584             cg0++;
7585             cg1++;
7586             shift_at += nat;
7587         }
7588         shift                 += ind->nrecv[cell];
7589         ncg_cell[ncell+cell+1] = cg1;
7590     }
7591 }
7592
7593 static void make_cell2at_index(gmx_domdec_comm_dim_t *cd,
7594                                int nzone, int cg0, const int *cgindex)
7595 {
7596     int cg, zone, p;
7597
7598     /* Store the atom block boundaries for easy copying of communication buffers
7599      */
7600     cg = cg0;
7601     for (zone = 0; zone < nzone; zone++)
7602     {
7603         for (p = 0; p < cd->np; p++)
7604         {
7605             cd->ind[p].cell2at0[zone] = cgindex[cg];
7606             cg += cd->ind[p].nrecv[zone];
7607             cd->ind[p].cell2at1[zone] = cgindex[cg];
7608         }
7609     }
7610 }
7611
7612 static gmx_bool missing_link(t_blocka *link, int cg_gl, char *bLocalCG)
7613 {
7614     int      i;
7615     gmx_bool bMiss;
7616
7617     bMiss = FALSE;
7618     for (i = link->index[cg_gl]; i < link->index[cg_gl+1]; i++)
7619     {
7620         if (!bLocalCG[link->a[i]])
7621         {
7622             bMiss = TRUE;
7623         }
7624     }
7625
7626     return bMiss;
7627 }
7628
7629 /* Domain corners for communication, a maximum of 4 i-zones see a j domain */
7630 typedef struct {
7631     real c[DIM][4]; /* the corners for the non-bonded communication */
7632     real cr0;       /* corner for rounding */
7633     real cr1[4];    /* corners for rounding */
7634     real bc[DIM];   /* corners for bounded communication */
7635     real bcr1;      /* corner for rounding for bonded communication */
7636 } dd_corners_t;
7637
7638 /* Determine the corners of the domain(s) we are communicating with */
7639 static void
7640 set_dd_corners(const gmx_domdec_t *dd,
7641                int dim0, int dim1, int dim2,
7642                gmx_bool bDistMB,
7643                dd_corners_t *c)
7644 {
7645     const gmx_domdec_comm_t  *comm;
7646     const gmx_domdec_zones_t *zones;
7647     int i, j;
7648
7649     comm = dd->comm;
7650
7651     zones = &comm->zones;
7652
7653     /* Keep the compiler happy */
7654     c->cr0  = 0;
7655     c->bcr1 = 0;
7656
7657     /* The first dimension is equal for all cells */
7658     c->c[0][0] = comm->cell_x0[dim0];
7659     if (bDistMB)
7660     {
7661         c->bc[0] = c->c[0][0];
7662     }
7663     if (dd->ndim >= 2)
7664     {
7665         dim1 = dd->dim[1];
7666         /* This cell row is only seen from the first row */
7667         c->c[1][0] = comm->cell_x0[dim1];
7668         /* All rows can see this row */
7669         c->c[1][1] = comm->cell_x0[dim1];
7670         if (isDlbOn(dd->comm))
7671         {
7672             c->c[1][1] = std::max(comm->cell_x0[dim1], comm->zone_d1[1].mch0);
7673             if (bDistMB)
7674             {
7675                 /* For the multi-body distance we need the maximum */
7676                 c->bc[1] = std::max(comm->cell_x0[dim1], comm->zone_d1[1].p1_0);
7677             }
7678         }
7679         /* Set the upper-right corner for rounding */
7680         c->cr0 = comm->cell_x1[dim0];
7681
7682         if (dd->ndim >= 3)
7683         {
7684             dim2 = dd->dim[2];
7685             for (j = 0; j < 4; j++)
7686             {
7687                 c->c[2][j] = comm->cell_x0[dim2];
7688             }
7689             if (isDlbOn(dd->comm))
7690             {
7691                 /* Use the maximum of the i-cells that see a j-cell */
7692                 for (i = 0; i < zones->nizone; i++)
7693                 {
7694                     for (j = zones->izone[i].j0; j < zones->izone[i].j1; j++)
7695                     {
7696                         if (j >= 4)
7697                         {
7698                             c->c[2][j-4] =
7699                                 std::max(c->c[2][j-4],
7700                                          comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0);
7701                         }
7702                     }
7703                 }
7704                 if (bDistMB)
7705                 {
7706                     /* For the multi-body distance we need the maximum */
7707                     c->bc[2] = comm->cell_x0[dim2];
7708                     for (i = 0; i < 2; i++)
7709                     {
7710                         for (j = 0; j < 2; j++)
7711                         {
7712                             c->bc[2] = std::max(c->bc[2], comm->zone_d2[i][j].p1_0);
7713                         }
7714                     }
7715                 }
7716             }
7717
7718             /* Set the upper-right corner for rounding */
7719             /* Cell (0,0,0) and cell (1,0,0) can see cell 4 (0,1,1)
7720              * Only cell (0,0,0) can see cell 7 (1,1,1)
7721              */
7722             c->cr1[0] = comm->cell_x1[dim1];
7723             c->cr1[3] = comm->cell_x1[dim1];
7724             if (isDlbOn(dd->comm))
7725             {
7726                 c->cr1[0] = std::max(comm->cell_x1[dim1], comm->zone_d1[1].mch1);
7727                 if (bDistMB)
7728                 {
7729                     /* For the multi-body distance we need the maximum */
7730                     c->bcr1 = std::max(comm->cell_x1[dim1], comm->zone_d1[1].p1_1);
7731                 }
7732             }
7733         }
7734     }
7735 }
7736
7737 /* Determine which cg's we need to send in this pulse from this zone */
7738 static void
7739 get_zone_pulse_cgs(gmx_domdec_t *dd,
7740                    int zonei, int zone,
7741                    int cg0, int cg1,
7742                    const int *index_gl,
7743                    const int *cgindex,
7744                    int dim, int dim_ind,
7745                    int dim0, int dim1, int dim2,
7746                    real r_comm2, real r_bcomm2,
7747                    matrix box,
7748                    ivec tric_dist,
7749                    rvec *normal,
7750                    real skew_fac2_d, real skew_fac_01,
7751                    rvec *v_d, rvec *v_0, rvec *v_1,
7752                    const dd_corners_t *c,
7753                    rvec sf2_round,
7754                    gmx_bool bDistBonded,
7755                    gmx_bool bBondComm,
7756                    gmx_bool bDist2B,
7757                    gmx_bool bDistMB,
7758                    rvec *cg_cm,
7759                    int *cginfo,
7760                    gmx_domdec_ind_t *ind,
7761                    int **ibuf, int *ibuf_nalloc,
7762                    vec_rvec_t *vbuf,
7763                    int *nsend_ptr,
7764                    int *nat_ptr,
7765                    int *nsend_z_ptr)
7766 {
7767     gmx_domdec_comm_t *comm;
7768     gmx_bool           bScrew;
7769     gmx_bool           bDistMB_pulse;
7770     int                cg, i;
7771     real               r2, rb2, r, tric_sh;
7772     rvec               rn, rb;
7773     int                dimd;
7774     int                nsend_z, nsend, nat;
7775
7776     comm = dd->comm;
7777
7778     bScrew = (dd->bScrewPBC && dim == XX);
7779
7780     bDistMB_pulse = (bDistMB && bDistBonded);
7781
7782     nsend_z = 0;
7783     nsend   = *nsend_ptr;
7784     nat     = *nat_ptr;
7785
7786     for (cg = cg0; cg < cg1; cg++)
7787     {
7788         r2  = 0;
7789         rb2 = 0;
7790         if (tric_dist[dim_ind] == 0)
7791         {
7792             /* Rectangular direction, easy */
7793             r = cg_cm[cg][dim] - c->c[dim_ind][zone];
7794             if (r > 0)
7795             {
7796                 r2 += r*r;
7797             }
7798             if (bDistMB_pulse)
7799             {
7800                 r = cg_cm[cg][dim] - c->bc[dim_ind];
7801                 if (r > 0)
7802                 {
7803                     rb2 += r*r;
7804                 }
7805             }
7806             /* Rounding gives at most a 16% reduction
7807              * in communicated atoms
7808              */
7809             if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
7810             {
7811                 r = cg_cm[cg][dim0] - c->cr0;
7812                 /* This is the first dimension, so always r >= 0 */
7813                 r2 += r*r;
7814                 if (bDistMB_pulse)
7815                 {
7816                     rb2 += r*r;
7817                 }
7818             }
7819             if (dim_ind == 2 && (zonei == 2 || zonei == 3))
7820             {
7821                 r = cg_cm[cg][dim1] - c->cr1[zone];
7822                 if (r > 0)
7823                 {
7824                     r2 += r*r;
7825                 }
7826                 if (bDistMB_pulse)
7827                 {
7828                     r = cg_cm[cg][dim1] - c->bcr1;
7829                     if (r > 0)
7830                     {
7831                         rb2 += r*r;
7832                     }
7833                 }
7834             }
7835         }
7836         else
7837         {
7838             /* Triclinic direction, more complicated */
7839             clear_rvec(rn);
7840             clear_rvec(rb);
7841             /* Rounding, conservative as the skew_fac multiplication
7842              * will slightly underestimate the distance.
7843              */
7844             if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
7845             {
7846                 rn[dim0] = cg_cm[cg][dim0] - c->cr0;
7847                 for (i = dim0+1; i < DIM; i++)
7848                 {
7849                     rn[dim0] -= cg_cm[cg][i]*v_0[i][dim0];
7850                 }
7851                 r2 = rn[dim0]*rn[dim0]*sf2_round[dim0];
7852                 if (bDistMB_pulse)
7853                 {
7854                     rb[dim0] = rn[dim0];
7855                     rb2      = r2;
7856                 }
7857                 /* Take care that the cell planes along dim0 might not
7858                  * be orthogonal to those along dim1 and dim2.
7859                  */
7860                 for (i = 1; i <= dim_ind; i++)
7861                 {
7862                     dimd = dd->dim[i];
7863                     if (normal[dim0][dimd] > 0)
7864                     {
7865                         rn[dimd] -= rn[dim0]*normal[dim0][dimd];
7866                         if (bDistMB_pulse)
7867                         {
7868                             rb[dimd] -= rb[dim0]*normal[dim0][dimd];
7869                         }
7870                     }
7871                 }
7872             }
7873             if (dim_ind == 2 && (zonei == 2 || zonei == 3))
7874             {
7875                 rn[dim1] += cg_cm[cg][dim1] - c->cr1[zone];
7876                 tric_sh   = 0;
7877                 for (i = dim1+1; i < DIM; i++)
7878                 {
7879                     tric_sh -= cg_cm[cg][i]*v_1[i][dim1];
7880                 }
7881                 rn[dim1] += tric_sh;
7882                 if (rn[dim1] > 0)
7883                 {
7884                     r2 += rn[dim1]*rn[dim1]*sf2_round[dim1];
7885                     /* Take care of coupling of the distances
7886                      * to the planes along dim0 and dim1 through dim2.
7887                      */
7888                     r2 -= rn[dim0]*rn[dim1]*skew_fac_01;
7889                     /* Take care that the cell planes along dim1
7890                      * might not be orthogonal to that along dim2.
7891                      */
7892                     if (normal[dim1][dim2] > 0)
7893                     {
7894                         rn[dim2] -= rn[dim1]*normal[dim1][dim2];
7895                     }
7896                 }
7897                 if (bDistMB_pulse)
7898                 {
7899                     rb[dim1] +=
7900                         cg_cm[cg][dim1] - c->bcr1 + tric_sh;
7901                     if (rb[dim1] > 0)
7902                     {
7903                         rb2 += rb[dim1]*rb[dim1]*sf2_round[dim1];
7904                         /* Take care of coupling of the distances
7905                          * to the planes along dim0 and dim1 through dim2.
7906                          */
7907                         rb2 -= rb[dim0]*rb[dim1]*skew_fac_01;
7908                         /* Take care that the cell planes along dim1
7909                          * might not be orthogonal to that along dim2.
7910                          */
7911                         if (normal[dim1][dim2] > 0)
7912                         {
7913                             rb[dim2] -= rb[dim1]*normal[dim1][dim2];
7914                         }
7915                     }
7916                 }
7917             }
7918             /* The distance along the communication direction */
7919             rn[dim] += cg_cm[cg][dim] - c->c[dim_ind][zone];
7920             tric_sh  = 0;
7921             for (i = dim+1; i < DIM; i++)
7922             {
7923                 tric_sh -= cg_cm[cg][i]*v_d[i][dim];
7924             }
7925             rn[dim] += tric_sh;
7926             if (rn[dim] > 0)
7927             {
7928                 r2 += rn[dim]*rn[dim]*skew_fac2_d;
7929                 /* Take care of coupling of the distances
7930                  * to the planes along dim0 and dim1 through dim2.
7931                  */
7932                 if (dim_ind == 1 && zonei == 1)
7933                 {
7934                     r2 -= rn[dim0]*rn[dim]*skew_fac_01;
7935                 }
7936             }
7937             if (bDistMB_pulse)
7938             {
7939                 clear_rvec(rb);
7940                 rb[dim] += cg_cm[cg][dim] - c->bc[dim_ind] + tric_sh;
7941                 if (rb[dim] > 0)
7942                 {
7943                     rb2 += rb[dim]*rb[dim]*skew_fac2_d;
7944                     /* Take care of coupling of the distances
7945                      * to the planes along dim0 and dim1 through dim2.
7946                      */
7947                     if (dim_ind == 1 && zonei == 1)
7948                     {
7949                         rb2 -= rb[dim0]*rb[dim]*skew_fac_01;
7950                     }
7951                 }
7952             }
7953         }
7954
7955         if (r2 < r_comm2 ||
7956             (bDistBonded &&
7957              ((bDistMB && rb2 < r_bcomm2) ||
7958               (bDist2B && r2  < r_bcomm2)) &&
7959              (!bBondComm ||
7960               (GET_CGINFO_BOND_INTER(cginfo[cg]) &&
7961                missing_link(comm->cglink, index_gl[cg],
7962                             comm->bLocalCG)))))
7963         {
7964             /* Make an index to the local charge groups */
7965             if (nsend+1 > ind->nalloc)
7966             {
7967                 ind->nalloc = over_alloc_large(nsend+1);
7968                 srenew(ind->index, ind->nalloc);
7969             }
7970             if (nsend+1 > *ibuf_nalloc)
7971             {
7972                 *ibuf_nalloc = over_alloc_large(nsend+1);
7973                 srenew(*ibuf, *ibuf_nalloc);
7974             }
7975             ind->index[nsend] = cg;
7976             (*ibuf)[nsend]    = index_gl[cg];
7977             nsend_z++;
7978             vec_rvec_check_alloc(vbuf, nsend+1);
7979
7980             if (dd->ci[dim] == 0)
7981             {
7982                 /* Correct cg_cm for pbc */
7983                 rvec_add(cg_cm[cg], box[dim], vbuf->v[nsend]);
7984                 if (bScrew)
7985                 {
7986                     vbuf->v[nsend][YY] = box[YY][YY] - vbuf->v[nsend][YY];
7987                     vbuf->v[nsend][ZZ] = box[ZZ][ZZ] - vbuf->v[nsend][ZZ];
7988                 }
7989             }
7990             else
7991             {
7992                 copy_rvec(cg_cm[cg], vbuf->v[nsend]);
7993             }
7994             nsend++;
7995             nat += cgindex[cg+1] - cgindex[cg];
7996         }
7997     }
7998
7999     *nsend_ptr   = nsend;
8000     *nat_ptr     = nat;
8001     *nsend_z_ptr = nsend_z;
8002 }
8003
8004 static void setup_dd_communication(gmx_domdec_t *dd,
8005                                    matrix box, gmx_ddbox_t *ddbox,
8006                                    t_forcerec *fr,
8007                                    t_state *state, PaddedRVecVector *f)
8008 {
8009     int                    dim_ind, dim, dim0, dim1, dim2, dimd, p, nat_tot;
8010     int                    nzone, nzone_send, zone, zonei, cg0, cg1;
8011     int                    c, i, cg, cg_gl, nrcg;
8012     int                   *zone_cg_range, pos_cg, *index_gl, *cgindex, *recv_i;
8013     gmx_domdec_comm_t     *comm;
8014     gmx_domdec_zones_t    *zones;
8015     gmx_domdec_comm_dim_t *cd;
8016     gmx_domdec_ind_t      *ind;
8017     cginfo_mb_t           *cginfo_mb;
8018     gmx_bool               bBondComm, bDist2B, bDistMB, bDistBonded;
8019     real                   r_comm2, r_bcomm2;
8020     dd_corners_t           corners;
8021     ivec                   tric_dist;
8022     rvec                  *cg_cm, *normal, *v_d, *v_0 = nullptr, *v_1 = nullptr, *recv_vr;
8023     real                   skew_fac2_d, skew_fac_01;
8024     rvec                   sf2_round;
8025     int                    nsend, nat;
8026     int                    th;
8027
8028     if (debug)
8029     {
8030         fprintf(debug, "Setting up DD communication\n");
8031     }
8032
8033     comm  = dd->comm;
8034
8035     if (comm->nth == 0)
8036     {
8037         /* Initialize the thread data.
8038          * This can not be done in init_domain_decomposition,
8039          * as the numbers of threads is determined later.
8040          */
8041         comm->nth = gmx_omp_nthreads_get(emntDomdec);
8042         if (comm->nth > 1)
8043         {
8044             snew(comm->dth, comm->nth);
8045         }
8046     }
8047
8048     switch (fr->cutoff_scheme)
8049     {
8050         case ecutsGROUP:
8051             cg_cm = fr->cg_cm;
8052             break;
8053         case ecutsVERLET:
8054             cg_cm = as_rvec_array(state->x.data());
8055             break;
8056         default:
8057             gmx_incons("unimplemented");
8058             cg_cm = nullptr;
8059     }
8060
8061     for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
8062     {
8063         /* Check if we need to use triclinic distances */
8064         tric_dist[dim_ind] = 0;
8065         for (i = 0; i <= dim_ind; i++)
8066         {
8067             if (ddbox->tric_dir[dd->dim[i]])
8068             {
8069                 tric_dist[dim_ind] = 1;
8070             }
8071         }
8072     }
8073
8074     bBondComm = comm->bBondComm;
8075
8076     /* Do we need to determine extra distances for multi-body bondeds? */
8077     bDistMB = (comm->bInterCGMultiBody && isDlbOn(dd->comm) && dd->ndim > 1);
8078
8079     /* Do we need to determine extra distances for only two-body bondeds? */
8080     bDist2B = (bBondComm && !bDistMB);
8081
8082     r_comm2  = gmx::square(comm->cutoff);
8083     r_bcomm2 = gmx::square(comm->cutoff_mbody);
8084
8085     if (debug)
8086     {
8087         fprintf(debug, "bBondComm %d, r_bc %f\n", bBondComm, std::sqrt(r_bcomm2));
8088     }
8089
8090     zones = &comm->zones;
8091
8092     dim0 = dd->dim[0];
8093     dim1 = (dd->ndim >= 2 ? dd->dim[1] : -1);
8094     dim2 = (dd->ndim >= 3 ? dd->dim[2] : -1);
8095
8096     set_dd_corners(dd, dim0, dim1, dim2, bDistMB, &corners);
8097
8098     /* Triclinic stuff */
8099     normal      = ddbox->normal;
8100     skew_fac_01 = 0;
8101     if (dd->ndim >= 2)
8102     {
8103         v_0 = ddbox->v[dim0];
8104         if (ddbox->tric_dir[dim0] && ddbox->tric_dir[dim1])
8105         {
8106             /* Determine the coupling coefficient for the distances
8107              * to the cell planes along dim0 and dim1 through dim2.
8108              * This is required for correct rounding.
8109              */
8110             skew_fac_01 =
8111                 ddbox->v[dim0][dim1+1][dim0]*ddbox->v[dim1][dim1+1][dim1];
8112             if (debug)
8113             {
8114                 fprintf(debug, "\nskew_fac_01 %f\n", skew_fac_01);
8115             }
8116         }
8117     }
8118     if (dd->ndim >= 3)
8119     {
8120         v_1 = ddbox->v[dim1];
8121     }
8122
8123     zone_cg_range = zones->cg_range;
8124     index_gl      = dd->index_gl;
8125     cgindex       = dd->cgindex;
8126     cginfo_mb     = fr->cginfo_mb;
8127
8128     zone_cg_range[0]   = 0;
8129     zone_cg_range[1]   = dd->ncg_home;
8130     comm->zone_ncg1[0] = dd->ncg_home;
8131     pos_cg             = dd->ncg_home;
8132
8133     nat_tot = dd->nat_home;
8134     nzone   = 1;
8135     for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
8136     {
8137         dim = dd->dim[dim_ind];
8138         cd  = &comm->cd[dim_ind];
8139
8140         if (dim >= ddbox->npbcdim && dd->ci[dim] == 0)
8141         {
8142             /* No pbc in this dimension, the first node should not comm. */
8143             nzone_send = 0;
8144         }
8145         else
8146         {
8147             nzone_send = nzone;
8148         }
8149
8150         v_d         = ddbox->v[dim];
8151         skew_fac2_d = gmx::square(ddbox->skew_fac[dim]);
8152
8153         cd->bInPlace = TRUE;
8154         for (p = 0; p < cd->np; p++)
8155         {
8156             /* Only atoms communicated in the first pulse are used
8157              * for multi-body bonded interactions or for bBondComm.
8158              */
8159             bDistBonded = ((bDistMB || bDist2B) && p == 0);
8160
8161             ind   = &cd->ind[p];
8162             nsend = 0;
8163             nat   = 0;
8164             for (zone = 0; zone < nzone_send; zone++)
8165             {
8166                 if (tric_dist[dim_ind] && dim_ind > 0)
8167                 {
8168                     /* Determine slightly more optimized skew_fac's
8169                      * for rounding.
8170                      * This reduces the number of communicated atoms
8171                      * by about 10% for 3D DD of rhombic dodecahedra.
8172                      */
8173                     for (dimd = 0; dimd < dim; dimd++)
8174                     {
8175                         sf2_round[dimd] = 1;
8176                         if (ddbox->tric_dir[dimd])
8177                         {
8178                             for (i = dd->dim[dimd]+1; i < DIM; i++)
8179                             {
8180                                 /* If we are shifted in dimension i
8181                                  * and the cell plane is tilted forward
8182                                  * in dimension i, skip this coupling.
8183                                  */
8184                                 if (!(zones->shift[nzone+zone][i] &&
8185                                       ddbox->v[dimd][i][dimd] >= 0))
8186                                 {
8187                                     sf2_round[dimd] +=
8188                                         gmx::square(ddbox->v[dimd][i][dimd]);
8189                                 }
8190                             }
8191                             sf2_round[dimd] = 1/sf2_round[dimd];
8192                         }
8193                     }
8194                 }
8195
8196                 zonei = zone_perm[dim_ind][zone];
8197                 if (p == 0)
8198                 {
8199                     /* Here we permutate the zones to obtain a convenient order
8200                      * for neighbor searching
8201                      */
8202                     cg0 = zone_cg_range[zonei];
8203                     cg1 = zone_cg_range[zonei+1];
8204                 }
8205                 else
8206                 {
8207                     /* Look only at the cg's received in the previous grid pulse
8208                      */
8209                     cg1 = zone_cg_range[nzone+zone+1];
8210                     cg0 = cg1 - cd->ind[p-1].nrecv[zone];
8211                 }
8212
8213 #pragma omp parallel for num_threads(comm->nth) schedule(static)
8214                 for (th = 0; th < comm->nth; th++)
8215                 {
8216                     try
8217                     {
8218                         gmx_domdec_ind_t *ind_p;
8219                         int             **ibuf_p, *ibuf_nalloc_p;
8220                         vec_rvec_t       *vbuf_p;
8221                         int              *nsend_p, *nat_p;
8222                         int              *nsend_zone_p;
8223                         int               cg0_th, cg1_th;
8224
8225                         if (th == 0)
8226                         {
8227                             /* Thread 0 writes in the comm buffers */
8228                             ind_p         = ind;
8229                             ibuf_p        = &comm->buf_int;
8230                             ibuf_nalloc_p = &comm->nalloc_int;
8231                             vbuf_p        = &comm->vbuf;
8232                             nsend_p       = &nsend;
8233                             nat_p         = &nat;
8234                             nsend_zone_p  = &ind->nsend[zone];
8235                         }
8236                         else
8237                         {
8238                             /* Other threads write into temp buffers */
8239                             ind_p         = &comm->dth[th].ind;
8240                             ibuf_p        = &comm->dth[th].ibuf;
8241                             ibuf_nalloc_p = &comm->dth[th].ibuf_nalloc;
8242                             vbuf_p        = &comm->dth[th].vbuf;
8243                             nsend_p       = &comm->dth[th].nsend;
8244                             nat_p         = &comm->dth[th].nat;
8245                             nsend_zone_p  = &comm->dth[th].nsend_zone;
8246
8247                             comm->dth[th].nsend      = 0;
8248                             comm->dth[th].nat        = 0;
8249                             comm->dth[th].nsend_zone = 0;
8250                         }
8251
8252                         if (comm->nth == 1)
8253                         {
8254                             cg0_th = cg0;
8255                             cg1_th = cg1;
8256                         }
8257                         else
8258                         {
8259                             cg0_th = cg0 + ((cg1 - cg0)* th   )/comm->nth;
8260                             cg1_th = cg0 + ((cg1 - cg0)*(th+1))/comm->nth;
8261                         }
8262
8263                         /* Get the cg's for this pulse in this zone */
8264                         get_zone_pulse_cgs(dd, zonei, zone, cg0_th, cg1_th,
8265                                            index_gl, cgindex,
8266                                            dim, dim_ind, dim0, dim1, dim2,
8267                                            r_comm2, r_bcomm2,
8268                                            box, tric_dist,
8269                                            normal, skew_fac2_d, skew_fac_01,
8270                                            v_d, v_0, v_1, &corners, sf2_round,
8271                                            bDistBonded, bBondComm,
8272                                            bDist2B, bDistMB,
8273                                            cg_cm, fr->cginfo,
8274                                            ind_p,
8275                                            ibuf_p, ibuf_nalloc_p,
8276                                            vbuf_p,
8277                                            nsend_p, nat_p,
8278                                            nsend_zone_p);
8279                     }
8280                     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
8281                 } // END
8282
8283                 /* Append data of threads>=1 to the communication buffers */
8284                 for (th = 1; th < comm->nth; th++)
8285                 {
8286                     dd_comm_setup_work_t *dth;
8287                     int                   i, ns1;
8288
8289                     dth = &comm->dth[th];
8290
8291                     ns1 = nsend + dth->nsend_zone;
8292                     if (ns1 > ind->nalloc)
8293                     {
8294                         ind->nalloc = over_alloc_dd(ns1);
8295                         srenew(ind->index, ind->nalloc);
8296                     }
8297                     if (ns1 > comm->nalloc_int)
8298                     {
8299                         comm->nalloc_int = over_alloc_dd(ns1);
8300                         srenew(comm->buf_int, comm->nalloc_int);
8301                     }
8302                     if (ns1 > comm->vbuf.nalloc)
8303                     {
8304                         comm->vbuf.nalloc = over_alloc_dd(ns1);
8305                         srenew(comm->vbuf.v, comm->vbuf.nalloc);
8306                     }
8307
8308                     for (i = 0; i < dth->nsend_zone; i++)
8309                     {
8310                         ind->index[nsend]    = dth->ind.index[i];
8311                         comm->buf_int[nsend] = dth->ibuf[i];
8312                         copy_rvec(dth->vbuf.v[i],
8313                                   comm->vbuf.v[nsend]);
8314                         nsend++;
8315                     }
8316                     nat              += dth->nat;
8317                     ind->nsend[zone] += dth->nsend_zone;
8318                 }
8319             }
8320             /* Clear the counts in case we do not have pbc */
8321             for (zone = nzone_send; zone < nzone; zone++)
8322             {
8323                 ind->nsend[zone] = 0;
8324             }
8325             ind->nsend[nzone]   = nsend;
8326             ind->nsend[nzone+1] = nat;
8327             /* Communicate the number of cg's and atoms to receive */
8328             dd_sendrecv_int(dd, dim_ind, dddirBackward,
8329                             ind->nsend, nzone+2,
8330                             ind->nrecv, nzone+2);
8331
8332             /* The rvec buffer is also required for atom buffers of size nsend
8333              * in dd_move_x and dd_move_f.
8334              */
8335             vec_rvec_check_alloc(&comm->vbuf, ind->nsend[nzone+1]);
8336
8337             if (p > 0)
8338             {
8339                 /* We can receive in place if only the last zone is not empty */
8340                 for (zone = 0; zone < nzone-1; zone++)
8341                 {
8342                     if (ind->nrecv[zone] > 0)
8343                     {
8344                         cd->bInPlace = FALSE;
8345                     }
8346                 }
8347                 if (!cd->bInPlace)
8348                 {
8349                     /* The int buffer is only required here for the cg indices */
8350                     if (ind->nrecv[nzone] > comm->nalloc_int2)
8351                     {
8352                         comm->nalloc_int2 = over_alloc_dd(ind->nrecv[nzone]);
8353                         srenew(comm->buf_int2, comm->nalloc_int2);
8354                     }
8355                     /* The rvec buffer is also required for atom buffers
8356                      * of size nrecv in dd_move_x and dd_move_f.
8357                      */
8358                     i = std::max(cd->ind[0].nrecv[nzone+1], ind->nrecv[nzone+1]);
8359                     vec_rvec_check_alloc(&comm->vbuf2, i);
8360                 }
8361             }
8362
8363             /* Make space for the global cg indices */
8364             if (pos_cg + ind->nrecv[nzone] > dd->cg_nalloc
8365                 || dd->cg_nalloc == 0)
8366             {
8367                 dd->cg_nalloc = over_alloc_dd(pos_cg + ind->nrecv[nzone]);
8368                 srenew(index_gl, dd->cg_nalloc);
8369                 srenew(cgindex, dd->cg_nalloc+1);
8370             }
8371             /* Communicate the global cg indices */
8372             if (cd->bInPlace)
8373             {
8374                 recv_i = index_gl + pos_cg;
8375             }
8376             else
8377             {
8378                 recv_i = comm->buf_int2;
8379             }
8380             dd_sendrecv_int(dd, dim_ind, dddirBackward,
8381                             comm->buf_int, nsend,
8382                             recv_i,        ind->nrecv[nzone]);
8383
8384             /* Make space for cg_cm */
8385             dd_check_alloc_ncg(fr, state, f, pos_cg + ind->nrecv[nzone]);
8386             if (fr->cutoff_scheme == ecutsGROUP)
8387             {
8388                 cg_cm = fr->cg_cm;
8389             }
8390             else
8391             {
8392                 cg_cm = as_rvec_array(state->x.data());
8393             }
8394             /* Communicate cg_cm */
8395             if (cd->bInPlace)
8396             {
8397                 recv_vr = cg_cm + pos_cg;
8398             }
8399             else
8400             {
8401                 recv_vr = comm->vbuf2.v;
8402             }
8403             dd_sendrecv_rvec(dd, dim_ind, dddirBackward,
8404                              comm->vbuf.v, nsend,
8405                              recv_vr,      ind->nrecv[nzone]);
8406
8407             /* Make the charge group index */
8408             if (cd->bInPlace)
8409             {
8410                 zone = (p == 0 ? 0 : nzone - 1);
8411                 while (zone < nzone)
8412                 {
8413                     for (cg = 0; cg < ind->nrecv[zone]; cg++)
8414                     {
8415                         cg_gl              = index_gl[pos_cg];
8416                         fr->cginfo[pos_cg] = ddcginfo(cginfo_mb, cg_gl);
8417                         nrcg               = GET_CGINFO_NATOMS(fr->cginfo[pos_cg]);
8418                         cgindex[pos_cg+1]  = cgindex[pos_cg] + nrcg;
8419                         if (bBondComm)
8420                         {
8421                             /* Update the charge group presence,
8422                              * so we can use it in the next pass of the loop.
8423                              */
8424                             comm->bLocalCG[cg_gl] = TRUE;
8425                         }
8426                         pos_cg++;
8427                     }
8428                     if (p == 0)
8429                     {
8430                         comm->zone_ncg1[nzone+zone] = ind->nrecv[zone];
8431                     }
8432                     zone++;
8433                     zone_cg_range[nzone+zone] = pos_cg;
8434                 }
8435             }
8436             else
8437             {
8438                 /* This part of the code is never executed with bBondComm. */
8439                 merge_cg_buffers(nzone, cd, p, zone_cg_range,
8440                                  index_gl, recv_i, cg_cm, recv_vr,
8441                                  cgindex, fr->cginfo_mb, fr->cginfo);
8442                 pos_cg += ind->nrecv[nzone];
8443             }
8444             nat_tot += ind->nrecv[nzone+1];
8445         }
8446         if (!cd->bInPlace)
8447         {
8448             /* Store the atom block for easy copying of communication buffers */
8449             make_cell2at_index(cd, nzone, zone_cg_range[nzone], cgindex);
8450         }
8451         nzone += nzone;
8452     }
8453     dd->index_gl = index_gl;
8454     dd->cgindex  = cgindex;
8455
8456     dd->ncg_tot          = zone_cg_range[zones->n];
8457     dd->nat_tot          = nat_tot;
8458     comm->nat[ddnatHOME] = dd->nat_home;
8459     for (i = ddnatZONE; i < ddnatNR; i++)
8460     {
8461         comm->nat[i] = dd->nat_tot;
8462     }
8463
8464     if (!bBondComm)
8465     {
8466         /* We don't need to update cginfo, since that was alrady done above.
8467          * So we pass NULL for the forcerec.
8468          */
8469         dd_set_cginfo(dd->index_gl, dd->ncg_home, dd->ncg_tot,
8470                       nullptr, comm->bLocalCG);
8471     }
8472
8473     if (debug)
8474     {
8475         fprintf(debug, "Finished setting up DD communication, zones:");
8476         for (c = 0; c < zones->n; c++)
8477         {
8478             fprintf(debug, " %d", zones->cg_range[c+1]-zones->cg_range[c]);
8479         }
8480         fprintf(debug, "\n");
8481     }
8482 }
8483
8484 static void set_cg_boundaries(gmx_domdec_zones_t *zones)
8485 {
8486     int c;
8487
8488     for (c = 0; c < zones->nizone; c++)
8489     {
8490         zones->izone[c].cg1  = zones->cg_range[c+1];
8491         zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0];
8492         zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1];
8493     }
8494 }
8495
8496 /* \brief Set zone dimensions for zones \p zone_start to \p zone_end-1
8497  *
8498  * Also sets the atom density for the home zone when \p zone_start=0.
8499  * For this \p numMovedChargeGroupsInHomeZone needs to be passed to tell
8500  * how many charge groups will move but are still part of the current range.
8501  * \todo When converting domdec to use proper classes, all these variables
8502  *       should be private and a method should return the correct count
8503  *       depending on an internal state.
8504  *
8505  * \param[in,out] dd          The domain decomposition struct
8506  * \param[in]     box         The box
8507  * \param[in]     ddbox       The domain decomposition box struct
8508  * \param[in]     zone_start  The start of the zone range to set sizes for
8509  * \param[in]     zone_end    The end of the zone range to set sizes for
8510  * \param[in]     numMovedChargeGroupsInHomeZone  The number of charge groups in the home zone that should moved but are still present in dd->comm->zones.cg_range
8511  */
8512 static void set_zones_size(gmx_domdec_t *dd,
8513                            matrix box, const gmx_ddbox_t *ddbox,
8514                            int zone_start, int zone_end,
8515                            int numMovedChargeGroupsInHomeZone)
8516 {
8517     gmx_domdec_comm_t  *comm;
8518     gmx_domdec_zones_t *zones;
8519     gmx_bool            bDistMB;
8520     int                 z, zi, d, dim;
8521     real                rcs, rcmbs;
8522     int                 i, j;
8523     real                vol;
8524
8525     comm = dd->comm;
8526
8527     zones = &comm->zones;
8528
8529     /* Do we need to determine extra distances for multi-body bondeds? */
8530     bDistMB = (comm->bInterCGMultiBody && isDlbOn(dd->comm) && dd->ndim > 1);
8531
8532     for (z = zone_start; z < zone_end; z++)
8533     {
8534         /* Copy cell limits to zone limits.
8535          * Valid for non-DD dims and non-shifted dims.
8536          */
8537         copy_rvec(comm->cell_x0, zones->size[z].x0);
8538         copy_rvec(comm->cell_x1, zones->size[z].x1);
8539     }
8540
8541     for (d = 0; d < dd->ndim; d++)
8542     {
8543         dim = dd->dim[d];
8544
8545         for (z = 0; z < zones->n; z++)
8546         {
8547             /* With a staggered grid we have different sizes
8548              * for non-shifted dimensions.
8549              */
8550             if (isDlbOn(dd->comm) && zones->shift[z][dim] == 0)
8551             {
8552                 if (d == 1)
8553                 {
8554                     zones->size[z].x0[dim] = comm->zone_d1[zones->shift[z][dd->dim[d-1]]].min0;
8555                     zones->size[z].x1[dim] = comm->zone_d1[zones->shift[z][dd->dim[d-1]]].max1;
8556                 }
8557                 else if (d == 2)
8558                 {
8559                     zones->size[z].x0[dim] = comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].min0;
8560                     zones->size[z].x1[dim] = comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].max1;
8561                 }
8562             }
8563         }
8564
8565         rcs   = comm->cutoff;
8566         rcmbs = comm->cutoff_mbody;
8567         if (ddbox->tric_dir[dim])
8568         {
8569             rcs   /= ddbox->skew_fac[dim];
8570             rcmbs /= ddbox->skew_fac[dim];
8571         }
8572
8573         /* Set the lower limit for the shifted zone dimensions */
8574         for (z = zone_start; z < zone_end; z++)
8575         {
8576             if (zones->shift[z][dim] > 0)
8577             {
8578                 dim = dd->dim[d];
8579                 if (!isDlbOn(dd->comm) || d == 0)
8580                 {
8581                     zones->size[z].x0[dim] = comm->cell_x1[dim];
8582                     zones->size[z].x1[dim] = comm->cell_x1[dim] + rcs;
8583                 }
8584                 else
8585                 {
8586                     /* Here we take the lower limit of the zone from
8587                      * the lowest domain of the zone below.
8588                      */
8589                     if (z < 4)
8590                     {
8591                         zones->size[z].x0[dim] =
8592                             comm->zone_d1[zones->shift[z][dd->dim[d-1]]].min1;
8593                     }
8594                     else
8595                     {
8596                         if (d == 1)
8597                         {
8598                             zones->size[z].x0[dim] =
8599                                 zones->size[zone_perm[2][z-4]].x0[dim];
8600                         }
8601                         else
8602                         {
8603                             zones->size[z].x0[dim] =
8604                                 comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].min1;
8605                         }
8606                     }
8607                     /* A temporary limit, is updated below */
8608                     zones->size[z].x1[dim] = zones->size[z].x0[dim];
8609
8610                     if (bDistMB)
8611                     {
8612                         for (zi = 0; zi < zones->nizone; zi++)
8613                         {
8614                             if (zones->shift[zi][dim] == 0)
8615                             {
8616                                 /* This takes the whole zone into account.
8617                                  * With multiple pulses this will lead
8618                                  * to a larger zone then strictly necessary.
8619                                  */
8620                                 zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim],
8621                                                                   zones->size[zi].x1[dim]+rcmbs);
8622                             }
8623                         }
8624                     }
8625                 }
8626             }
8627         }
8628
8629         /* Loop over the i-zones to set the upper limit of each
8630          * j-zone they see.
8631          */
8632         for (zi = 0; zi < zones->nizone; zi++)
8633         {
8634             if (zones->shift[zi][dim] == 0)
8635             {
8636                 for (z = zones->izone[zi].j0; z < zones->izone[zi].j1; z++)
8637                 {
8638                     if (zones->shift[z][dim] > 0)
8639                     {
8640                         zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim],
8641                                                           zones->size[zi].x1[dim]+rcs);
8642                     }
8643                 }
8644             }
8645         }
8646     }
8647
8648     for (z = zone_start; z < zone_end; z++)
8649     {
8650         /* Initialization only required to keep the compiler happy */
8651         rvec corner_min = {0, 0, 0}, corner_max = {0, 0, 0}, corner;
8652         int  nc, c;
8653
8654         /* To determine the bounding box for a zone we need to find
8655          * the extreme corners of 4, 2 or 1 corners.
8656          */
8657         nc = 1 << (ddbox->nboundeddim - 1);
8658
8659         for (c = 0; c < nc; c++)
8660         {
8661             /* Set up a zone corner at x=0, ignoring trilinic couplings */
8662             corner[XX] = 0;
8663             if ((c & 1) == 0)
8664             {
8665                 corner[YY] = zones->size[z].x0[YY];
8666             }
8667             else
8668             {
8669                 corner[YY] = zones->size[z].x1[YY];
8670             }
8671             if ((c & 2) == 0)
8672             {
8673                 corner[ZZ] = zones->size[z].x0[ZZ];
8674             }
8675             else
8676             {
8677                 corner[ZZ] = zones->size[z].x1[ZZ];
8678             }
8679             if (dd->ndim == 1 && dd->dim[0] < ZZ && ZZ < dd->npbcdim &&
8680                 box[ZZ][1 - dd->dim[0]] != 0)
8681             {
8682                 /* With 1D domain decomposition the cg's are not in
8683                  * the triclinic box, but triclinic x-y and rectangular y/x-z.
8684                  * Shift the corner of the z-vector back to along the box
8685                  * vector of dimension d, so it will later end up at 0 along d.
8686                  * This can affect the location of this corner along dd->dim[0]
8687                  * through the matrix operation below if box[d][dd->dim[0]]!=0.
8688                  */
8689                 int d = 1 - dd->dim[0];
8690
8691                 corner[d] -= corner[ZZ]*box[ZZ][d]/box[ZZ][ZZ];
8692             }
8693             /* Apply the triclinic couplings */
8694             assert(ddbox->npbcdim <= DIM);
8695             for (i = YY; i < ddbox->npbcdim; i++)
8696             {
8697                 for (j = XX; j < i; j++)
8698                 {
8699                     corner[j] += corner[i]*box[i][j]/box[i][i];
8700                 }
8701             }
8702             if (c == 0)
8703             {
8704                 copy_rvec(corner, corner_min);
8705                 copy_rvec(corner, corner_max);
8706             }
8707             else
8708             {
8709                 for (i = 0; i < DIM; i++)
8710                 {
8711                     corner_min[i] = std::min(corner_min[i], corner[i]);
8712                     corner_max[i] = std::max(corner_max[i], corner[i]);
8713                 }
8714             }
8715         }
8716         /* Copy the extreme cornes without offset along x */
8717         for (i = 0; i < DIM; i++)
8718         {
8719             zones->size[z].bb_x0[i] = corner_min[i];
8720             zones->size[z].bb_x1[i] = corner_max[i];
8721         }
8722         /* Add the offset along x */
8723         zones->size[z].bb_x0[XX] += zones->size[z].x0[XX];
8724         zones->size[z].bb_x1[XX] += zones->size[z].x1[XX];
8725     }
8726
8727     if (zone_start == 0)
8728     {
8729         vol = 1;
8730         for (dim = 0; dim < DIM; dim++)
8731         {
8732             vol *= zones->size[0].x1[dim] - zones->size[0].x0[dim];
8733         }
8734         zones->dens_zone0 = (zones->cg_range[1] - zones->cg_range[0] - numMovedChargeGroupsInHomeZone)/vol;
8735     }
8736
8737     if (debug)
8738     {
8739         for (z = zone_start; z < zone_end; z++)
8740         {
8741             fprintf(debug, "zone %d    %6.3f - %6.3f  %6.3f - %6.3f  %6.3f - %6.3f\n",
8742                     z,
8743                     zones->size[z].x0[XX], zones->size[z].x1[XX],
8744                     zones->size[z].x0[YY], zones->size[z].x1[YY],
8745                     zones->size[z].x0[ZZ], zones->size[z].x1[ZZ]);
8746             fprintf(debug, "zone %d bb %6.3f - %6.3f  %6.3f - %6.3f  %6.3f - %6.3f\n",
8747                     z,
8748                     zones->size[z].bb_x0[XX], zones->size[z].bb_x1[XX],
8749                     zones->size[z].bb_x0[YY], zones->size[z].bb_x1[YY],
8750                     zones->size[z].bb_x0[ZZ], zones->size[z].bb_x1[ZZ]);
8751         }
8752     }
8753 }
8754
8755 static int comp_cgsort(const void *a, const void *b)
8756 {
8757     int           comp;
8758
8759     gmx_cgsort_t *cga, *cgb;
8760     cga = (gmx_cgsort_t *)a;
8761     cgb = (gmx_cgsort_t *)b;
8762
8763     comp = cga->nsc - cgb->nsc;
8764     if (comp == 0)
8765     {
8766         comp = cga->ind_gl - cgb->ind_gl;
8767     }
8768
8769     return comp;
8770 }
8771
8772 static void order_int_cg(int n, const gmx_cgsort_t *sort,
8773                          int *a, int *buf)
8774 {
8775     int i;
8776
8777     /* Order the data */
8778     for (i = 0; i < n; i++)
8779     {
8780         buf[i] = a[sort[i].ind];
8781     }
8782
8783     /* Copy back to the original array */
8784     for (i = 0; i < n; i++)
8785     {
8786         a[i] = buf[i];
8787     }
8788 }
8789
8790 static void order_vec_cg(int n, const gmx_cgsort_t *sort,
8791                          rvec *v, rvec *buf)
8792 {
8793     int i;
8794
8795     /* Order the data */
8796     for (i = 0; i < n; i++)
8797     {
8798         copy_rvec(v[sort[i].ind], buf[i]);
8799     }
8800
8801     /* Copy back to the original array */
8802     for (i = 0; i < n; i++)
8803     {
8804         copy_rvec(buf[i], v[i]);
8805     }
8806 }
8807
8808 static void order_vec_atom(int ncg, const int *cgindex, const gmx_cgsort_t *sort,
8809                            rvec *v, rvec *buf)
8810 {
8811     int a, atot, cg, cg0, cg1, i;
8812
8813     if (cgindex == nullptr)
8814     {
8815         /* Avoid the useless loop of the atoms within a cg */
8816         order_vec_cg(ncg, sort, v, buf);
8817
8818         return;
8819     }
8820
8821     /* Order the data */
8822     a = 0;
8823     for (cg = 0; cg < ncg; cg++)
8824     {
8825         cg0 = cgindex[sort[cg].ind];
8826         cg1 = cgindex[sort[cg].ind+1];
8827         for (i = cg0; i < cg1; i++)
8828         {
8829             copy_rvec(v[i], buf[a]);
8830             a++;
8831         }
8832     }
8833     atot = a;
8834
8835     /* Copy back to the original array */
8836     for (a = 0; a < atot; a++)
8837     {
8838         copy_rvec(buf[a], v[a]);
8839     }
8840 }
8841
8842 static void ordered_sort(int nsort2, gmx_cgsort_t *sort2,
8843                          int nsort_new, gmx_cgsort_t *sort_new,
8844                          gmx_cgsort_t *sort1)
8845 {
8846     int i1, i2, i_new;
8847
8848     /* The new indices are not very ordered, so we qsort them */
8849     gmx_qsort_threadsafe(sort_new, nsort_new, sizeof(sort_new[0]), comp_cgsort);
8850
8851     /* sort2 is already ordered, so now we can merge the two arrays */
8852     i1    = 0;
8853     i2    = 0;
8854     i_new = 0;
8855     while (i2 < nsort2 || i_new < nsort_new)
8856     {
8857         if (i2 == nsort2)
8858         {
8859             sort1[i1++] = sort_new[i_new++];
8860         }
8861         else if (i_new == nsort_new)
8862         {
8863             sort1[i1++] = sort2[i2++];
8864         }
8865         else if (sort2[i2].nsc < sort_new[i_new].nsc ||
8866                  (sort2[i2].nsc == sort_new[i_new].nsc &&
8867                   sort2[i2].ind_gl < sort_new[i_new].ind_gl))
8868         {
8869             sort1[i1++] = sort2[i2++];
8870         }
8871         else
8872         {
8873             sort1[i1++] = sort_new[i_new++];
8874         }
8875     }
8876 }
8877
8878 static int dd_sort_order(gmx_domdec_t *dd, t_forcerec *fr, int ncg_home_old)
8879 {
8880     gmx_domdec_sort_t *sort;
8881     gmx_cgsort_t      *cgsort, *sort_i;
8882     int                ncg_new, nsort2, nsort_new, i, *a, moved;
8883
8884     sort = dd->comm->sort;
8885
8886     a = fr->ns->grid->cell_index;
8887
8888     moved = NSGRID_SIGNAL_MOVED_FAC*fr->ns->grid->ncells;
8889
8890     if (ncg_home_old >= 0)
8891     {
8892         /* The charge groups that remained in the same ns grid cell
8893          * are completely ordered. So we can sort efficiently by sorting
8894          * the charge groups that did move into the stationary list.
8895          */
8896         ncg_new   = 0;
8897         nsort2    = 0;
8898         nsort_new = 0;
8899         for (i = 0; i < dd->ncg_home; i++)
8900         {
8901             /* Check if this cg did not move to another node */
8902             if (a[i] < moved)
8903             {
8904                 if (i >= ncg_home_old || a[i] != sort->sort[i].nsc)
8905                 {
8906                     /* This cg is new on this node or moved ns grid cell */
8907                     if (nsort_new >= sort->sort_new_nalloc)
8908                     {
8909                         sort->sort_new_nalloc = over_alloc_dd(nsort_new+1);
8910                         srenew(sort->sort_new, sort->sort_new_nalloc);
8911                     }
8912                     sort_i = &(sort->sort_new[nsort_new++]);
8913                 }
8914                 else
8915                 {
8916                     /* This cg did not move */
8917                     sort_i = &(sort->sort2[nsort2++]);
8918                 }
8919                 /* Sort on the ns grid cell indices
8920                  * and the global topology index.
8921                  * index_gl is irrelevant with cell ns,
8922                  * but we set it here anyhow to avoid a conditional.
8923                  */
8924                 sort_i->nsc    = a[i];
8925                 sort_i->ind_gl = dd->index_gl[i];
8926                 sort_i->ind    = i;
8927                 ncg_new++;
8928             }
8929         }
8930         if (debug)
8931         {
8932             fprintf(debug, "ordered sort cgs: stationary %d moved %d\n",
8933                     nsort2, nsort_new);
8934         }
8935         /* Sort efficiently */
8936         ordered_sort(nsort2, sort->sort2, nsort_new, sort->sort_new,
8937                      sort->sort);
8938     }
8939     else
8940     {
8941         cgsort  = sort->sort;
8942         ncg_new = 0;
8943         for (i = 0; i < dd->ncg_home; i++)
8944         {
8945             /* Sort on the ns grid cell indices
8946              * and the global topology index
8947              */
8948             cgsort[i].nsc    = a[i];
8949             cgsort[i].ind_gl = dd->index_gl[i];
8950             cgsort[i].ind    = i;
8951             if (cgsort[i].nsc < moved)
8952             {
8953                 ncg_new++;
8954             }
8955         }
8956         if (debug)
8957         {
8958             fprintf(debug, "qsort cgs: %d new home %d\n", dd->ncg_home, ncg_new);
8959         }
8960         /* Determine the order of the charge groups using qsort */
8961         gmx_qsort_threadsafe(cgsort, dd->ncg_home, sizeof(cgsort[0]), comp_cgsort);
8962     }
8963
8964     return ncg_new;
8965 }
8966
8967 static int dd_sort_order_nbnxn(gmx_domdec_t *dd, t_forcerec *fr)
8968 {
8969     gmx_cgsort_t *sort;
8970     int           ncg_new, i, na;
8971     const int    *a;
8972
8973     sort = dd->comm->sort->sort;
8974
8975     nbnxn_get_atomorder(fr->nbv->nbs, &a, &na);
8976
8977     ncg_new = 0;
8978     for (i = 0; i < na; i++)
8979     {
8980         if (a[i] >= 0)
8981         {
8982             sort[ncg_new].ind = a[i];
8983             ncg_new++;
8984         }
8985     }
8986
8987     return ncg_new;
8988 }
8989
8990 static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state *state,
8991                           int ncg_home_old)
8992 {
8993     gmx_domdec_sort_t *sort;
8994     gmx_cgsort_t      *cgsort;
8995     int               *cgindex;
8996     int                ncg_new, i, *ibuf, cgsize;
8997     rvec              *vbuf;
8998
8999     sort = dd->comm->sort;
9000
9001     if (dd->ncg_home > sort->sort_nalloc)
9002     {
9003         sort->sort_nalloc = over_alloc_dd(dd->ncg_home);
9004         srenew(sort->sort, sort->sort_nalloc);
9005         srenew(sort->sort2, sort->sort_nalloc);
9006     }
9007     cgsort = sort->sort;
9008
9009     switch (fr->cutoff_scheme)
9010     {
9011         case ecutsGROUP:
9012             ncg_new = dd_sort_order(dd, fr, ncg_home_old);
9013             break;
9014         case ecutsVERLET:
9015             ncg_new = dd_sort_order_nbnxn(dd, fr);
9016             break;
9017         default:
9018             gmx_incons("unimplemented");
9019             ncg_new = 0;
9020     }
9021
9022     /* We alloc with the old size, since cgindex is still old */
9023     vec_rvec_check_alloc(&dd->comm->vbuf, dd->cgindex[dd->ncg_home]);
9024     vbuf = dd->comm->vbuf.v;
9025
9026     if (dd->comm->bCGs)
9027     {
9028         cgindex = dd->cgindex;
9029     }
9030     else
9031     {
9032         cgindex = nullptr;
9033     }
9034
9035     /* Remove the charge groups which are no longer at home here */
9036     dd->ncg_home = ncg_new;
9037     if (debug)
9038     {
9039         fprintf(debug, "Set the new home charge group count to %d\n",
9040                 dd->ncg_home);
9041     }
9042
9043     /* Reorder the state */
9044     if (state->flags & (1 << estX))
9045     {
9046         order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->x.data()), vbuf);
9047     }
9048     if (state->flags & (1 << estV))
9049     {
9050         order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->v.data()), vbuf);
9051     }
9052     if (state->flags & (1 << estCGP))
9053     {
9054         order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->cg_p.data()), vbuf);
9055     }
9056
9057     if (fr->cutoff_scheme == ecutsGROUP)
9058     {
9059         /* Reorder cgcm */
9060         order_vec_cg(dd->ncg_home, cgsort, cgcm, vbuf);
9061     }
9062
9063     if (dd->ncg_home+1 > sort->ibuf_nalloc)
9064     {
9065         sort->ibuf_nalloc = over_alloc_dd(dd->ncg_home+1);
9066         srenew(sort->ibuf, sort->ibuf_nalloc);
9067     }
9068     ibuf = sort->ibuf;
9069     /* Reorder the global cg index */
9070     order_int_cg(dd->ncg_home, cgsort, dd->index_gl, ibuf);
9071     /* Reorder the cginfo */
9072     order_int_cg(dd->ncg_home, cgsort, fr->cginfo, ibuf);
9073     /* Rebuild the local cg index */
9074     if (dd->comm->bCGs)
9075     {
9076         ibuf[0] = 0;
9077         for (i = 0; i < dd->ncg_home; i++)
9078         {
9079             cgsize    = dd->cgindex[cgsort[i].ind+1] - dd->cgindex[cgsort[i].ind];
9080             ibuf[i+1] = ibuf[i] + cgsize;
9081         }
9082         for (i = 0; i < dd->ncg_home+1; i++)
9083         {
9084             dd->cgindex[i] = ibuf[i];
9085         }
9086     }
9087     else
9088     {
9089         for (i = 0; i < dd->ncg_home+1; i++)
9090         {
9091             dd->cgindex[i] = i;
9092         }
9093     }
9094     /* Set the home atom number */
9095     dd->nat_home = dd->cgindex[dd->ncg_home];
9096
9097     if (fr->cutoff_scheme == ecutsVERLET)
9098     {
9099         /* The atoms are now exactly in grid order, update the grid order */
9100         nbnxn_set_atomorder(fr->nbv->nbs);
9101     }
9102     else
9103     {
9104         /* Copy the sorted ns cell indices back to the ns grid struct */
9105         for (i = 0; i < dd->ncg_home; i++)
9106         {
9107             fr->ns->grid->cell_index[i] = cgsort[i].nsc;
9108         }
9109         fr->ns->grid->nr = dd->ncg_home;
9110     }
9111 }
9112
9113 static void add_dd_statistics(gmx_domdec_t *dd)
9114 {
9115     gmx_domdec_comm_t *comm;
9116     int                ddnat;
9117
9118     comm = dd->comm;
9119
9120     for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9121     {
9122         comm->sum_nat[ddnat-ddnatZONE] +=
9123             comm->nat[ddnat] - comm->nat[ddnat-1];
9124     }
9125     comm->ndecomp++;
9126 }
9127
9128 void reset_dd_statistics_counters(gmx_domdec_t *dd)
9129 {
9130     gmx_domdec_comm_t *comm;
9131     int                ddnat;
9132
9133     comm = dd->comm;
9134
9135     /* Reset all the statistics and counters for total run counting */
9136     for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9137     {
9138         comm->sum_nat[ddnat-ddnatZONE] = 0;
9139     }
9140     comm->ndecomp   = 0;
9141     comm->nload     = 0;
9142     comm->load_step = 0;
9143     comm->load_sum  = 0;
9144     comm->load_max  = 0;
9145     clear_ivec(comm->load_lim);
9146     comm->load_mdf = 0;
9147     comm->load_pme = 0;
9148 }
9149
9150 void print_dd_statistics(t_commrec *cr, const t_inputrec *ir, FILE *fplog)
9151 {
9152     gmx_domdec_comm_t *comm;
9153     int                ddnat;
9154     double             av;
9155
9156     comm = cr->dd->comm;
9157
9158     gmx_sumd(ddnatNR-ddnatZONE, comm->sum_nat, cr);
9159
9160     if (fplog == nullptr)
9161     {
9162         return;
9163     }
9164
9165     fprintf(fplog, "\n    D O M A I N   D E C O M P O S I T I O N   S T A T I S T I C S\n\n");
9166
9167     for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9168     {
9169         av = comm->sum_nat[ddnat-ddnatZONE]/comm->ndecomp;
9170         switch (ddnat)
9171         {
9172             case ddnatZONE:
9173                 fprintf(fplog,
9174                         " av. #atoms communicated per step for force:  %d x %.1f\n",
9175                         2, av);
9176                 break;
9177             case ddnatVSITE:
9178                 if (cr->dd->vsite_comm)
9179                 {
9180                     fprintf(fplog,
9181                             " av. #atoms communicated per step for vsites: %d x %.1f\n",
9182                             (EEL_PME(ir->coulombtype) || ir->coulombtype == eelEWALD) ? 3 : 2,
9183                             av);
9184                 }
9185                 break;
9186             case ddnatCON:
9187                 if (cr->dd->constraint_comm)
9188                 {
9189                     fprintf(fplog,
9190                             " av. #atoms communicated per step for LINCS:  %d x %.1f\n",
9191                             1 + ir->nLincsIter, av);
9192                 }
9193                 break;
9194             default:
9195                 gmx_incons(" Unknown type for DD statistics");
9196         }
9197     }
9198     fprintf(fplog, "\n");
9199
9200     if (comm->bRecordLoad && EI_DYNAMICS(ir->eI))
9201     {
9202         print_dd_load_av(fplog, cr->dd);
9203     }
9204 }
9205
9206 void dd_partition_system(FILE                *fplog,
9207                          gmx_int64_t          step,
9208                          t_commrec           *cr,
9209                          gmx_bool             bMasterState,
9210                          int                  nstglobalcomm,
9211                          t_state             *state_global,
9212                          const gmx_mtop_t    *top_global,
9213                          const t_inputrec    *ir,
9214                          t_state             *state_local,
9215                          PaddedRVecVector    *f,
9216                          gmx::MDAtoms        *mdAtoms,
9217                          gmx_localtop_t      *top_local,
9218                          t_forcerec          *fr,
9219                          gmx_vsite_t         *vsite,
9220                          gmx_constr_t         constr,
9221                          t_nrnb              *nrnb,
9222                          gmx_wallcycle_t      wcycle,
9223                          gmx_bool             bVerbose)
9224 {
9225     gmx_domdec_t      *dd;
9226     gmx_domdec_comm_t *comm;
9227     gmx_ddbox_t        ddbox = {0};
9228     t_block           *cgs_gl;
9229     gmx_int64_t        step_pcoupl;
9230     rvec               cell_ns_x0, cell_ns_x1;
9231     int                i, n, ncgindex_set, ncg_home_old = -1, ncg_moved, nat_f_novirsum;
9232     gmx_bool           bBoxChanged, bNStGlobalComm, bDoDLB, bCheckWhetherToTurnDlbOn, bLogLoad;
9233     gmx_bool           bRedist, bSortCG, bResortAll;
9234     ivec               ncells_old = {0, 0, 0}, ncells_new = {0, 0, 0}, np;
9235     real               grid_density;
9236     char               sbuf[22];
9237
9238     wallcycle_start(wcycle, ewcDOMDEC);
9239
9240     dd   = cr->dd;
9241     comm = dd->comm;
9242
9243     bBoxChanged = (bMasterState || inputrecDeform(ir));
9244     if (ir->epc != epcNO)
9245     {
9246         /* With nstpcouple > 1 pressure coupling happens.
9247          * one step after calculating the pressure.
9248          * Box scaling happens at the end of the MD step,
9249          * after the DD partitioning.
9250          * We therefore have to do DLB in the first partitioning
9251          * after an MD step where P-coupling occurred.
9252          * We need to determine the last step in which p-coupling occurred.
9253          * MRS -- need to validate this for vv?
9254          */
9255         n = ir->nstpcouple;
9256         if (n == 1)
9257         {
9258             step_pcoupl = step - 1;
9259         }
9260         else
9261         {
9262             step_pcoupl = ((step - 1)/n)*n + 1;
9263         }
9264         if (step_pcoupl >= comm->partition_step)
9265         {
9266             bBoxChanged = TRUE;
9267         }
9268     }
9269
9270     bNStGlobalComm = (step % nstglobalcomm == 0);
9271
9272     if (!isDlbOn(comm))
9273     {
9274         bDoDLB = FALSE;
9275     }
9276     else
9277     {
9278         /* Should we do dynamic load balacing this step?
9279          * Since it requires (possibly expensive) global communication,
9280          * we might want to do DLB less frequently.
9281          */
9282         if (bBoxChanged || ir->epc != epcNO)
9283         {
9284             bDoDLB = bBoxChanged;
9285         }
9286         else
9287         {
9288             bDoDLB = bNStGlobalComm;
9289         }
9290     }
9291
9292     /* Check if we have recorded loads on the nodes */
9293     if (comm->bRecordLoad && dd_load_count(comm) > 0)
9294     {
9295         bCheckWhetherToTurnDlbOn = dd_dlb_get_should_check_whether_to_turn_dlb_on(dd);
9296
9297         /* Print load every nstlog, first and last step to the log file */
9298         bLogLoad = ((ir->nstlog > 0 && step % ir->nstlog == 0) ||
9299                     comm->n_load_collect == 0 ||
9300                     (ir->nsteps >= 0 &&
9301                      (step + ir->nstlist > ir->init_step + ir->nsteps)));
9302
9303         /* Avoid extra communication due to verbose screen output
9304          * when nstglobalcomm is set.
9305          */
9306         if (bDoDLB || bLogLoad || bCheckWhetherToTurnDlbOn ||
9307             (bVerbose && (ir->nstlist == 0 || nstglobalcomm <= ir->nstlist)))
9308         {
9309             get_load_distribution(dd, wcycle);
9310             if (DDMASTER(dd))
9311             {
9312                 if (bLogLoad)
9313                 {
9314                     dd_print_load(fplog, dd, step-1);
9315                 }
9316                 if (bVerbose)
9317                 {
9318                     dd_print_load_verbose(dd);
9319                 }
9320             }
9321             comm->n_load_collect++;
9322
9323             if (isDlbOn(comm))
9324             {
9325                 if (DDMASTER(dd))
9326                 {
9327                     /* Add the measured cycles to the running average */
9328                     const float averageFactor        = 0.1f;
9329                     comm->cyclesPerStepDlbExpAverage =
9330                         (1 - averageFactor)*comm->cyclesPerStepDlbExpAverage +
9331                         averageFactor*comm->cycl[ddCyclStep]/comm->cycl_n[ddCyclStep];
9332                 }
9333                 if (comm->dlbState == edlbsOnCanTurnOff &&
9334                     dd->comm->n_load_have % c_checkTurnDlbOffInterval == c_checkTurnDlbOffInterval - 1)
9335                 {
9336                     gmx_bool turnOffDlb;
9337                     if (DDMASTER(dd))
9338                     {
9339                         /* If the running averaged cycles with DLB are more
9340                          * than before we turned on DLB, turn off DLB.
9341                          * We will again run and check the cycles without DLB
9342                          * and we can then decide if to turn off DLB forever.
9343                          */
9344                         turnOffDlb = (comm->cyclesPerStepDlbExpAverage >
9345                                       comm->cyclesPerStepBeforeDLB);
9346                     }
9347                     dd_bcast(dd, sizeof(turnOffDlb), &turnOffDlb);
9348                     if (turnOffDlb)
9349                     {
9350                         /* To turn off DLB, we need to redistribute the atoms */
9351                         dd_collect_state(dd, state_local, state_global);
9352                         bMasterState = TRUE;
9353                         turn_off_dlb(fplog, cr, step);
9354                     }
9355                 }
9356             }
9357             else if (bCheckWhetherToTurnDlbOn)
9358             {
9359                 gmx_bool turnOffDlbForever = FALSE;
9360                 gmx_bool turnOnDlb         = FALSE;
9361
9362                 /* Since the timings are node dependent, the master decides */
9363                 if (DDMASTER(dd))
9364                 {
9365                     /* If we recently turned off DLB, we want to check if
9366                      * performance is better without DLB. We want to do this
9367                      * ASAP to minimize the chance that external factors
9368                      * slowed down the DLB step are gone here and we
9369                      * incorrectly conclude that DLB was causing the slowdown.
9370                      * So we measure one nstlist block, no running average.
9371                      */
9372                     if (comm->haveTurnedOffDlb &&
9373                         comm->cycl[ddCyclStep]/comm->cycl_n[ddCyclStep] <
9374                         comm->cyclesPerStepDlbExpAverage)
9375                     {
9376                         /* After turning off DLB we ran nstlist steps in fewer
9377                          * cycles than with DLB. This likely means that DLB
9378                          * in not benefical, but this could be due to a one
9379                          * time unlucky fluctuation, so we require two such
9380                          * observations in close succession to turn off DLB
9381                          * forever.
9382                          */
9383                         if (comm->dlbSlowerPartitioningCount > 0 &&
9384                             dd->ddp_count < comm->dlbSlowerPartitioningCount + 10*c_checkTurnDlbOnInterval)
9385                         {
9386                             turnOffDlbForever = TRUE;
9387                         }
9388                         comm->haveTurnedOffDlb           = false;
9389                         /* Register when we last measured DLB slowdown */
9390                         comm->dlbSlowerPartitioningCount = dd->ddp_count;
9391                     }
9392                     else
9393                     {
9394                         /* Here we check if the max PME rank load is more than 0.98
9395                          * the max PP force load. If so, PP DLB will not help,
9396                          * since we are (almost) limited by PME. Furthermore,
9397                          * DLB will cause a significant extra x/f redistribution
9398                          * cost on the PME ranks, which will then surely result
9399                          * in lower total performance.
9400                          */
9401                         if (cr->npmenodes > 0 &&
9402                             dd_pme_f_ratio(dd) > 1 - DD_PERF_LOSS_DLB_ON)
9403                         {
9404                             turnOnDlb = FALSE;
9405                         }
9406                         else
9407                         {
9408                             turnOnDlb = (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS_DLB_ON);
9409                         }
9410                     }
9411                 }
9412                 struct
9413                 {
9414                     gmx_bool turnOffDlbForever;
9415                     gmx_bool turnOnDlb;
9416                 }
9417                 bools {
9418                     turnOffDlbForever, turnOnDlb
9419                 };
9420                 dd_bcast(dd, sizeof(bools), &bools);
9421                 if (bools.turnOffDlbForever)
9422                 {
9423                     turn_off_dlb_forever(fplog, cr, step);
9424                 }
9425                 else if (bools.turnOnDlb)
9426                 {
9427                     turn_on_dlb(fplog, cr, step);
9428                     bDoDLB = TRUE;
9429                 }
9430             }
9431         }
9432         comm->n_load_have++;
9433     }
9434
9435     cgs_gl = &comm->cgs_gl;
9436
9437     bRedist = FALSE;
9438     if (bMasterState)
9439     {
9440         /* Clear the old state */
9441         clear_dd_indices(dd, 0, 0);
9442         ncgindex_set = 0;
9443
9444         rvec *xGlobal = (SIMMASTER(cr) ? as_rvec_array(state_global->x.data()) : nullptr);
9445
9446         set_ddbox(dd, bMasterState, cr, ir,
9447                   SIMMASTER(cr) ? state_global->box : nullptr,
9448                   TRUE, cgs_gl, xGlobal,
9449                   &ddbox);
9450
9451         get_cg_distribution(fplog, dd, cgs_gl,
9452                             SIMMASTER(cr) ? state_global->box : nullptr,
9453                             &ddbox, xGlobal);
9454
9455         dd_distribute_state(dd, cgs_gl,
9456                             state_global, state_local, f);
9457
9458         dd_make_local_cgs(dd, &top_local->cgs);
9459
9460         /* Ensure that we have space for the new distribution */
9461         dd_check_alloc_ncg(fr, state_local, f, dd->ncg_home);
9462
9463         if (fr->cutoff_scheme == ecutsGROUP)
9464         {
9465             calc_cgcm(fplog, 0, dd->ncg_home,
9466                       &top_local->cgs, as_rvec_array(state_local->x.data()), fr->cg_cm);
9467         }
9468
9469         inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
9470
9471         dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
9472     }
9473     else if (state_local->ddp_count != dd->ddp_count)
9474     {
9475         if (state_local->ddp_count > dd->ddp_count)
9476         {
9477             gmx_fatal(FARGS, "Internal inconsistency state_local->ddp_count (%d) > dd->ddp_count (%d)", state_local->ddp_count, dd->ddp_count);
9478         }
9479
9480         if (state_local->ddp_count_cg_gl != state_local->ddp_count)
9481         {
9482             gmx_fatal(FARGS, "Internal inconsistency state_local->ddp_count_cg_gl (%d) != state_local->ddp_count (%d)", state_local->ddp_count_cg_gl, state_local->ddp_count);
9483         }
9484
9485         /* Clear the old state */
9486         clear_dd_indices(dd, 0, 0);
9487
9488         /* Build the new indices */
9489         rebuild_cgindex(dd, cgs_gl->index, state_local);
9490         make_dd_indices(dd, cgs_gl->index, 0);
9491         ncgindex_set = dd->ncg_home;
9492
9493         if (fr->cutoff_scheme == ecutsGROUP)
9494         {
9495             /* Redetermine the cg COMs */
9496             calc_cgcm(fplog, 0, dd->ncg_home,
9497                       &top_local->cgs, as_rvec_array(state_local->x.data()), fr->cg_cm);
9498         }
9499
9500         inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
9501
9502         dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
9503
9504         set_ddbox(dd, bMasterState, cr, ir, state_local->box,
9505                   TRUE, &top_local->cgs, as_rvec_array(state_local->x.data()), &ddbox);
9506
9507         bRedist = isDlbOn(comm);
9508     }
9509     else
9510     {
9511         /* We have the full state, only redistribute the cgs */
9512
9513         /* Clear the non-home indices */
9514         clear_dd_indices(dd, dd->ncg_home, dd->nat_home);
9515         ncgindex_set = 0;
9516
9517         /* Avoid global communication for dim's without pbc and -gcom */
9518         if (!bNStGlobalComm)
9519         {
9520             copy_rvec(comm->box0, ddbox.box0    );
9521             copy_rvec(comm->box_size, ddbox.box_size);
9522         }
9523         set_ddbox(dd, bMasterState, cr, ir, state_local->box,
9524                   bNStGlobalComm, &top_local->cgs, as_rvec_array(state_local->x.data()), &ddbox);
9525
9526         bBoxChanged = TRUE;
9527         bRedist     = TRUE;
9528     }
9529     /* For dim's without pbc and -gcom */
9530     copy_rvec(ddbox.box0, comm->box0    );
9531     copy_rvec(ddbox.box_size, comm->box_size);
9532
9533     set_dd_cell_sizes(dd, &ddbox, dynamic_dd_box(&ddbox, ir), bMasterState, bDoDLB,
9534                       step, wcycle);
9535
9536     if (comm->nstDDDumpGrid > 0 && step % comm->nstDDDumpGrid == 0)
9537     {
9538         write_dd_grid_pdb("dd_grid", step, dd, state_local->box, &ddbox);
9539     }
9540
9541     /* Check if we should sort the charge groups */
9542     bSortCG = (bMasterState || bRedist);
9543
9544     ncg_home_old = dd->ncg_home;
9545
9546     /* When repartitioning we mark charge groups that will move to neighboring
9547      * DD cells, but we do not move them right away for performance reasons.
9548      * Thus we need to keep track of how many charge groups will move for
9549      * obtaining correct local charge group / atom counts.
9550      */
9551     ncg_moved = 0;
9552     if (bRedist)
9553     {
9554         wallcycle_sub_start(wcycle, ewcsDD_REDIST);
9555
9556         dd_redistribute_cg(fplog, step, dd, ddbox.tric_dir,
9557                            state_local, f, fr,
9558                            !bSortCG, nrnb, &ncgindex_set, &ncg_moved);
9559
9560         wallcycle_sub_stop(wcycle, ewcsDD_REDIST);
9561     }
9562
9563     get_nsgrid_boundaries(ddbox.nboundeddim, state_local->box,
9564                           dd, &ddbox,
9565                           &comm->cell_x0, &comm->cell_x1,
9566                           dd->ncg_home, fr->cg_cm,
9567                           cell_ns_x0, cell_ns_x1, &grid_density);
9568
9569     if (bBoxChanged)
9570     {
9571         comm_dd_ns_cell_sizes(dd, &ddbox, cell_ns_x0, cell_ns_x1, step);
9572     }
9573
9574     switch (fr->cutoff_scheme)
9575     {
9576         case ecutsGROUP:
9577             copy_ivec(fr->ns->grid->n, ncells_old);
9578             grid_first(fplog, fr->ns->grid, dd, &ddbox,
9579                        state_local->box, cell_ns_x0, cell_ns_x1,
9580                        fr->rlist, grid_density);
9581             break;
9582         case ecutsVERLET:
9583             nbnxn_get_ncells(fr->nbv->nbs, &ncells_old[XX], &ncells_old[YY]);
9584             break;
9585         default:
9586             gmx_incons("unimplemented");
9587     }
9588     /* We need to store tric_dir for dd_get_ns_ranges called from ns.c */
9589     copy_ivec(ddbox.tric_dir, comm->tric_dir);
9590
9591     if (bSortCG)
9592     {
9593         wallcycle_sub_start(wcycle, ewcsDD_GRID);
9594
9595         /* Sort the state on charge group position.
9596          * This enables exact restarts from this step.
9597          * It also improves performance by about 15% with larger numbers
9598          * of atoms per node.
9599          */
9600
9601         /* Fill the ns grid with the home cell,
9602          * so we can sort with the indices.
9603          */
9604         set_zones_ncg_home(dd);
9605
9606         switch (fr->cutoff_scheme)
9607         {
9608             case ecutsVERLET:
9609                 set_zones_size(dd, state_local->box, &ddbox, 0, 1, ncg_moved);
9610
9611                 nbnxn_put_on_grid(fr->nbv->nbs, fr->ePBC, state_local->box,
9612                                   0,
9613                                   comm->zones.size[0].bb_x0,
9614                                   comm->zones.size[0].bb_x1,
9615                                   0, dd->ncg_home,
9616                                   comm->zones.dens_zone0,
9617                                   fr->cginfo,
9618                                   as_rvec_array(state_local->x.data()),
9619                                   ncg_moved, bRedist ? comm->moved : nullptr,
9620                                   fr->nbv->grp[eintLocal].kernel_type,
9621                                   fr->nbv->nbat);
9622
9623                 nbnxn_get_ncells(fr->nbv->nbs, &ncells_new[XX], &ncells_new[YY]);
9624                 break;
9625             case ecutsGROUP:
9626                 fill_grid(&comm->zones, fr->ns->grid, dd->ncg_home,
9627                           0, dd->ncg_home, fr->cg_cm);
9628
9629                 copy_ivec(fr->ns->grid->n, ncells_new);
9630                 break;
9631             default:
9632                 gmx_incons("unimplemented");
9633         }
9634
9635         bResortAll = bMasterState;
9636
9637         /* Check if we can user the old order and ns grid cell indices
9638          * of the charge groups to sort the charge groups efficiently.
9639          */
9640         if (ncells_new[XX] != ncells_old[XX] ||
9641             ncells_new[YY] != ncells_old[YY] ||
9642             ncells_new[ZZ] != ncells_old[ZZ])
9643         {
9644             bResortAll = TRUE;
9645         }
9646
9647         if (debug)
9648         {
9649             fprintf(debug, "Step %s, sorting the %d home charge groups\n",
9650                     gmx_step_str(step, sbuf), dd->ncg_home);
9651         }
9652         dd_sort_state(dd, fr->cg_cm, fr, state_local,
9653                       bResortAll ? -1 : ncg_home_old);
9654
9655         /* After sorting and compacting we set the correct size */
9656         dd_resize_state(state_local, f, dd->nat_home);
9657
9658         /* Rebuild all the indices */
9659         ga2la_clear(dd->ga2la);
9660         ncgindex_set = 0;
9661
9662         wallcycle_sub_stop(wcycle, ewcsDD_GRID);
9663     }
9664
9665     wallcycle_sub_start(wcycle, ewcsDD_SETUPCOMM);
9666
9667     /* Setup up the communication and communicate the coordinates */
9668     setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local, f);
9669
9670     /* Set the indices */
9671     make_dd_indices(dd, cgs_gl->index, ncgindex_set);
9672
9673     /* Set the charge group boundaries for neighbor searching */
9674     set_cg_boundaries(&comm->zones);
9675
9676     if (fr->cutoff_scheme == ecutsVERLET)
9677     {
9678         set_zones_size(dd, state_local->box, &ddbox,
9679                        bSortCG ? 1 : 0, comm->zones.n,
9680                        0);
9681     }
9682
9683     wallcycle_sub_stop(wcycle, ewcsDD_SETUPCOMM);
9684
9685     /*
9686        write_dd_pdb("dd_home",step,"dump",top_global,cr,
9687                  -1,as_rvec_array(state_local->x.data()),state_local->box);
9688      */
9689
9690     wallcycle_sub_start(wcycle, ewcsDD_MAKETOP);
9691
9692     /* Extract a local topology from the global topology */
9693     for (i = 0; i < dd->ndim; i++)
9694     {
9695         np[dd->dim[i]] = comm->cd[i].np;
9696     }
9697     dd_make_local_top(dd, &comm->zones, dd->npbcdim, state_local->box,
9698                       comm->cellsize_min, np,
9699                       fr,
9700                       fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : as_rvec_array(state_local->x.data()),
9701                       vsite, top_global, top_local);
9702
9703     wallcycle_sub_stop(wcycle, ewcsDD_MAKETOP);
9704
9705     wallcycle_sub_start(wcycle, ewcsDD_MAKECONSTR);
9706
9707     /* Set up the special atom communication */
9708     n = comm->nat[ddnatZONE];
9709     for (i = ddnatZONE+1; i < ddnatNR; i++)
9710     {
9711         switch (i)
9712         {
9713             case ddnatVSITE:
9714                 if (vsite && vsite->n_intercg_vsite)
9715                 {
9716                     n = dd_make_local_vsites(dd, n, top_local->idef.il);
9717                 }
9718                 break;
9719             case ddnatCON:
9720                 if (dd->bInterCGcons || dd->bInterCGsettles)
9721                 {
9722                     /* Only for inter-cg constraints we need special code */
9723                     n = dd_make_local_constraints(dd, n, top_global, fr->cginfo,
9724                                                   constr, ir->nProjOrder,
9725                                                   top_local->idef.il);
9726                 }
9727                 break;
9728             default:
9729                 gmx_incons("Unknown special atom type setup");
9730         }
9731         comm->nat[i] = n;
9732     }
9733
9734     wallcycle_sub_stop(wcycle, ewcsDD_MAKECONSTR);
9735
9736     wallcycle_sub_start(wcycle, ewcsDD_TOPOTHER);
9737
9738     /* Make space for the extra coordinates for virtual site
9739      * or constraint communication.
9740      */
9741     state_local->natoms = comm->nat[ddnatNR-1];
9742
9743     dd_resize_state(state_local, f, state_local->natoms);
9744
9745     if (fr->haveDirectVirialContributions)
9746     {
9747         if (vsite && vsite->n_intercg_vsite)
9748         {
9749             nat_f_novirsum = comm->nat[ddnatVSITE];
9750         }
9751         else
9752         {
9753             if (EEL_FULL(ir->coulombtype) && dd->n_intercg_excl > 0)
9754             {
9755                 nat_f_novirsum = dd->nat_tot;
9756             }
9757             else
9758             {
9759                 nat_f_novirsum = dd->nat_home;
9760             }
9761         }
9762     }
9763     else
9764     {
9765         nat_f_novirsum = 0;
9766     }
9767
9768     /* Set the number of atoms required for the force calculation.
9769      * Forces need to be constrained when doing energy
9770      * minimization. For simple simulations we could avoid some
9771      * allocation, zeroing and copying, but this is probably not worth
9772      * the complications and checking.
9773      */
9774     forcerec_set_ranges(fr, dd->ncg_home, dd->ncg_tot,
9775                         dd->nat_tot, comm->nat[ddnatCON], nat_f_novirsum);
9776
9777     /* Update atom data for mdatoms and several algorithms */
9778     mdAlgorithmsSetupAtomData(cr, ir, top_global, top_local, fr,
9779                               nullptr, mdAtoms, vsite, nullptr);
9780
9781     if (ir->implicit_solvent)
9782     {
9783         make_local_gb(cr, fr->born, ir->gb_algorithm);
9784     }
9785
9786     auto mdatoms = mdAtoms->mdatoms();
9787     if (!thisRankHasDuty(cr, DUTY_PME))
9788     {
9789         /* Send the charges and/or c6/sigmas to our PME only node */
9790         gmx_pme_send_parameters(cr,
9791                                 fr->ic,
9792                                 mdatoms->nChargePerturbed, mdatoms->nTypePerturbed,
9793                                 mdatoms->chargeA, mdatoms->chargeB,
9794                                 mdatoms->sqrt_c6A, mdatoms->sqrt_c6B,
9795                                 mdatoms->sigmaA, mdatoms->sigmaB,
9796                                 dd_pme_maxshift_x(dd), dd_pme_maxshift_y(dd));
9797     }
9798
9799     if (constr)
9800     {
9801         set_constraints(constr, top_local, ir, mdatoms, cr);
9802     }
9803
9804     if (ir->bPull)
9805     {
9806         /* Update the local pull groups */
9807         dd_make_local_pull_groups(cr, ir->pull_work, mdatoms);
9808     }
9809
9810     if (ir->bRot)
9811     {
9812         /* Update the local rotation groups */
9813         dd_make_local_rotation_groups(dd, ir->rot);
9814     }
9815
9816     if (ir->eSwapCoords != eswapNO)
9817     {
9818         /* Update the local groups needed for ion swapping */
9819         dd_make_local_swap_groups(dd, ir->swap);
9820     }
9821
9822     /* Update the local atoms to be communicated via the IMD protocol if bIMD is TRUE. */
9823     dd_make_local_IMD_atoms(ir->bIMD, dd, ir->imd);
9824
9825     add_dd_statistics(dd);
9826
9827     /* Make sure we only count the cycles for this DD partitioning */
9828     clear_dd_cycle_counts(dd);
9829
9830     /* Because the order of the atoms might have changed since
9831      * the last vsite construction, we need to communicate the constructing
9832      * atom coordinates again (for spreading the forces this MD step).
9833      */
9834     dd_move_x_vsites(dd, state_local->box, as_rvec_array(state_local->x.data()));
9835
9836     wallcycle_sub_stop(wcycle, ewcsDD_TOPOTHER);
9837
9838     if (comm->nstDDDump > 0 && step % comm->nstDDDump == 0)
9839     {
9840         dd_move_x(dd, state_local->box, as_rvec_array(state_local->x.data()));
9841         write_dd_pdb("dd_dump", step, "dump", top_global, cr,
9842                      -1, as_rvec_array(state_local->x.data()), state_local->box);
9843     }
9844
9845     /* Store the partitioning step */
9846     comm->partition_step = step;
9847
9848     /* Increase the DD partitioning counter */
9849     dd->ddp_count++;
9850     /* The state currently matches this DD partitioning count, store it */
9851     state_local->ddp_count = dd->ddp_count;
9852     if (bMasterState)
9853     {
9854         /* The DD master node knows the complete cg distribution,
9855          * store the count so we can possibly skip the cg info communication.
9856          */
9857         comm->master_cg_ddp_count = (bSortCG ? 0 : dd->ddp_count);
9858     }
9859
9860     if (comm->DD_debug > 0)
9861     {
9862         /* Set the env var GMX_DD_DEBUG if you suspect corrupted indices */
9863         check_index_consistency(dd, top_global->natoms, ncg_mtop(top_global),
9864                                 "after partitioning");
9865     }
9866
9867     wallcycle_stop(wcycle, ewcDOMDEC);
9868 }