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