Move code to prepare for GPU interface rework
[gromacs.git] / src / gromacs / domdec / domdec.cpp
blob01be44705a77642923247a7d2dd2757e0c86504a
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014, 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.
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.
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.
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.
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.
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.
36 #include "gmxpre.h"
38 #include "domdec.h"
40 #include "config.h"
42 #include <assert.h>
43 #include <limits.h>
44 #include <math.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
49 #include <algorithm>
51 #include "gromacs/domdec/domdec_network.h"
52 #include "gromacs/ewald/pme.h"
53 #include "gromacs/fileio/gmxfio.h"
54 #include "gromacs/fileio/pdbio.h"
55 #include "gromacs/gmxlib/gpu_utils/gpu_utils.h"
56 #include "gromacs/imd/imd.h"
57 #include "gromacs/legacyheaders/chargegroup.h"
58 #include "gromacs/legacyheaders/constr.h"
59 #include "gromacs/legacyheaders/force.h"
60 #include "gromacs/legacyheaders/genborn.h"
61 #include "gromacs/legacyheaders/gmx_ga2la.h"
62 #include "gromacs/legacyheaders/gmx_omp_nthreads.h"
63 #include "gromacs/legacyheaders/mdatoms.h"
64 #include "gromacs/legacyheaders/mdrun.h"
65 #include "gromacs/legacyheaders/names.h"
66 #include "gromacs/legacyheaders/network.h"
67 #include "gromacs/legacyheaders/nrnb.h"
68 #include "gromacs/legacyheaders/nsgrid.h"
69 #include "gromacs/legacyheaders/shellfc.h"
70 #include "gromacs/legacyheaders/typedefs.h"
71 #include "gromacs/legacyheaders/vsite.h"
72 #include "gromacs/legacyheaders/types/commrec.h"
73 #include "gromacs/legacyheaders/types/constr.h"
74 #include "gromacs/legacyheaders/types/enums.h"
75 #include "gromacs/legacyheaders/types/forcerec.h"
76 #include "gromacs/legacyheaders/types/hw_info.h"
77 #include "gromacs/legacyheaders/types/ifunc.h"
78 #include "gromacs/legacyheaders/types/inputrec.h"
79 #include "gromacs/legacyheaders/types/mdatom.h"
80 #include "gromacs/legacyheaders/types/nrnb.h"
81 #include "gromacs/legacyheaders/types/ns.h"
82 #include "gromacs/legacyheaders/types/nsgrid.h"
83 #include "gromacs/legacyheaders/types/shellfc.h"
84 #include "gromacs/legacyheaders/types/simple.h"
85 #include "gromacs/legacyheaders/types/state.h"
86 #include "gromacs/listed-forces/manage-threading.h"
87 #include "gromacs/math/vec.h"
88 #include "gromacs/math/vectypes.h"
89 #include "gromacs/mdlib/nb_verlet.h"
90 #include "gromacs/mdlib/nbnxn_search.h"
91 #include "gromacs/pbcutil/ishift.h"
92 #include "gromacs/pbcutil/pbc.h"
93 #include "gromacs/pulling/pull.h"
94 #include "gromacs/pulling/pull_rotation.h"
95 #include "gromacs/swap/swapcoords.h"
96 #include "gromacs/timing/wallcycle.h"
97 #include "gromacs/topology/block.h"
98 #include "gromacs/topology/idef.h"
99 #include "gromacs/topology/mtop_util.h"
100 #include "gromacs/topology/topology.h"
101 #include "gromacs/utility/basedefinitions.h"
102 #include "gromacs/utility/basenetwork.h"
103 #include "gromacs/utility/cstringutil.h"
104 #include "gromacs/utility/fatalerror.h"
105 #include "gromacs/utility/gmxmpi.h"
106 #include "gromacs/utility/qsort_threadsafe.h"
107 #include "gromacs/utility/real.h"
108 #include "gromacs/utility/smalloc.h"
110 #include "domdec_constraints.h"
111 #include "domdec_internal.h"
112 #include "domdec_vsite.h"
114 #define DDRANK(dd, rank) (rank)
115 #define DDMASTERRANK(dd) (dd->masterrank)
117 typedef struct gmx_domdec_master
119 /* The cell boundaries */
120 real **cell_x;
121 /* The global charge group division */
122 int *ncg; /* Number of home charge groups for each node */
123 int *index; /* Index of nnodes+1 into cg */
124 int *cg; /* Global charge group index */
125 int *nat; /* Number of home atoms for each node. */
126 int *ibuf; /* Buffer for communication */
127 rvec *vbuf; /* Buffer for state scattering and gathering */
128 } gmx_domdec_master_t;
130 typedef struct
132 /* The numbers of charge groups to send and receive for each cell
133 * that requires communication, the last entry contains the total
134 * number of atoms that needs to be communicated.
136 int nsend[DD_MAXIZONE+2];
137 int nrecv[DD_MAXIZONE+2];
138 /* The charge groups to send */
139 int *index;
140 int nalloc;
141 /* The atom range for non-in-place communication */
142 int cell2at0[DD_MAXIZONE];
143 int cell2at1[DD_MAXIZONE];
144 } gmx_domdec_ind_t;
146 typedef struct
148 int np; /* Number of grid pulses in this dimension */
149 int np_dlb; /* For dlb, for use with edlbAUTO */
150 gmx_domdec_ind_t *ind; /* The indices to communicate, size np */
151 int np_nalloc;
152 gmx_bool bInPlace; /* Can we communicate in place? */
153 } gmx_domdec_comm_dim_t;
155 typedef struct
157 gmx_bool *bCellMin; /* Temp. var.: is this cell size at the limit */
158 real *cell_f; /* State var.: cell boundaries, box relative */
159 real *old_cell_f; /* Temp. var.: old cell size */
160 real *cell_f_max0; /* State var.: max lower boundary, incl neighbors */
161 real *cell_f_min1; /* State var.: min upper boundary, incl neighbors */
162 real *bound_min; /* Temp. var.: lower limit for cell boundary */
163 real *bound_max; /* Temp. var.: upper limit for cell boundary */
164 gmx_bool bLimited; /* State var.: is DLB limited in this dim and row */
165 real *buf_ncd; /* Temp. var. */
166 } gmx_domdec_root_t;
168 #define DD_NLOAD_MAX 9
170 /* Here floats are accurate enough, since these variables
171 * only influence the load balancing, not the actual MD results.
173 typedef struct
175 int nload;
176 float *load;
177 float sum;
178 float max;
179 float sum_m;
180 float cvol_min;
181 float mdf;
182 float pme;
183 int flags;
184 } gmx_domdec_load_t;
186 typedef struct
188 int nsc;
189 int ind_gl;
190 int ind;
191 } gmx_cgsort_t;
193 typedef struct
195 gmx_cgsort_t *sort;
196 gmx_cgsort_t *sort2;
197 int sort_nalloc;
198 gmx_cgsort_t *sort_new;
199 int sort_new_nalloc;
200 int *ibuf;
201 int ibuf_nalloc;
202 } gmx_domdec_sort_t;
204 typedef struct
206 rvec *v;
207 int nalloc;
208 } vec_rvec_t;
210 /* This enum determines the order of the coordinates.
211 * ddnatHOME and ddnatZONE should be first and second,
212 * the others can be ordered as wanted.
214 enum {
215 ddnatHOME, ddnatZONE, ddnatVSITE, ddnatCON, ddnatNR
218 enum {
219 edlbAUTO, edlbNO, edlbYES, edlbNR
221 const char *edlb_names[edlbNR] = { "auto", "no", "yes" };
223 typedef struct
225 int dim; /* The dimension */
226 gmx_bool dim_match; /* Tells if DD and PME dims match */
227 int nslab; /* The number of PME slabs in this dimension */
228 real *slb_dim_f; /* Cell sizes for determining the PME comm. with SLB */
229 int *pp_min; /* The minimum pp node location, size nslab */
230 int *pp_max; /* The maximum pp node location,size nslab */
231 int maxshift; /* The maximum shift for coordinate redistribution in PME */
232 } gmx_ddpme_t;
234 typedef struct
236 real min0; /* The minimum bottom of this zone */
237 real max1; /* The maximum top of this zone */
238 real min1; /* The minimum top of this zone */
239 real mch0; /* The maximum bottom communicaton height for this zone */
240 real mch1; /* The maximum top communicaton height for this zone */
241 real p1_0; /* The bottom value of the first cell in this zone */
242 real p1_1; /* The top value of the first cell in this zone */
243 } gmx_ddzone_t;
245 typedef struct
247 gmx_domdec_ind_t ind;
248 int *ibuf;
249 int ibuf_nalloc;
250 vec_rvec_t vbuf;
251 int nsend;
252 int nat;
253 int nsend_zone;
254 } dd_comm_setup_work_t;
256 typedef struct gmx_domdec_comm
258 /* All arrays are indexed with 0 to dd->ndim (not Cartesian indexing),
259 * unless stated otherwise.
262 /* The number of decomposition dimensions for PME, 0: no PME */
263 int npmedecompdim;
264 /* The number of nodes doing PME (PP/PME or only PME) */
265 int npmenodes;
266 int npmenodes_x;
267 int npmenodes_y;
268 /* The communication setup including the PME only nodes */
269 gmx_bool bCartesianPP_PME;
270 ivec ntot;
271 int cartpmedim;
272 int *pmenodes; /* size npmenodes */
273 int *ddindex2simnodeid; /* size npmenodes, only with bCartesianPP
274 * but with bCartesianPP_PME */
275 gmx_ddpme_t ddpme[2];
277 /* The DD particle-particle nodes only */
278 gmx_bool bCartesianPP;
279 int *ddindex2ddnodeid; /* size npmenode, only with bCartesianPP_PME */
281 /* The global charge groups */
282 t_block cgs_gl;
284 /* Should we sort the cgs */
285 int nstSortCG;
286 gmx_domdec_sort_t *sort;
288 /* Are there charge groups? */
289 gmx_bool bCGs;
291 /* Are there bonded and multi-body interactions between charge groups? */
292 gmx_bool bInterCGBondeds;
293 gmx_bool bInterCGMultiBody;
295 /* Data for the optional bonded interaction atom communication range */
296 gmx_bool bBondComm;
297 t_blocka *cglink;
298 char *bLocalCG;
300 /* The DLB option */
301 int eDLB;
302 /* Is eDLB=edlbAUTO locked such that we currently can't turn it on? */
303 gmx_bool bDLB_locked;
304 /* Are we actually using DLB? */
305 gmx_bool bDynLoadBal;
307 /* Cell sizes for static load balancing, first index cartesian */
308 real **slb_frac;
310 /* The width of the communicated boundaries */
311 real cutoff_mbody;
312 real cutoff;
313 /* The minimum cell size (including triclinic correction) */
314 rvec cellsize_min;
315 /* For dlb, for use with edlbAUTO */
316 rvec cellsize_min_dlb;
317 /* The lower limit for the DD cell size with DLB */
318 real cellsize_limit;
319 /* Effectively no NB cut-off limit with DLB for systems without PBC? */
320 gmx_bool bVacDLBNoLimit;
322 /* With PME load balancing we set limits on DLB */
323 gmx_bool bPMELoadBalDLBLimits;
324 /* DLB needs to take into account that we want to allow this maximum
325 * cut-off (for PME load balancing), this could limit cell boundaries.
327 real PMELoadBal_max_cutoff;
329 /* tric_dir is only stored here because dd_get_ns_ranges needs it */
330 ivec tric_dir;
331 /* box0 and box_size are required with dim's without pbc and -gcom */
332 rvec box0;
333 rvec box_size;
335 /* The cell boundaries */
336 rvec cell_x0;
337 rvec cell_x1;
339 /* The old location of the cell boundaries, to check cg displacements */
340 rvec old_cell_x0;
341 rvec old_cell_x1;
343 /* The communication setup and charge group boundaries for the zones */
344 gmx_domdec_zones_t zones;
346 /* The zone limits for DD dimensions 1 and 2 (not 0), determined from
347 * cell boundaries of neighboring cells for dynamic load balancing.
349 gmx_ddzone_t zone_d1[2];
350 gmx_ddzone_t zone_d2[2][2];
352 /* The coordinate/force communication setup and indices */
353 gmx_domdec_comm_dim_t cd[DIM];
354 /* The maximum number of cells to communicate with in one dimension */
355 int maxpulse;
357 /* Which cg distribution is stored on the master node */
358 int master_cg_ddp_count;
360 /* The number of cg's received from the direct neighbors */
361 int zone_ncg1[DD_MAXZONE];
363 /* The atom counts, the range for each type t is nat[t-1] <= at < nat[t] */
364 int nat[ddnatNR];
366 /* Array for signalling if atoms have moved to another domain */
367 int *moved;
368 int moved_nalloc;
370 /* Communication buffer for general use */
371 int *buf_int;
372 int nalloc_int;
374 /* Communication buffer for general use */
375 vec_rvec_t vbuf;
377 /* Temporary storage for thread parallel communication setup */
378 int nth;
379 dd_comm_setup_work_t *dth;
381 /* Communication buffers only used with multiple grid pulses */
382 int *buf_int2;
383 int nalloc_int2;
384 vec_rvec_t vbuf2;
386 /* Communication buffers for local redistribution */
387 int **cggl_flag;
388 int cggl_flag_nalloc[DIM*2];
389 rvec **cgcm_state;
390 int cgcm_state_nalloc[DIM*2];
392 /* Cell sizes for dynamic load balancing */
393 gmx_domdec_root_t **root;
394 real *cell_f_row;
395 real cell_f0[DIM];
396 real cell_f1[DIM];
397 real cell_f_max0[DIM];
398 real cell_f_min1[DIM];
400 /* Stuff for load communication */
401 gmx_bool bRecordLoad;
402 gmx_domdec_load_t *load;
403 int nrank_gpu_shared;
404 #ifdef GMX_MPI
405 MPI_Comm *mpi_comm_load;
406 MPI_Comm mpi_comm_gpu_shared;
407 #endif
409 /* Maximum DLB scaling per load balancing step in percent */
410 int dlb_scale_lim;
412 /* Cycle counters */
413 float cycl[ddCyclNr];
414 int cycl_n[ddCyclNr];
415 float cycl_max[ddCyclNr];
416 /* Flop counter (0=no,1=yes,2=with (eFlop-1)*5% noise */
417 int eFlop;
418 double flop;
419 int flop_n;
420 /* How many times have did we have load measurements */
421 int n_load_have;
422 /* How many times have we collected the load measurements */
423 int n_load_collect;
425 /* Statistics */
426 double sum_nat[ddnatNR-ddnatZONE];
427 int ndecomp;
428 int nload;
429 double load_step;
430 double load_sum;
431 double load_max;
432 ivec load_lim;
433 double load_mdf;
434 double load_pme;
436 /* The last partition step */
437 gmx_int64_t partition_step;
439 /* Debugging */
440 int nstDDDump;
441 int nstDDDumpGrid;
442 int DD_debug;
443 } gmx_domdec_comm_t;
445 /* The size per charge group of the cggl_flag buffer in gmx_domdec_comm_t */
446 #define DD_CGIBS 2
448 /* The flags for the cggl_flag buffer in gmx_domdec_comm_t */
449 #define DD_FLAG_NRCG 65535
450 #define DD_FLAG_FW(d) (1<<(16+(d)*2))
451 #define DD_FLAG_BW(d) (1<<(16+(d)*2+1))
453 /* Zone permutation required to obtain consecutive charge groups
454 * for neighbor searching.
456 static const int zone_perm[3][4] = { {0, 0, 0, 0}, {1, 0, 0, 0}, {3, 0, 1, 2} };
458 /* dd_zo and dd_zp3/dd_zp2 are set up such that i zones with non-zero
459 * components see only j zones with that component 0.
462 /* The DD zone order */
463 static const ivec dd_zo[DD_MAXZONE] =
464 {{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 1, 1}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}};
466 /* The 3D setup */
467 #define dd_z3n 8
468 #define dd_zp3n 4
469 static const ivec dd_zp3[dd_zp3n] = {{0, 0, 8}, {1, 3, 6}, {2, 5, 6}, {3, 5, 7}};
471 /* The 2D setup */
472 #define dd_z2n 4
473 #define dd_zp2n 2
474 static const ivec dd_zp2[dd_zp2n] = {{0, 0, 4}, {1, 3, 4}};
476 /* The 1D setup */
477 #define dd_z1n 2
478 #define dd_zp1n 1
479 static const ivec dd_zp1[dd_zp1n] = {{0, 0, 2}};
481 /* Factors used to avoid problems due to rounding issues */
482 #define DD_CELL_MARGIN 1.0001
483 #define DD_CELL_MARGIN2 1.00005
484 /* Factor to account for pressure scaling during nstlist steps */
485 #define DD_PRES_SCALE_MARGIN 1.02
487 /* Turn on DLB when the load imbalance causes this amount of total loss.
488 * There is a bit of overhead with DLB and it's difficult to achieve
489 * a load imbalance of less than 2% with DLB.
491 #define DD_PERF_LOSS_DLB_ON 0.02
493 /* Warn about imbalance due to PP or PP/PME load imbalance at this loss */
494 #define DD_PERF_LOSS_WARN 0.05
496 #define DD_CELL_F_SIZE(dd, di) ((dd)->nc[(dd)->dim[(di)]]+1+(di)*2+1+(di))
498 /* Use separate MPI send and receive commands
499 * when nnodes <= GMX_DD_NNODES_SENDRECV.
500 * This saves memory (and some copying for small nnodes).
501 * For high parallelization scatter and gather calls are used.
503 #define GMX_DD_NNODES_SENDRECV 4
507 #define dd_index(n,i) ((((i)[ZZ]*(n)[YY] + (i)[YY])*(n)[XX]) + (i)[XX])
509 static void index2xyz(ivec nc,int ind,ivec xyz)
511 xyz[XX] = ind % nc[XX];
512 xyz[YY] = (ind / nc[XX]) % nc[YY];
513 xyz[ZZ] = ind / (nc[YY]*nc[XX]);
517 /* This order is required to minimize the coordinate communication in PME
518 * which uses decomposition in the x direction.
520 #define dd_index(n, i) ((((i)[XX]*(n)[YY] + (i)[YY])*(n)[ZZ]) + (i)[ZZ])
522 static void ddindex2xyz(ivec nc, int ind, ivec xyz)
524 xyz[XX] = ind / (nc[YY]*nc[ZZ]);
525 xyz[YY] = (ind / nc[ZZ]) % nc[YY];
526 xyz[ZZ] = ind % nc[ZZ];
529 static int ddcoord2ddnodeid(gmx_domdec_t *dd, ivec c)
531 int ddindex;
532 int ddnodeid = -1;
534 ddindex = dd_index(dd->nc, c);
535 if (dd->comm->bCartesianPP_PME)
537 ddnodeid = dd->comm->ddindex2ddnodeid[ddindex];
539 else if (dd->comm->bCartesianPP)
541 #ifdef GMX_MPI
542 MPI_Cart_rank(dd->mpi_comm_all, c, &ddnodeid);
543 #endif
545 else
547 ddnodeid = ddindex;
550 return ddnodeid;
553 static gmx_bool dynamic_dd_box(gmx_ddbox_t *ddbox, t_inputrec *ir)
555 return (ddbox->nboundeddim < DIM || DYNAMIC_BOX(*ir));
558 int ddglatnr(gmx_domdec_t *dd, int i)
560 int atnr;
562 if (dd == NULL)
564 atnr = i + 1;
566 else
568 if (i >= dd->comm->nat[ddnatNR-1])
570 gmx_fatal(FARGS, "glatnr called with %d, which is larger than the local number of atoms (%d)", i, dd->comm->nat[ddnatNR-1]);
572 atnr = dd->gatindex[i] + 1;
575 return atnr;
578 t_block *dd_charge_groups_global(gmx_domdec_t *dd)
580 return &dd->comm->cgs_gl;
583 static void vec_rvec_init(vec_rvec_t *v)
585 v->nalloc = 0;
586 v->v = NULL;
589 static void vec_rvec_check_alloc(vec_rvec_t *v, int n)
591 if (n > v->nalloc)
593 v->nalloc = over_alloc_dd(n);
594 srenew(v->v, v->nalloc);
598 void dd_store_state(gmx_domdec_t *dd, t_state *state)
600 int i;
602 if (state->ddp_count != dd->ddp_count)
604 gmx_incons("The state does not the domain decomposition state");
607 state->ncg_gl = dd->ncg_home;
608 if (state->ncg_gl > state->cg_gl_nalloc)
610 state->cg_gl_nalloc = over_alloc_dd(state->ncg_gl);
611 srenew(state->cg_gl, state->cg_gl_nalloc);
613 for (i = 0; i < state->ncg_gl; i++)
615 state->cg_gl[i] = dd->index_gl[i];
618 state->ddp_count_cg_gl = dd->ddp_count;
621 gmx_domdec_zones_t *domdec_zones(gmx_domdec_t *dd)
623 return &dd->comm->zones;
626 void dd_get_ns_ranges(gmx_domdec_t *dd, int icg,
627 int *jcg0, int *jcg1, ivec shift0, ivec shift1)
629 gmx_domdec_zones_t *zones;
630 int izone, d, dim;
632 zones = &dd->comm->zones;
634 izone = 0;
635 while (icg >= zones->izone[izone].cg1)
637 izone++;
640 if (izone == 0)
642 *jcg0 = icg;
644 else if (izone < zones->nizone)
646 *jcg0 = zones->izone[izone].jcg0;
648 else
650 gmx_fatal(FARGS, "DD icg %d out of range: izone (%d) >= nizone (%d)",
651 icg, izone, zones->nizone);
654 *jcg1 = zones->izone[izone].jcg1;
656 for (d = 0; d < dd->ndim; d++)
658 dim = dd->dim[d];
659 shift0[dim] = zones->izone[izone].shift0[dim];
660 shift1[dim] = zones->izone[izone].shift1[dim];
661 if (dd->comm->tric_dir[dim] || (dd->bGridJump && d > 0))
663 /* A conservative approach, this can be optimized */
664 shift0[dim] -= 1;
665 shift1[dim] += 1;
670 int dd_natoms_vsite(gmx_domdec_t *dd)
672 return dd->comm->nat[ddnatVSITE];
675 void dd_get_constraint_range(gmx_domdec_t *dd, int *at_start, int *at_end)
677 *at_start = dd->comm->nat[ddnatCON-1];
678 *at_end = dd->comm->nat[ddnatCON];
681 void dd_move_x(gmx_domdec_t *dd, matrix box, rvec x[])
683 int nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
684 int *index, *cgindex;
685 gmx_domdec_comm_t *comm;
686 gmx_domdec_comm_dim_t *cd;
687 gmx_domdec_ind_t *ind;
688 rvec shift = {0, 0, 0}, *buf, *rbuf;
689 gmx_bool bPBC, bScrew;
691 comm = dd->comm;
693 cgindex = dd->cgindex;
695 buf = comm->vbuf.v;
697 nzone = 1;
698 nat_tot = dd->nat_home;
699 for (d = 0; d < dd->ndim; d++)
701 bPBC = (dd->ci[dd->dim[d]] == 0);
702 bScrew = (bPBC && dd->bScrewPBC && dd->dim[d] == XX);
703 if (bPBC)
705 copy_rvec(box[dd->dim[d]], shift);
707 cd = &comm->cd[d];
708 for (p = 0; p < cd->np; p++)
710 ind = &cd->ind[p];
711 index = ind->index;
712 n = 0;
713 if (!bPBC)
715 for (i = 0; i < ind->nsend[nzone]; i++)
717 at0 = cgindex[index[i]];
718 at1 = cgindex[index[i]+1];
719 for (j = at0; j < at1; j++)
721 copy_rvec(x[j], buf[n]);
722 n++;
726 else if (!bScrew)
728 for (i = 0; i < ind->nsend[nzone]; i++)
730 at0 = cgindex[index[i]];
731 at1 = cgindex[index[i]+1];
732 for (j = at0; j < at1; j++)
734 /* We need to shift the coordinates */
735 rvec_add(x[j], shift, buf[n]);
736 n++;
740 else
742 for (i = 0; i < ind->nsend[nzone]; i++)
744 at0 = cgindex[index[i]];
745 at1 = cgindex[index[i]+1];
746 for (j = at0; j < at1; j++)
748 /* Shift x */
749 buf[n][XX] = x[j][XX] + shift[XX];
750 /* Rotate y and z.
751 * This operation requires a special shift force
752 * treatment, which is performed in calc_vir.
754 buf[n][YY] = box[YY][YY] - x[j][YY];
755 buf[n][ZZ] = box[ZZ][ZZ] - x[j][ZZ];
756 n++;
761 if (cd->bInPlace)
763 rbuf = x + nat_tot;
765 else
767 rbuf = comm->vbuf2.v;
769 /* Send and receive the coordinates */
770 dd_sendrecv_rvec(dd, d, dddirBackward,
771 buf, ind->nsend[nzone+1],
772 rbuf, ind->nrecv[nzone+1]);
773 if (!cd->bInPlace)
775 j = 0;
776 for (zone = 0; zone < nzone; zone++)
778 for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
780 copy_rvec(rbuf[j], x[i]);
781 j++;
785 nat_tot += ind->nrecv[nzone+1];
787 nzone += nzone;
791 void dd_move_f(gmx_domdec_t *dd, rvec f[], rvec *fshift)
793 int nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
794 int *index, *cgindex;
795 gmx_domdec_comm_t *comm;
796 gmx_domdec_comm_dim_t *cd;
797 gmx_domdec_ind_t *ind;
798 rvec *buf, *sbuf;
799 ivec vis;
800 int is;
801 gmx_bool bShiftForcesNeedPbc, bScrew;
803 comm = dd->comm;
805 cgindex = dd->cgindex;
807 buf = comm->vbuf.v;
809 nzone = comm->zones.n/2;
810 nat_tot = dd->nat_tot;
811 for (d = dd->ndim-1; d >= 0; d--)
813 /* Only forces in domains near the PBC boundaries need to
814 consider PBC in the treatment of fshift */
815 bShiftForcesNeedPbc = (dd->ci[dd->dim[d]] == 0);
816 bScrew = (bShiftForcesNeedPbc && dd->bScrewPBC && dd->dim[d] == XX);
817 if (fshift == NULL && !bScrew)
819 bShiftForcesNeedPbc = FALSE;
821 /* Determine which shift vector we need */
822 clear_ivec(vis);
823 vis[dd->dim[d]] = 1;
824 is = IVEC2IS(vis);
826 cd = &comm->cd[d];
827 for (p = cd->np-1; p >= 0; p--)
829 ind = &cd->ind[p];
830 nat_tot -= ind->nrecv[nzone+1];
831 if (cd->bInPlace)
833 sbuf = f + nat_tot;
835 else
837 sbuf = comm->vbuf2.v;
838 j = 0;
839 for (zone = 0; zone < nzone; zone++)
841 for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
843 copy_rvec(f[i], sbuf[j]);
844 j++;
848 /* Communicate the forces */
849 dd_sendrecv_rvec(dd, d, dddirForward,
850 sbuf, ind->nrecv[nzone+1],
851 buf, ind->nsend[nzone+1]);
852 index = ind->index;
853 /* Add the received forces */
854 n = 0;
855 if (!bShiftForcesNeedPbc)
857 for (i = 0; i < ind->nsend[nzone]; i++)
859 at0 = cgindex[index[i]];
860 at1 = cgindex[index[i]+1];
861 for (j = at0; j < at1; j++)
863 rvec_inc(f[j], buf[n]);
864 n++;
868 else if (!bScrew)
870 /* fshift should always be defined if this function is
871 * called when bShiftForcesNeedPbc is true */
872 assert(NULL != fshift);
873 for (i = 0; i < ind->nsend[nzone]; i++)
875 at0 = cgindex[index[i]];
876 at1 = cgindex[index[i]+1];
877 for (j = at0; j < at1; j++)
879 rvec_inc(f[j], buf[n]);
880 /* Add this force to the shift force */
881 rvec_inc(fshift[is], buf[n]);
882 n++;
886 else
888 for (i = 0; i < ind->nsend[nzone]; i++)
890 at0 = cgindex[index[i]];
891 at1 = cgindex[index[i]+1];
892 for (j = at0; j < at1; j++)
894 /* Rotate the force */
895 f[j][XX] += buf[n][XX];
896 f[j][YY] -= buf[n][YY];
897 f[j][ZZ] -= buf[n][ZZ];
898 if (fshift)
900 /* Add this force to the shift force */
901 rvec_inc(fshift[is], buf[n]);
903 n++;
908 nzone /= 2;
912 void dd_atom_spread_real(gmx_domdec_t *dd, real v[])
914 int nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
915 int *index, *cgindex;
916 gmx_domdec_comm_t *comm;
917 gmx_domdec_comm_dim_t *cd;
918 gmx_domdec_ind_t *ind;
919 real *buf, *rbuf;
921 comm = dd->comm;
923 cgindex = dd->cgindex;
925 buf = &comm->vbuf.v[0][0];
927 nzone = 1;
928 nat_tot = dd->nat_home;
929 for (d = 0; d < dd->ndim; d++)
931 cd = &comm->cd[d];
932 for (p = 0; p < cd->np; p++)
934 ind = &cd->ind[p];
935 index = ind->index;
936 n = 0;
937 for (i = 0; i < ind->nsend[nzone]; i++)
939 at0 = cgindex[index[i]];
940 at1 = cgindex[index[i]+1];
941 for (j = at0; j < at1; j++)
943 buf[n] = v[j];
944 n++;
948 if (cd->bInPlace)
950 rbuf = v + nat_tot;
952 else
954 rbuf = &comm->vbuf2.v[0][0];
956 /* Send and receive the coordinates */
957 dd_sendrecv_real(dd, d, dddirBackward,
958 buf, ind->nsend[nzone+1],
959 rbuf, ind->nrecv[nzone+1]);
960 if (!cd->bInPlace)
962 j = 0;
963 for (zone = 0; zone < nzone; zone++)
965 for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
967 v[i] = rbuf[j];
968 j++;
972 nat_tot += ind->nrecv[nzone+1];
974 nzone += nzone;
978 void dd_atom_sum_real(gmx_domdec_t *dd, real v[])
980 int nzone, nat_tot, n, d, p, i, j, at0, at1, zone;
981 int *index, *cgindex;
982 gmx_domdec_comm_t *comm;
983 gmx_domdec_comm_dim_t *cd;
984 gmx_domdec_ind_t *ind;
985 real *buf, *sbuf;
987 comm = dd->comm;
989 cgindex = dd->cgindex;
991 buf = &comm->vbuf.v[0][0];
993 nzone = comm->zones.n/2;
994 nat_tot = dd->nat_tot;
995 for (d = dd->ndim-1; d >= 0; d--)
997 cd = &comm->cd[d];
998 for (p = cd->np-1; p >= 0; p--)
1000 ind = &cd->ind[p];
1001 nat_tot -= ind->nrecv[nzone+1];
1002 if (cd->bInPlace)
1004 sbuf = v + nat_tot;
1006 else
1008 sbuf = &comm->vbuf2.v[0][0];
1009 j = 0;
1010 for (zone = 0; zone < nzone; zone++)
1012 for (i = ind->cell2at0[zone]; i < ind->cell2at1[zone]; i++)
1014 sbuf[j] = v[i];
1015 j++;
1019 /* Communicate the forces */
1020 dd_sendrecv_real(dd, d, dddirForward,
1021 sbuf, ind->nrecv[nzone+1],
1022 buf, ind->nsend[nzone+1]);
1023 index = ind->index;
1024 /* Add the received forces */
1025 n = 0;
1026 for (i = 0; i < ind->nsend[nzone]; i++)
1028 at0 = cgindex[index[i]];
1029 at1 = cgindex[index[i]+1];
1030 for (j = at0; j < at1; j++)
1032 v[j] += buf[n];
1033 n++;
1037 nzone /= 2;
1041 static void print_ddzone(FILE *fp, int d, int i, int j, gmx_ddzone_t *zone)
1043 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",
1044 d, i, j,
1045 zone->min0, zone->max1,
1046 zone->mch0, zone->mch0,
1047 zone->p1_0, zone->p1_1);
1051 #define DDZONECOMM_MAXZONE 5
1052 #define DDZONECOMM_BUFSIZE 3
1054 static void dd_sendrecv_ddzone(const gmx_domdec_t *dd,
1055 int ddimind, int direction,
1056 gmx_ddzone_t *buf_s, int n_s,
1057 gmx_ddzone_t *buf_r, int n_r)
1059 #define ZBS DDZONECOMM_BUFSIZE
1060 rvec vbuf_s[DDZONECOMM_MAXZONE*ZBS];
1061 rvec vbuf_r[DDZONECOMM_MAXZONE*ZBS];
1062 int i;
1064 for (i = 0; i < n_s; i++)
1066 vbuf_s[i*ZBS ][0] = buf_s[i].min0;
1067 vbuf_s[i*ZBS ][1] = buf_s[i].max1;
1068 vbuf_s[i*ZBS ][2] = buf_s[i].min1;
1069 vbuf_s[i*ZBS+1][0] = buf_s[i].mch0;
1070 vbuf_s[i*ZBS+1][1] = buf_s[i].mch1;
1071 vbuf_s[i*ZBS+1][2] = 0;
1072 vbuf_s[i*ZBS+2][0] = buf_s[i].p1_0;
1073 vbuf_s[i*ZBS+2][1] = buf_s[i].p1_1;
1074 vbuf_s[i*ZBS+2][2] = 0;
1077 dd_sendrecv_rvec(dd, ddimind, direction,
1078 vbuf_s, n_s*ZBS,
1079 vbuf_r, n_r*ZBS);
1081 for (i = 0; i < n_r; i++)
1083 buf_r[i].min0 = vbuf_r[i*ZBS ][0];
1084 buf_r[i].max1 = vbuf_r[i*ZBS ][1];
1085 buf_r[i].min1 = vbuf_r[i*ZBS ][2];
1086 buf_r[i].mch0 = vbuf_r[i*ZBS+1][0];
1087 buf_r[i].mch1 = vbuf_r[i*ZBS+1][1];
1088 buf_r[i].p1_0 = vbuf_r[i*ZBS+2][0];
1089 buf_r[i].p1_1 = vbuf_r[i*ZBS+2][1];
1092 #undef ZBS
1095 static void dd_move_cellx(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
1096 rvec cell_ns_x0, rvec cell_ns_x1)
1098 int d, d1, dim, pos, buf_size, i, j, p, npulse, npulse_min;
1099 gmx_ddzone_t *zp;
1100 gmx_ddzone_t buf_s[DDZONECOMM_MAXZONE];
1101 gmx_ddzone_t buf_r[DDZONECOMM_MAXZONE];
1102 gmx_ddzone_t buf_e[DDZONECOMM_MAXZONE];
1103 rvec extr_s[2], extr_r[2];
1104 rvec dh;
1105 real dist_d, c = 0, det;
1106 gmx_domdec_comm_t *comm;
1107 gmx_bool bPBC, bUse;
1109 comm = dd->comm;
1111 for (d = 1; d < dd->ndim; d++)
1113 dim = dd->dim[d];
1114 zp = (d == 1) ? &comm->zone_d1[0] : &comm->zone_d2[0][0];
1115 zp->min0 = cell_ns_x0[dim];
1116 zp->max1 = cell_ns_x1[dim];
1117 zp->min1 = cell_ns_x1[dim];
1118 zp->mch0 = cell_ns_x0[dim];
1119 zp->mch1 = cell_ns_x1[dim];
1120 zp->p1_0 = cell_ns_x0[dim];
1121 zp->p1_1 = cell_ns_x1[dim];
1124 for (d = dd->ndim-2; d >= 0; d--)
1126 dim = dd->dim[d];
1127 bPBC = (dim < ddbox->npbcdim);
1129 /* Use an rvec to store two reals */
1130 extr_s[d][0] = comm->cell_f0[d+1];
1131 extr_s[d][1] = comm->cell_f1[d+1];
1132 extr_s[d][2] = comm->cell_f1[d+1];
1134 pos = 0;
1135 /* Store the extremes in the backward sending buffer,
1136 * so the get updated separately from the forward communication.
1138 for (d1 = d; d1 < dd->ndim-1; d1++)
1140 /* We invert the order to be able to use the same loop for buf_e */
1141 buf_s[pos].min0 = extr_s[d1][1];
1142 buf_s[pos].max1 = extr_s[d1][0];
1143 buf_s[pos].min1 = extr_s[d1][2];
1144 buf_s[pos].mch0 = 0;
1145 buf_s[pos].mch1 = 0;
1146 /* Store the cell corner of the dimension we communicate along */
1147 buf_s[pos].p1_0 = comm->cell_x0[dim];
1148 buf_s[pos].p1_1 = 0;
1149 pos++;
1152 buf_s[pos] = (dd->ndim == 2) ? comm->zone_d1[0] : comm->zone_d2[0][0];
1153 pos++;
1155 if (dd->ndim == 3 && d == 0)
1157 buf_s[pos] = comm->zone_d2[0][1];
1158 pos++;
1159 buf_s[pos] = comm->zone_d1[0];
1160 pos++;
1163 /* We only need to communicate the extremes
1164 * in the forward direction
1166 npulse = comm->cd[d].np;
1167 if (bPBC)
1169 /* Take the minimum to avoid double communication */
1170 npulse_min = std::min(npulse, dd->nc[dim]-1-npulse);
1172 else
1174 /* Without PBC we should really not communicate over
1175 * the boundaries, but implementing that complicates
1176 * the communication setup and therefore we simply
1177 * do all communication, but ignore some data.
1179 npulse_min = npulse;
1181 for (p = 0; p < npulse_min; p++)
1183 /* Communicate the extremes forward */
1184 bUse = (bPBC || dd->ci[dim] > 0);
1186 dd_sendrecv_rvec(dd, d, dddirForward,
1187 extr_s+d, dd->ndim-d-1,
1188 extr_r+d, dd->ndim-d-1);
1190 if (bUse)
1192 for (d1 = d; d1 < dd->ndim-1; d1++)
1194 extr_s[d1][0] = std::max(extr_s[d1][0], extr_r[d1][0]);
1195 extr_s[d1][1] = std::min(extr_s[d1][1], extr_r[d1][1]);
1196 extr_s[d1][2] = std::min(extr_s[d1][2], extr_r[d1][2]);
1201 buf_size = pos;
1202 for (p = 0; p < npulse; p++)
1204 /* Communicate all the zone information backward */
1205 bUse = (bPBC || dd->ci[dim] < dd->nc[dim] - 1);
1207 dd_sendrecv_ddzone(dd, d, dddirBackward,
1208 buf_s, buf_size,
1209 buf_r, buf_size);
1211 clear_rvec(dh);
1212 if (p > 0)
1214 for (d1 = d+1; d1 < dd->ndim; d1++)
1216 /* Determine the decrease of maximum required
1217 * communication height along d1 due to the distance along d,
1218 * this avoids a lot of useless atom communication.
1220 dist_d = comm->cell_x1[dim] - buf_r[0].p1_0;
1222 if (ddbox->tric_dir[dim])
1224 /* c is the off-diagonal coupling between the cell planes
1225 * along directions d and d1.
1227 c = ddbox->v[dim][dd->dim[d1]][dim];
1229 else
1231 c = 0;
1233 det = (1 + c*c)*comm->cutoff*comm->cutoff - dist_d*dist_d;
1234 if (det > 0)
1236 dh[d1] = comm->cutoff - (c*dist_d + sqrt(det))/(1 + c*c);
1238 else
1240 /* A negative value signals out of range */
1241 dh[d1] = -1;
1246 /* Accumulate the extremes over all pulses */
1247 for (i = 0; i < buf_size; i++)
1249 if (p == 0)
1251 buf_e[i] = buf_r[i];
1253 else
1255 if (bUse)
1257 buf_e[i].min0 = std::min(buf_e[i].min0, buf_r[i].min0);
1258 buf_e[i].max1 = std::max(buf_e[i].max1, buf_r[i].max1);
1259 buf_e[i].min1 = std::min(buf_e[i].min1, buf_r[i].min1);
1262 if (dd->ndim == 3 && d == 0 && i == buf_size - 1)
1264 d1 = 1;
1266 else
1268 d1 = d + 1;
1270 if (bUse && dh[d1] >= 0)
1272 buf_e[i].mch0 = std::max(buf_e[i].mch0, buf_r[i].mch0-dh[d1]);
1273 buf_e[i].mch1 = std::max(buf_e[i].mch1, buf_r[i].mch1-dh[d1]);
1276 /* Copy the received buffer to the send buffer,
1277 * to pass the data through with the next pulse.
1279 buf_s[i] = buf_r[i];
1281 if (((bPBC || dd->ci[dim]+npulse < dd->nc[dim]) && p == npulse-1) ||
1282 (!bPBC && dd->ci[dim]+1+p == dd->nc[dim]-1))
1284 /* Store the extremes */
1285 pos = 0;
1287 for (d1 = d; d1 < dd->ndim-1; d1++)
1289 extr_s[d1][1] = std::min(extr_s[d1][1], buf_e[pos].min0);
1290 extr_s[d1][0] = std::max(extr_s[d1][0], buf_e[pos].max1);
1291 extr_s[d1][2] = std::min(extr_s[d1][2], buf_e[pos].min1);
1292 pos++;
1295 if (d == 1 || (d == 0 && dd->ndim == 3))
1297 for (i = d; i < 2; i++)
1299 comm->zone_d2[1-d][i] = buf_e[pos];
1300 pos++;
1303 if (d == 0)
1305 comm->zone_d1[1] = buf_e[pos];
1306 pos++;
1312 if (dd->ndim >= 2)
1314 dim = dd->dim[1];
1315 for (i = 0; i < 2; i++)
1317 if (debug)
1319 print_ddzone(debug, 1, i, 0, &comm->zone_d1[i]);
1321 cell_ns_x0[dim] = std::min(cell_ns_x0[dim], comm->zone_d1[i].min0);
1322 cell_ns_x1[dim] = std::max(cell_ns_x1[dim], comm->zone_d1[i].max1);
1325 if (dd->ndim >= 3)
1327 dim = dd->dim[2];
1328 for (i = 0; i < 2; i++)
1330 for (j = 0; j < 2; j++)
1332 if (debug)
1334 print_ddzone(debug, 2, i, j, &comm->zone_d2[i][j]);
1336 cell_ns_x0[dim] = std::min(cell_ns_x0[dim], comm->zone_d2[i][j].min0);
1337 cell_ns_x1[dim] = std::max(cell_ns_x1[dim], comm->zone_d2[i][j].max1);
1341 for (d = 1; d < dd->ndim; d++)
1343 comm->cell_f_max0[d] = extr_s[d-1][0];
1344 comm->cell_f_min1[d] = extr_s[d-1][1];
1345 if (debug)
1347 fprintf(debug, "Cell fraction d %d, max0 %f, min1 %f\n",
1348 d, comm->cell_f_max0[d], comm->cell_f_min1[d]);
1353 static void dd_collect_cg(gmx_domdec_t *dd,
1354 t_state *state_local)
1356 gmx_domdec_master_t *ma = NULL;
1357 int buf2[2], *ibuf, i, ncg_home = 0, *cg = NULL, nat_home = 0;
1359 if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
1361 /* The master has the correct distribution */
1362 return;
1365 if (state_local->ddp_count == dd->ddp_count)
1367 /* The local state and DD are in sync, use the DD indices */
1368 ncg_home = dd->ncg_home;
1369 cg = dd->index_gl;
1370 nat_home = dd->nat_home;
1372 else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
1374 /* The DD is out of sync with the local state, but we have stored
1375 * the cg indices with the local state, so we can use those.
1377 t_block *cgs_gl;
1379 cgs_gl = &dd->comm->cgs_gl;
1381 ncg_home = state_local->ncg_gl;
1382 cg = state_local->cg_gl;
1383 nat_home = 0;
1384 for (i = 0; i < ncg_home; i++)
1386 nat_home += cgs_gl->index[cg[i]+1] - cgs_gl->index[cg[i]];
1389 else
1391 gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
1394 buf2[0] = ncg_home;
1395 buf2[1] = nat_home;
1396 if (DDMASTER(dd))
1398 ma = dd->ma;
1399 ibuf = ma->ibuf;
1401 else
1403 ibuf = NULL;
1405 /* Collect the charge group and atom counts on the master */
1406 dd_gather(dd, 2*sizeof(int), buf2, ibuf);
1408 if (DDMASTER(dd))
1410 ma->index[0] = 0;
1411 for (i = 0; i < dd->nnodes; i++)
1413 ma->ncg[i] = ma->ibuf[2*i];
1414 ma->nat[i] = ma->ibuf[2*i+1];
1415 ma->index[i+1] = ma->index[i] + ma->ncg[i];
1418 /* Make byte counts and indices */
1419 for (i = 0; i < dd->nnodes; i++)
1421 ma->ibuf[i] = ma->ncg[i]*sizeof(int);
1422 ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
1424 if (debug)
1426 fprintf(debug, "Initial charge group distribution: ");
1427 for (i = 0; i < dd->nnodes; i++)
1429 fprintf(debug, " %d", ma->ncg[i]);
1431 fprintf(debug, "\n");
1435 /* Collect the charge group indices on the master */
1436 dd_gatherv(dd,
1437 ncg_home*sizeof(int), cg,
1438 DDMASTER(dd) ? ma->ibuf : NULL,
1439 DDMASTER(dd) ? ma->ibuf+dd->nnodes : NULL,
1440 DDMASTER(dd) ? ma->cg : NULL);
1442 dd->comm->master_cg_ddp_count = state_local->ddp_count;
1445 static void dd_collect_vec_sendrecv(gmx_domdec_t *dd,
1446 rvec *lv, rvec *v)
1448 gmx_domdec_master_t *ma;
1449 int n, i, c, a, nalloc = 0;
1450 rvec *buf = NULL;
1451 t_block *cgs_gl;
1453 ma = dd->ma;
1455 if (!DDMASTER(dd))
1457 #ifdef GMX_MPI
1458 MPI_Send(lv, dd->nat_home*sizeof(rvec), MPI_BYTE, DDMASTERRANK(dd),
1459 dd->rank, dd->mpi_comm_all);
1460 #endif
1462 else
1464 /* Copy the master coordinates to the global array */
1465 cgs_gl = &dd->comm->cgs_gl;
1467 n = DDMASTERRANK(dd);
1468 a = 0;
1469 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1471 for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1473 copy_rvec(lv[a++], v[c]);
1477 for (n = 0; n < dd->nnodes; n++)
1479 if (n != dd->rank)
1481 if (ma->nat[n] > nalloc)
1483 nalloc = over_alloc_dd(ma->nat[n]);
1484 srenew(buf, nalloc);
1486 #ifdef GMX_MPI
1487 MPI_Recv(buf, ma->nat[n]*sizeof(rvec), MPI_BYTE, DDRANK(dd, n),
1488 n, dd->mpi_comm_all, MPI_STATUS_IGNORE);
1489 #endif
1490 a = 0;
1491 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1493 for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1495 copy_rvec(buf[a++], v[c]);
1500 sfree(buf);
1504 static void get_commbuffer_counts(gmx_domdec_t *dd,
1505 int **counts, int **disps)
1507 gmx_domdec_master_t *ma;
1508 int n;
1510 ma = dd->ma;
1512 /* Make the rvec count and displacment arrays */
1513 *counts = ma->ibuf;
1514 *disps = ma->ibuf + dd->nnodes;
1515 for (n = 0; n < dd->nnodes; n++)
1517 (*counts)[n] = ma->nat[n]*sizeof(rvec);
1518 (*disps)[n] = (n == 0 ? 0 : (*disps)[n-1] + (*counts)[n-1]);
1522 static void dd_collect_vec_gatherv(gmx_domdec_t *dd,
1523 rvec *lv, rvec *v)
1525 gmx_domdec_master_t *ma;
1526 int *rcounts = NULL, *disps = NULL;
1527 int n, i, c, a;
1528 rvec *buf = NULL;
1529 t_block *cgs_gl;
1531 ma = dd->ma;
1533 if (DDMASTER(dd))
1535 get_commbuffer_counts(dd, &rcounts, &disps);
1537 buf = ma->vbuf;
1540 dd_gatherv(dd, dd->nat_home*sizeof(rvec), lv, rcounts, disps, buf);
1542 if (DDMASTER(dd))
1544 cgs_gl = &dd->comm->cgs_gl;
1546 a = 0;
1547 for (n = 0; n < dd->nnodes; n++)
1549 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1551 for (c = cgs_gl->index[ma->cg[i]]; c < cgs_gl->index[ma->cg[i]+1]; c++)
1553 copy_rvec(buf[a++], v[c]);
1560 void dd_collect_vec(gmx_domdec_t *dd,
1561 t_state *state_local, rvec *lv, rvec *v)
1563 dd_collect_cg(dd, state_local);
1565 if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
1567 dd_collect_vec_sendrecv(dd, lv, v);
1569 else
1571 dd_collect_vec_gatherv(dd, lv, v);
1576 void dd_collect_state(gmx_domdec_t *dd,
1577 t_state *state_local, t_state *state)
1579 int est, i, j, nh;
1581 nh = state->nhchainlength;
1583 if (DDMASTER(dd))
1585 for (i = 0; i < efptNR; i++)
1587 state->lambda[i] = state_local->lambda[i];
1589 state->fep_state = state_local->fep_state;
1590 state->veta = state_local->veta;
1591 state->vol0 = state_local->vol0;
1592 copy_mat(state_local->box, state->box);
1593 copy_mat(state_local->boxv, state->boxv);
1594 copy_mat(state_local->svir_prev, state->svir_prev);
1595 copy_mat(state_local->fvir_prev, state->fvir_prev);
1596 copy_mat(state_local->pres_prev, state->pres_prev);
1598 for (i = 0; i < state_local->ngtc; i++)
1600 for (j = 0; j < nh; j++)
1602 state->nosehoover_xi[i*nh+j] = state_local->nosehoover_xi[i*nh+j];
1603 state->nosehoover_vxi[i*nh+j] = state_local->nosehoover_vxi[i*nh+j];
1605 state->therm_integral[i] = state_local->therm_integral[i];
1607 for (i = 0; i < state_local->nnhpres; i++)
1609 for (j = 0; j < nh; j++)
1611 state->nhpres_xi[i*nh+j] = state_local->nhpres_xi[i*nh+j];
1612 state->nhpres_vxi[i*nh+j] = state_local->nhpres_vxi[i*nh+j];
1616 for (est = 0; est < estNR; est++)
1618 if (EST_DISTR(est) && (state_local->flags & (1<<est)))
1620 switch (est)
1622 case estX:
1623 dd_collect_vec(dd, state_local, state_local->x, state->x);
1624 break;
1625 case estV:
1626 dd_collect_vec(dd, state_local, state_local->v, state->v);
1627 break;
1628 case estSDX:
1629 dd_collect_vec(dd, state_local, state_local->sd_X, state->sd_X);
1630 break;
1631 case estCGP:
1632 dd_collect_vec(dd, state_local, state_local->cg_p, state->cg_p);
1633 break;
1634 case estDISRE_INITF:
1635 case estDISRE_RM3TAV:
1636 case estORIRE_INITF:
1637 case estORIRE_DTAV:
1638 break;
1639 default:
1640 gmx_incons("Unknown state entry encountered in dd_collect_state");
1646 static void dd_realloc_state(t_state *state, rvec **f, int nalloc)
1648 int est;
1650 if (debug)
1652 fprintf(debug, "Reallocating state: currently %d, required %d, allocating %d\n", state->nalloc, nalloc, over_alloc_dd(nalloc));
1655 state->nalloc = over_alloc_dd(nalloc);
1657 for (est = 0; est < estNR; est++)
1659 if (EST_DISTR(est) && (state->flags & (1<<est)))
1661 switch (est)
1663 case estX:
1664 srenew(state->x, state->nalloc);
1665 break;
1666 case estV:
1667 srenew(state->v, state->nalloc);
1668 break;
1669 case estSDX:
1670 srenew(state->sd_X, state->nalloc);
1671 break;
1672 case estCGP:
1673 srenew(state->cg_p, state->nalloc);
1674 break;
1675 case estDISRE_INITF:
1676 case estDISRE_RM3TAV:
1677 case estORIRE_INITF:
1678 case estORIRE_DTAV:
1679 /* No reallocation required */
1680 break;
1681 default:
1682 gmx_incons("Unknown state entry encountered in dd_realloc_state");
1687 if (f != NULL)
1689 srenew(*f, state->nalloc);
1693 static void dd_check_alloc_ncg(t_forcerec *fr, t_state *state, rvec **f,
1694 int nalloc)
1696 if (nalloc > fr->cg_nalloc)
1698 if (debug)
1700 fprintf(debug, "Reallocating forcerec: currently %d, required %d, allocating %d\n", fr->cg_nalloc, nalloc, over_alloc_dd(nalloc));
1702 fr->cg_nalloc = over_alloc_dd(nalloc);
1703 srenew(fr->cginfo, fr->cg_nalloc);
1704 if (fr->cutoff_scheme == ecutsGROUP)
1706 srenew(fr->cg_cm, fr->cg_nalloc);
1709 if (fr->cutoff_scheme == ecutsVERLET && nalloc > state->nalloc)
1711 /* We don't use charge groups, we use x in state to set up
1712 * the atom communication.
1714 dd_realloc_state(state, f, nalloc);
1718 static void dd_distribute_vec_sendrecv(gmx_domdec_t *dd, t_block *cgs,
1719 rvec *v, rvec *lv)
1721 gmx_domdec_master_t *ma;
1722 int n, i, c, a, nalloc = 0;
1723 rvec *buf = NULL;
1725 if (DDMASTER(dd))
1727 ma = dd->ma;
1729 for (n = 0; n < dd->nnodes; n++)
1731 if (n != dd->rank)
1733 if (ma->nat[n] > nalloc)
1735 nalloc = over_alloc_dd(ma->nat[n]);
1736 srenew(buf, nalloc);
1738 /* Use lv as a temporary buffer */
1739 a = 0;
1740 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1742 for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1744 copy_rvec(v[c], buf[a++]);
1747 if (a != ma->nat[n])
1749 gmx_fatal(FARGS, "Internal error a (%d) != nat (%d)",
1750 a, ma->nat[n]);
1753 #ifdef GMX_MPI
1754 MPI_Send(buf, ma->nat[n]*sizeof(rvec), MPI_BYTE,
1755 DDRANK(dd, n), n, dd->mpi_comm_all);
1756 #endif
1759 sfree(buf);
1760 n = DDMASTERRANK(dd);
1761 a = 0;
1762 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1764 for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1766 copy_rvec(v[c], lv[a++]);
1770 else
1772 #ifdef GMX_MPI
1773 MPI_Recv(lv, dd->nat_home*sizeof(rvec), MPI_BYTE, DDMASTERRANK(dd),
1774 MPI_ANY_TAG, dd->mpi_comm_all, MPI_STATUS_IGNORE);
1775 #endif
1779 static void dd_distribute_vec_scatterv(gmx_domdec_t *dd, t_block *cgs,
1780 rvec *v, rvec *lv)
1782 gmx_domdec_master_t *ma;
1783 int *scounts = NULL, *disps = NULL;
1784 int n, i, c, a;
1785 rvec *buf = NULL;
1787 if (DDMASTER(dd))
1789 ma = dd->ma;
1791 get_commbuffer_counts(dd, &scounts, &disps);
1793 buf = ma->vbuf;
1794 a = 0;
1795 for (n = 0; n < dd->nnodes; n++)
1797 for (i = ma->index[n]; i < ma->index[n+1]; i++)
1799 for (c = cgs->index[ma->cg[i]]; c < cgs->index[ma->cg[i]+1]; c++)
1801 copy_rvec(v[c], buf[a++]);
1807 dd_scatterv(dd, scounts, disps, buf, dd->nat_home*sizeof(rvec), lv);
1810 static void dd_distribute_vec(gmx_domdec_t *dd, t_block *cgs, rvec *v, rvec *lv)
1812 if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
1814 dd_distribute_vec_sendrecv(dd, cgs, v, lv);
1816 else
1818 dd_distribute_vec_scatterv(dd, cgs, v, lv);
1822 static void dd_distribute_dfhist(gmx_domdec_t *dd, df_history_t *dfhist)
1824 int i;
1825 dd_bcast(dd, sizeof(int), &dfhist->bEquil);
1826 dd_bcast(dd, sizeof(int), &dfhist->nlambda);
1827 dd_bcast(dd, sizeof(real), &dfhist->wl_delta);
1829 if (dfhist->nlambda > 0)
1831 int nlam = dfhist->nlambda;
1832 dd_bcast(dd, sizeof(int)*nlam, dfhist->n_at_lam);
1833 dd_bcast(dd, sizeof(real)*nlam, dfhist->wl_histo);
1834 dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_weights);
1835 dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_dg);
1836 dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_minvar);
1837 dd_bcast(dd, sizeof(real)*nlam, dfhist->sum_variance);
1839 for (i = 0; i < nlam; i++)
1841 dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p[i]);
1842 dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m[i]);
1843 dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_p2[i]);
1844 dd_bcast(dd, sizeof(real)*nlam, dfhist->accum_m2[i]);
1845 dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij[i]);
1846 dd_bcast(dd, sizeof(real)*nlam, dfhist->Tij_empirical[i]);
1851 static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
1852 t_state *state, t_state *state_local,
1853 rvec **f)
1855 int i, j, nh;
1857 nh = state->nhchainlength;
1859 if (DDMASTER(dd))
1861 for (i = 0; i < efptNR; i++)
1863 state_local->lambda[i] = state->lambda[i];
1865 state_local->fep_state = state->fep_state;
1866 state_local->veta = state->veta;
1867 state_local->vol0 = state->vol0;
1868 copy_mat(state->box, state_local->box);
1869 copy_mat(state->box_rel, state_local->box_rel);
1870 copy_mat(state->boxv, state_local->boxv);
1871 copy_mat(state->svir_prev, state_local->svir_prev);
1872 copy_mat(state->fvir_prev, state_local->fvir_prev);
1873 copy_df_history(&state_local->dfhist, &state->dfhist);
1874 for (i = 0; i < state_local->ngtc; i++)
1876 for (j = 0; j < nh; j++)
1878 state_local->nosehoover_xi[i*nh+j] = state->nosehoover_xi[i*nh+j];
1879 state_local->nosehoover_vxi[i*nh+j] = state->nosehoover_vxi[i*nh+j];
1881 state_local->therm_integral[i] = state->therm_integral[i];
1883 for (i = 0; i < state_local->nnhpres; i++)
1885 for (j = 0; j < nh; j++)
1887 state_local->nhpres_xi[i*nh+j] = state->nhpres_xi[i*nh+j];
1888 state_local->nhpres_vxi[i*nh+j] = state->nhpres_vxi[i*nh+j];
1892 dd_bcast(dd, ((efptNR)*sizeof(real)), state_local->lambda);
1893 dd_bcast(dd, sizeof(int), &state_local->fep_state);
1894 dd_bcast(dd, sizeof(real), &state_local->veta);
1895 dd_bcast(dd, sizeof(real), &state_local->vol0);
1896 dd_bcast(dd, sizeof(state_local->box), state_local->box);
1897 dd_bcast(dd, sizeof(state_local->box_rel), state_local->box_rel);
1898 dd_bcast(dd, sizeof(state_local->boxv), state_local->boxv);
1899 dd_bcast(dd, sizeof(state_local->svir_prev), state_local->svir_prev);
1900 dd_bcast(dd, sizeof(state_local->fvir_prev), state_local->fvir_prev);
1901 dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_xi);
1902 dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_vxi);
1903 dd_bcast(dd, state_local->ngtc*sizeof(double), state_local->therm_integral);
1904 dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_xi);
1905 dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_vxi);
1907 /* communicate df_history -- required for restarting from checkpoint */
1908 dd_distribute_dfhist(dd, &state_local->dfhist);
1910 if (dd->nat_home > state_local->nalloc)
1912 dd_realloc_state(state_local, f, dd->nat_home);
1914 for (i = 0; i < estNR; i++)
1916 if (EST_DISTR(i) && (state_local->flags & (1<<i)))
1918 switch (i)
1920 case estX:
1921 dd_distribute_vec(dd, cgs, state->x, state_local->x);
1922 break;
1923 case estV:
1924 dd_distribute_vec(dd, cgs, state->v, state_local->v);
1925 break;
1926 case estSDX:
1927 dd_distribute_vec(dd, cgs, state->sd_X, state_local->sd_X);
1928 break;
1929 case estCGP:
1930 dd_distribute_vec(dd, cgs, state->cg_p, state_local->cg_p);
1931 break;
1932 case estDISRE_INITF:
1933 case estDISRE_RM3TAV:
1934 case estORIRE_INITF:
1935 case estORIRE_DTAV:
1936 /* Not implemented yet */
1937 break;
1938 default:
1939 gmx_incons("Unknown state entry encountered in dd_distribute_state");
1945 static char dim2char(int dim)
1947 char c = '?';
1949 switch (dim)
1951 case XX: c = 'X'; break;
1952 case YY: c = 'Y'; break;
1953 case ZZ: c = 'Z'; break;
1954 default: gmx_fatal(FARGS, "Unknown dim %d", dim);
1957 return c;
1960 static void write_dd_grid_pdb(const char *fn, gmx_int64_t step,
1961 gmx_domdec_t *dd, matrix box, gmx_ddbox_t *ddbox)
1963 rvec grid_s[2], *grid_r = NULL, cx, r;
1964 char fname[STRLEN], buf[22];
1965 FILE *out;
1966 int a, i, d, z, y, x;
1967 matrix tric;
1968 real vol;
1970 copy_rvec(dd->comm->cell_x0, grid_s[0]);
1971 copy_rvec(dd->comm->cell_x1, grid_s[1]);
1973 if (DDMASTER(dd))
1975 snew(grid_r, 2*dd->nnodes);
1978 dd_gather(dd, 2*sizeof(rvec), grid_s, DDMASTER(dd) ? grid_r : NULL);
1980 if (DDMASTER(dd))
1982 for (d = 0; d < DIM; d++)
1984 for (i = 0; i < DIM; i++)
1986 if (d == i)
1988 tric[d][i] = 1;
1990 else
1992 if (d < ddbox->npbcdim && dd->nc[d] > 1)
1994 tric[d][i] = box[i][d]/box[i][i];
1996 else
1998 tric[d][i] = 0;
2003 sprintf(fname, "%s_%s.pdb", fn, gmx_step_str(step, buf));
2004 out = gmx_fio_fopen(fname, "w");
2005 gmx_write_pdb_box(out, dd->bScrewPBC ? epbcSCREW : epbcXYZ, box);
2006 a = 1;
2007 for (i = 0; i < dd->nnodes; i++)
2009 vol = dd->nnodes/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
2010 for (d = 0; d < DIM; d++)
2012 vol *= grid_r[i*2+1][d] - grid_r[i*2][d];
2014 for (z = 0; z < 2; z++)
2016 for (y = 0; y < 2; y++)
2018 for (x = 0; x < 2; x++)
2020 cx[XX] = grid_r[i*2+x][XX];
2021 cx[YY] = grid_r[i*2+y][YY];
2022 cx[ZZ] = grid_r[i*2+z][ZZ];
2023 mvmul(tric, cx, r);
2024 gmx_fprintf_pdb_atomline(out, epdbATOM, a++, "CA", ' ', "GLY", ' ', i+1, ' ',
2025 10*r[XX], 10*r[YY], 10*r[ZZ], 1.0, vol, "");
2029 for (d = 0; d < DIM; d++)
2031 for (x = 0; x < 4; x++)
2033 switch (d)
2035 case 0: y = 1 + i*8 + 2*x; break;
2036 case 1: y = 1 + i*8 + 2*x - (x % 2); break;
2037 case 2: y = 1 + i*8 + x; break;
2039 fprintf(out, "%6s%5d%5d\n", "CONECT", y, y+(1<<d));
2043 gmx_fio_fclose(out);
2044 sfree(grid_r);
2048 void write_dd_pdb(const char *fn, gmx_int64_t step, const char *title,
2049 gmx_mtop_t *mtop, t_commrec *cr,
2050 int natoms, rvec x[], matrix box)
2052 char fname[STRLEN], buf[22];
2053 FILE *out;
2054 int i, ii, resnr, c;
2055 char *atomname, *resname;
2056 real b;
2057 gmx_domdec_t *dd;
2059 dd = cr->dd;
2060 if (natoms == -1)
2062 natoms = dd->comm->nat[ddnatVSITE];
2065 sprintf(fname, "%s_%s_n%d.pdb", fn, gmx_step_str(step, buf), cr->sim_nodeid);
2067 out = gmx_fio_fopen(fname, "w");
2069 fprintf(out, "TITLE %s\n", title);
2070 gmx_write_pdb_box(out, dd->bScrewPBC ? epbcSCREW : epbcXYZ, box);
2071 for (i = 0; i < natoms; i++)
2073 ii = dd->gatindex[i];
2074 gmx_mtop_atominfo_global(mtop, ii, &atomname, &resnr, &resname);
2075 if (i < dd->comm->nat[ddnatZONE])
2077 c = 0;
2078 while (i >= dd->cgindex[dd->comm->zones.cg_range[c+1]])
2080 c++;
2082 b = c;
2084 else if (i < dd->comm->nat[ddnatVSITE])
2086 b = dd->comm->zones.n;
2088 else
2090 b = dd->comm->zones.n + 1;
2092 gmx_fprintf_pdb_atomline(out, epdbATOM, ii+1, atomname, ' ', resname, ' ', resnr, ' ',
2093 10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ], 1.0, b, "");
2095 fprintf(out, "TER\n");
2097 gmx_fio_fclose(out);
2100 real dd_cutoff_multibody(const gmx_domdec_t *dd)
2102 gmx_domdec_comm_t *comm;
2103 int di;
2104 real r;
2106 comm = dd->comm;
2108 r = -1;
2109 if (comm->bInterCGBondeds)
2111 if (comm->cutoff_mbody > 0)
2113 r = comm->cutoff_mbody;
2115 else
2117 /* cutoff_mbody=0 means we do not have DLB */
2118 r = comm->cellsize_min[dd->dim[0]];
2119 for (di = 1; di < dd->ndim; di++)
2121 r = std::min(r, comm->cellsize_min[dd->dim[di]]);
2123 if (comm->bBondComm)
2125 r = std::max(r, comm->cutoff_mbody);
2127 else
2129 r = std::min(r, comm->cutoff);
2134 return r;
2137 real dd_cutoff_twobody(const gmx_domdec_t *dd)
2139 real r_mb;
2141 r_mb = dd_cutoff_multibody(dd);
2143 return std::max(dd->comm->cutoff, r_mb);
2147 static void dd_cart_coord2pmecoord(gmx_domdec_t *dd, ivec coord, ivec coord_pme)
2149 int nc, ntot;
2151 nc = dd->nc[dd->comm->cartpmedim];
2152 ntot = dd->comm->ntot[dd->comm->cartpmedim];
2153 copy_ivec(coord, coord_pme);
2154 coord_pme[dd->comm->cartpmedim] =
2155 nc + (coord[dd->comm->cartpmedim]*(ntot - nc) + (ntot - nc)/2)/nc;
2158 static int low_ddindex2pmeindex(int ndd, int npme, int ddindex)
2160 /* Here we assign a PME node to communicate with this DD node
2161 * by assuming that the major index of both is x.
2162 * We add cr->npmenodes/2 to obtain an even distribution.
2164 return (ddindex*npme + npme/2)/ndd;
2167 static int ddindex2pmeindex(const gmx_domdec_t *dd, int ddindex)
2169 return low_ddindex2pmeindex(dd->nnodes, dd->comm->npmenodes, ddindex);
2172 static int cr_ddindex2pmeindex(const t_commrec *cr, int ddindex)
2174 return low_ddindex2pmeindex(cr->dd->nnodes, cr->npmenodes, ddindex);
2177 static int *dd_pmenodes(t_commrec *cr)
2179 int *pmenodes;
2180 int n, i, p0, p1;
2182 snew(pmenodes, cr->npmenodes);
2183 n = 0;
2184 for (i = 0; i < cr->dd->nnodes; i++)
2186 p0 = cr_ddindex2pmeindex(cr, i);
2187 p1 = cr_ddindex2pmeindex(cr, i+1);
2188 if (i+1 == cr->dd->nnodes || p1 > p0)
2190 if (debug)
2192 fprintf(debug, "pmenode[%d] = %d\n", n, i+1+n);
2194 pmenodes[n] = i + 1 + n;
2195 n++;
2199 return pmenodes;
2202 static int gmx_ddcoord2pmeindex(t_commrec *cr, int x, int y, int z)
2204 gmx_domdec_t *dd;
2205 ivec coords;
2206 int slab;
2208 dd = cr->dd;
2210 if (dd->comm->bCartesian) {
2211 gmx_ddindex2xyz(dd->nc,ddindex,coords);
2212 dd_coords2pmecoords(dd,coords,coords_pme);
2213 copy_ivec(dd->ntot,nc);
2214 nc[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
2215 coords_pme[dd->cartpmedim] -= dd->nc[dd->cartpmedim];
2217 slab = (coords_pme[XX]*nc[YY] + coords_pme[YY])*nc[ZZ] + coords_pme[ZZ];
2218 } else {
2219 slab = (ddindex*cr->npmenodes + cr->npmenodes/2)/dd->nnodes;
2222 coords[XX] = x;
2223 coords[YY] = y;
2224 coords[ZZ] = z;
2225 slab = ddindex2pmeindex(dd, dd_index(dd->nc, coords));
2227 return slab;
2230 static int ddcoord2simnodeid(t_commrec *cr, int x, int y, int z)
2232 gmx_domdec_comm_t *comm;
2233 ivec coords;
2234 int ddindex, nodeid = -1;
2236 comm = cr->dd->comm;
2238 coords[XX] = x;
2239 coords[YY] = y;
2240 coords[ZZ] = z;
2241 if (comm->bCartesianPP_PME)
2243 #ifdef GMX_MPI
2244 MPI_Cart_rank(cr->mpi_comm_mysim, coords, &nodeid);
2245 #endif
2247 else
2249 ddindex = dd_index(cr->dd->nc, coords);
2250 if (comm->bCartesianPP)
2252 nodeid = comm->ddindex2simnodeid[ddindex];
2254 else
2256 if (comm->pmenodes)
2258 nodeid = ddindex + gmx_ddcoord2pmeindex(cr, x, y, z);
2260 else
2262 nodeid = ddindex;
2267 return nodeid;
2270 static int dd_simnode2pmenode(t_commrec *cr, int sim_nodeid)
2272 gmx_domdec_t *dd;
2273 gmx_domdec_comm_t *comm;
2274 int i;
2275 int pmenode = -1;
2277 dd = cr->dd;
2278 comm = dd->comm;
2280 /* This assumes a uniform x domain decomposition grid cell size */
2281 if (comm->bCartesianPP_PME)
2283 #ifdef GMX_MPI
2284 ivec coord, coord_pme;
2285 MPI_Cart_coords(cr->mpi_comm_mysim, sim_nodeid, DIM, coord);
2286 if (coord[comm->cartpmedim] < dd->nc[comm->cartpmedim])
2288 /* This is a PP node */
2289 dd_cart_coord2pmecoord(dd, coord, coord_pme);
2290 MPI_Cart_rank(cr->mpi_comm_mysim, coord_pme, &pmenode);
2292 #endif
2294 else if (comm->bCartesianPP)
2296 if (sim_nodeid < dd->nnodes)
2298 pmenode = dd->nnodes + ddindex2pmeindex(dd, sim_nodeid);
2301 else
2303 /* This assumes DD cells with identical x coordinates
2304 * are numbered sequentially.
2306 if (dd->comm->pmenodes == NULL)
2308 if (sim_nodeid < dd->nnodes)
2310 /* The DD index equals the nodeid */
2311 pmenode = dd->nnodes + ddindex2pmeindex(dd, sim_nodeid);
2314 else
2316 i = 0;
2317 while (sim_nodeid > dd->comm->pmenodes[i])
2319 i++;
2321 if (sim_nodeid < dd->comm->pmenodes[i])
2323 pmenode = dd->comm->pmenodes[i];
2328 return pmenode;
2331 void get_pme_nnodes(const gmx_domdec_t *dd,
2332 int *npmenodes_x, int *npmenodes_y)
2334 if (dd != NULL)
2336 *npmenodes_x = dd->comm->npmenodes_x;
2337 *npmenodes_y = dd->comm->npmenodes_y;
2339 else
2341 *npmenodes_x = 1;
2342 *npmenodes_y = 1;
2346 void get_pme_ddnodes(t_commrec *cr, int pmenodeid,
2347 int *nmy_ddnodes, int **my_ddnodes, int *node_peer)
2349 gmx_domdec_t *dd;
2350 int x, y, z;
2351 ivec coord, coord_pme;
2353 dd = cr->dd;
2355 snew(*my_ddnodes, (dd->nnodes+cr->npmenodes-1)/cr->npmenodes);
2357 *nmy_ddnodes = 0;
2358 for (x = 0; x < dd->nc[XX]; x++)
2360 for (y = 0; y < dd->nc[YY]; y++)
2362 for (z = 0; z < dd->nc[ZZ]; z++)
2364 if (dd->comm->bCartesianPP_PME)
2366 coord[XX] = x;
2367 coord[YY] = y;
2368 coord[ZZ] = z;
2369 dd_cart_coord2pmecoord(dd, coord, coord_pme);
2370 if (dd->ci[XX] == coord_pme[XX] &&
2371 dd->ci[YY] == coord_pme[YY] &&
2372 dd->ci[ZZ] == coord_pme[ZZ])
2374 (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr, x, y, z);
2377 else
2379 /* The slab corresponds to the nodeid in the PME group */
2380 if (gmx_ddcoord2pmeindex(cr, x, y, z) == pmenodeid)
2382 (*my_ddnodes)[(*nmy_ddnodes)++] = ddcoord2simnodeid(cr, x, y, z);
2389 /* The last PP-only node is the peer node */
2390 *node_peer = (*my_ddnodes)[*nmy_ddnodes-1];
2392 if (debug)
2394 fprintf(debug, "Receive coordinates from PP ranks:");
2395 for (x = 0; x < *nmy_ddnodes; x++)
2397 fprintf(debug, " %d", (*my_ddnodes)[x]);
2399 fprintf(debug, "\n");
2403 static gmx_bool receive_vir_ener(t_commrec *cr)
2405 gmx_domdec_comm_t *comm;
2406 int pmenode;
2407 gmx_bool bReceive;
2409 bReceive = TRUE;
2410 if (cr->npmenodes < cr->dd->nnodes)
2412 comm = cr->dd->comm;
2413 if (comm->bCartesianPP_PME)
2415 pmenode = dd_simnode2pmenode(cr, cr->sim_nodeid);
2416 #ifdef GMX_MPI
2417 ivec coords;
2418 MPI_Cart_coords(cr->mpi_comm_mysim, cr->sim_nodeid, DIM, coords);
2419 coords[comm->cartpmedim]++;
2420 if (coords[comm->cartpmedim] < cr->dd->nc[comm->cartpmedim])
2422 int rank;
2423 MPI_Cart_rank(cr->mpi_comm_mysim, coords, &rank);
2424 if (dd_simnode2pmenode(cr, rank) == pmenode)
2426 /* This is not the last PP node for pmenode */
2427 bReceive = FALSE;
2430 #endif
2432 else
2434 pmenode = dd_simnode2pmenode(cr, cr->sim_nodeid);
2435 if (cr->sim_nodeid+1 < cr->nnodes &&
2436 dd_simnode2pmenode(cr, cr->sim_nodeid+1) == pmenode)
2438 /* This is not the last PP node for pmenode */
2439 bReceive = FALSE;
2444 return bReceive;
2447 static void set_zones_ncg_home(gmx_domdec_t *dd)
2449 gmx_domdec_zones_t *zones;
2450 int i;
2452 zones = &dd->comm->zones;
2454 zones->cg_range[0] = 0;
2455 for (i = 1; i < zones->n+1; i++)
2457 zones->cg_range[i] = dd->ncg_home;
2459 /* zone_ncg1[0] should always be equal to ncg_home */
2460 dd->comm->zone_ncg1[0] = dd->ncg_home;
2463 static void rebuild_cgindex(gmx_domdec_t *dd,
2464 const int *gcgs_index, t_state *state)
2466 int nat, i, *ind, *dd_cg_gl, *cgindex, cg_gl;
2468 ind = state->cg_gl;
2469 dd_cg_gl = dd->index_gl;
2470 cgindex = dd->cgindex;
2471 nat = 0;
2472 cgindex[0] = nat;
2473 for (i = 0; i < state->ncg_gl; i++)
2475 cgindex[i] = nat;
2476 cg_gl = ind[i];
2477 dd_cg_gl[i] = cg_gl;
2478 nat += gcgs_index[cg_gl+1] - gcgs_index[cg_gl];
2480 cgindex[i] = nat;
2482 dd->ncg_home = state->ncg_gl;
2483 dd->nat_home = nat;
2485 set_zones_ncg_home(dd);
2488 static int ddcginfo(const cginfo_mb_t *cginfo_mb, int cg)
2490 while (cg >= cginfo_mb->cg_end)
2492 cginfo_mb++;
2495 return cginfo_mb->cginfo[(cg - cginfo_mb->cg_start) % cginfo_mb->cg_mod];
2498 static void dd_set_cginfo(int *index_gl, int cg0, int cg1,
2499 t_forcerec *fr, char *bLocalCG)
2501 cginfo_mb_t *cginfo_mb;
2502 int *cginfo;
2503 int cg;
2505 if (fr != NULL)
2507 cginfo_mb = fr->cginfo_mb;
2508 cginfo = fr->cginfo;
2510 for (cg = cg0; cg < cg1; cg++)
2512 cginfo[cg] = ddcginfo(cginfo_mb, index_gl[cg]);
2516 if (bLocalCG != NULL)
2518 for (cg = cg0; cg < cg1; cg++)
2520 bLocalCG[index_gl[cg]] = TRUE;
2525 static void make_dd_indices(gmx_domdec_t *dd,
2526 const int *gcgs_index, int cg_start)
2528 int nzone, zone, zone1, cg0, cg1, cg1_p1, cg, cg_gl, a, a_gl;
2529 int *zone2cg, *zone_ncg1, *index_gl, *gatindex;
2530 gmx_bool bCGs;
2532 if (dd->nat_tot > dd->gatindex_nalloc)
2534 dd->gatindex_nalloc = over_alloc_dd(dd->nat_tot);
2535 srenew(dd->gatindex, dd->gatindex_nalloc);
2538 nzone = dd->comm->zones.n;
2539 zone2cg = dd->comm->zones.cg_range;
2540 zone_ncg1 = dd->comm->zone_ncg1;
2541 index_gl = dd->index_gl;
2542 gatindex = dd->gatindex;
2543 bCGs = dd->comm->bCGs;
2545 if (zone2cg[1] != dd->ncg_home)
2547 gmx_incons("dd->ncg_zone is not up to date");
2550 /* Make the local to global and global to local atom index */
2551 a = dd->cgindex[cg_start];
2552 for (zone = 0; zone < nzone; zone++)
2554 if (zone == 0)
2556 cg0 = cg_start;
2558 else
2560 cg0 = zone2cg[zone];
2562 cg1 = zone2cg[zone+1];
2563 cg1_p1 = cg0 + zone_ncg1[zone];
2565 for (cg = cg0; cg < cg1; cg++)
2567 zone1 = zone;
2568 if (cg >= cg1_p1)
2570 /* Signal that this cg is from more than one pulse away */
2571 zone1 += nzone;
2573 cg_gl = index_gl[cg];
2574 if (bCGs)
2576 for (a_gl = gcgs_index[cg_gl]; a_gl < gcgs_index[cg_gl+1]; a_gl++)
2578 gatindex[a] = a_gl;
2579 ga2la_set(dd->ga2la, a_gl, a, zone1);
2580 a++;
2583 else
2585 gatindex[a] = cg_gl;
2586 ga2la_set(dd->ga2la, cg_gl, a, zone1);
2587 a++;
2593 static int check_bLocalCG(gmx_domdec_t *dd, int ncg_sys, const char *bLocalCG,
2594 const char *where)
2596 int i, ngl, nerr;
2598 nerr = 0;
2599 if (bLocalCG == NULL)
2601 return nerr;
2603 for (i = 0; i < dd->ncg_tot; i++)
2605 if (!bLocalCG[dd->index_gl[i]])
2607 fprintf(stderr,
2608 "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);
2609 nerr++;
2612 ngl = 0;
2613 for (i = 0; i < ncg_sys; i++)
2615 if (bLocalCG[i])
2617 ngl++;
2620 if (ngl != dd->ncg_tot)
2622 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);
2623 nerr++;
2626 return nerr;
2629 static void check_index_consistency(gmx_domdec_t *dd,
2630 int natoms_sys, int ncg_sys,
2631 const char *where)
2633 int nerr, ngl, i, a, cell;
2634 int *have;
2636 nerr = 0;
2638 if (dd->comm->DD_debug > 1)
2640 snew(have, natoms_sys);
2641 for (a = 0; a < dd->nat_tot; a++)
2643 if (have[dd->gatindex[a]] > 0)
2645 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);
2647 else
2649 have[dd->gatindex[a]] = a + 1;
2652 sfree(have);
2655 snew(have, dd->nat_tot);
2657 ngl = 0;
2658 for (i = 0; i < natoms_sys; i++)
2660 if (ga2la_get(dd->ga2la, i, &a, &cell))
2662 if (a >= dd->nat_tot)
2664 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);
2665 nerr++;
2667 else
2669 have[a] = 1;
2670 if (dd->gatindex[a] != i)
2672 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);
2673 nerr++;
2676 ngl++;
2679 if (ngl != dd->nat_tot)
2681 fprintf(stderr,
2682 "DD rank %d, %s: %d global atom indices, %d local atoms\n",
2683 dd->rank, where, ngl, dd->nat_tot);
2685 for (a = 0; a < dd->nat_tot; a++)
2687 if (have[a] == 0)
2689 fprintf(stderr,
2690 "DD rank %d, %s: local atom %d, global %d has no global index\n",
2691 dd->rank, where, a+1, dd->gatindex[a]+1);
2694 sfree(have);
2696 nerr += check_bLocalCG(dd, ncg_sys, dd->comm->bLocalCG, where);
2698 if (nerr > 0)
2700 gmx_fatal(FARGS, "DD rank %d, %s: %d atom/cg index inconsistencies",
2701 dd->rank, where, nerr);
2705 static void clear_dd_indices(gmx_domdec_t *dd, int cg_start, int a_start)
2707 int i;
2708 char *bLocalCG;
2710 if (a_start == 0)
2712 /* Clear the whole list without searching */
2713 ga2la_clear(dd->ga2la);
2715 else
2717 for (i = a_start; i < dd->nat_tot; i++)
2719 ga2la_del(dd->ga2la, dd->gatindex[i]);
2723 bLocalCG = dd->comm->bLocalCG;
2724 if (bLocalCG)
2726 for (i = cg_start; i < dd->ncg_tot; i++)
2728 bLocalCG[dd->index_gl[i]] = FALSE;
2732 dd_clear_local_vsite_indices(dd);
2734 if (dd->constraints)
2736 dd_clear_local_constraint_indices(dd);
2740 /* This function should be used for moving the domain boudaries during DLB,
2741 * for obtaining the minimum cell size. It checks the initially set limit
2742 * comm->cellsize_min, for bonded and initial non-bonded cut-offs,
2743 * and, possibly, a longer cut-off limit set for PME load balancing.
2745 static real cellsize_min_dlb(gmx_domdec_comm_t *comm, int dim_ind, int dim)
2747 real cellsize_min;
2749 cellsize_min = comm->cellsize_min[dim];
2751 if (!comm->bVacDLBNoLimit)
2753 /* The cut-off might have changed, e.g. by PME load balacning,
2754 * from the value used to set comm->cellsize_min, so check it.
2756 cellsize_min = std::max(cellsize_min, comm->cutoff/comm->cd[dim_ind].np_dlb);
2758 if (comm->bPMELoadBalDLBLimits)
2760 /* Check for the cut-off limit set by the PME load balancing */
2761 cellsize_min = std::max(cellsize_min, comm->PMELoadBal_max_cutoff/comm->cd[dim_ind].np_dlb);
2765 return cellsize_min;
2768 static real grid_jump_limit(gmx_domdec_comm_t *comm, real cutoff,
2769 int dim_ind)
2771 real grid_jump_limit;
2773 /* The distance between the boundaries of cells at distance
2774 * x+-1,y+-1 or y+-1,z+-1 is limited by the cut-off restrictions
2775 * and by the fact that cells should not be shifted by more than
2776 * half their size, such that cg's only shift by one cell
2777 * at redecomposition.
2779 grid_jump_limit = comm->cellsize_limit;
2780 if (!comm->bVacDLBNoLimit)
2782 if (comm->bPMELoadBalDLBLimits)
2784 cutoff = std::max(cutoff, comm->PMELoadBal_max_cutoff);
2786 grid_jump_limit = std::max(grid_jump_limit,
2787 cutoff/comm->cd[dim_ind].np);
2790 return grid_jump_limit;
2793 static gmx_bool check_grid_jump(gmx_int64_t step,
2794 gmx_domdec_t *dd,
2795 real cutoff,
2796 gmx_ddbox_t *ddbox,
2797 gmx_bool bFatal)
2799 gmx_domdec_comm_t *comm;
2800 int d, dim;
2801 real limit, bfac;
2802 gmx_bool bInvalid;
2804 bInvalid = FALSE;
2806 comm = dd->comm;
2808 for (d = 1; d < dd->ndim; d++)
2810 dim = dd->dim[d];
2811 limit = grid_jump_limit(comm, cutoff, d);
2812 bfac = ddbox->box_size[dim];
2813 if (ddbox->tric_dir[dim])
2815 bfac *= ddbox->skew_fac[dim];
2817 if ((comm->cell_f1[d] - comm->cell_f_max0[d])*bfac < limit ||
2818 (comm->cell_f0[d] - comm->cell_f_min1[d])*bfac > -limit)
2820 bInvalid = TRUE;
2822 if (bFatal)
2824 char buf[22];
2826 /* This error should never be triggered under normal
2827 * circumstances, but you never know ...
2829 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.",
2830 gmx_step_str(step, buf),
2831 dim2char(dim), dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
2836 return bInvalid;
2839 static int dd_load_count(gmx_domdec_comm_t *comm)
2841 return (comm->eFlop ? comm->flop_n : comm->cycl_n[ddCyclF]);
2844 static float dd_force_load(gmx_domdec_comm_t *comm)
2846 float load;
2848 if (comm->eFlop)
2850 load = comm->flop;
2851 if (comm->eFlop > 1)
2853 load *= 1.0 + (comm->eFlop - 1)*(0.1*rand()/RAND_MAX - 0.05);
2856 else
2858 load = comm->cycl[ddCyclF];
2859 if (comm->cycl_n[ddCyclF] > 1)
2861 /* Subtract the maximum of the last n cycle counts
2862 * to get rid of possible high counts due to other sources,
2863 * for instance system activity, that would otherwise
2864 * affect the dynamic load balancing.
2866 load -= comm->cycl_max[ddCyclF];
2869 #ifdef GMX_MPI
2870 if (comm->cycl_n[ddCyclWaitGPU] && comm->nrank_gpu_shared > 1)
2872 float gpu_wait, gpu_wait_sum;
2874 gpu_wait = comm->cycl[ddCyclWaitGPU];
2875 if (comm->cycl_n[ddCyclF] > 1)
2877 /* We should remove the WaitGPU time of the same MD step
2878 * as the one with the maximum F time, since the F time
2879 * and the wait time are not independent.
2880 * Furthermore, the step for the max F time should be chosen
2881 * the same on all ranks that share the same GPU.
2882 * But to keep the code simple, we remove the average instead.
2883 * The main reason for artificially long times at some steps
2884 * is spurious CPU activity or MPI time, so we don't expect
2885 * that changes in the GPU wait time matter a lot here.
2887 gpu_wait *= (comm->cycl_n[ddCyclF] - 1)/(float)comm->cycl_n[ddCyclF];
2889 /* Sum the wait times over the ranks that share the same GPU */
2890 MPI_Allreduce(&gpu_wait, &gpu_wait_sum, 1, MPI_FLOAT, MPI_SUM,
2891 comm->mpi_comm_gpu_shared);
2892 /* Replace the wait time by the average over the ranks */
2893 load += -gpu_wait + gpu_wait_sum/comm->nrank_gpu_shared;
2895 #endif
2898 return load;
2901 static void set_slb_pme_dim_f(gmx_domdec_t *dd, int dim, real **dim_f)
2903 gmx_domdec_comm_t *comm;
2904 int i;
2906 comm = dd->comm;
2908 snew(*dim_f, dd->nc[dim]+1);
2909 (*dim_f)[0] = 0;
2910 for (i = 1; i < dd->nc[dim]; i++)
2912 if (comm->slb_frac[dim])
2914 (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
2916 else
2918 (*dim_f)[i] = (real)i/(real)dd->nc[dim];
2921 (*dim_f)[dd->nc[dim]] = 1;
2924 static void init_ddpme(gmx_domdec_t *dd, gmx_ddpme_t *ddpme, int dimind)
2926 int pmeindex, slab, nso, i;
2927 ivec xyz;
2929 if (dimind == 0 && dd->dim[0] == YY && dd->comm->npmenodes_x == 1)
2931 ddpme->dim = YY;
2933 else
2935 ddpme->dim = dimind;
2937 ddpme->dim_match = (ddpme->dim == dd->dim[dimind]);
2939 ddpme->nslab = (ddpme->dim == 0 ?
2940 dd->comm->npmenodes_x :
2941 dd->comm->npmenodes_y);
2943 if (ddpme->nslab <= 1)
2945 return;
2948 nso = dd->comm->npmenodes/ddpme->nslab;
2949 /* Determine for each PME slab the PP location range for dimension dim */
2950 snew(ddpme->pp_min, ddpme->nslab);
2951 snew(ddpme->pp_max, ddpme->nslab);
2952 for (slab = 0; slab < ddpme->nslab; slab++)
2954 ddpme->pp_min[slab] = dd->nc[dd->dim[dimind]] - 1;
2955 ddpme->pp_max[slab] = 0;
2957 for (i = 0; i < dd->nnodes; i++)
2959 ddindex2xyz(dd->nc, i, xyz);
2960 /* For y only use our y/z slab.
2961 * This assumes that the PME x grid size matches the DD grid size.
2963 if (dimind == 0 || xyz[XX] == dd->ci[XX])
2965 pmeindex = ddindex2pmeindex(dd, i);
2966 if (dimind == 0)
2968 slab = pmeindex/nso;
2970 else
2972 slab = pmeindex % ddpme->nslab;
2974 ddpme->pp_min[slab] = std::min(ddpme->pp_min[slab], xyz[dimind]);
2975 ddpme->pp_max[slab] = std::max(ddpme->pp_max[slab], xyz[dimind]);
2979 set_slb_pme_dim_f(dd, ddpme->dim, &ddpme->slb_dim_f);
2982 int dd_pme_maxshift_x(gmx_domdec_t *dd)
2984 if (dd->comm->ddpme[0].dim == XX)
2986 return dd->comm->ddpme[0].maxshift;
2988 else
2990 return 0;
2994 int dd_pme_maxshift_y(gmx_domdec_t *dd)
2996 if (dd->comm->ddpme[0].dim == YY)
2998 return dd->comm->ddpme[0].maxshift;
3000 else if (dd->comm->npmedecompdim >= 2 && dd->comm->ddpme[1].dim == YY)
3002 return dd->comm->ddpme[1].maxshift;
3004 else
3006 return 0;
3010 static void set_pme_maxshift(gmx_domdec_t *dd, gmx_ddpme_t *ddpme,
3011 gmx_bool bUniform, gmx_ddbox_t *ddbox, real *cell_f)
3013 gmx_domdec_comm_t *comm;
3014 int nc, ns, s;
3015 int *xmin, *xmax;
3016 real range, pme_boundary;
3017 int sh;
3019 comm = dd->comm;
3020 nc = dd->nc[ddpme->dim];
3021 ns = ddpme->nslab;
3023 if (!ddpme->dim_match)
3025 /* PP decomposition is not along dim: the worst situation */
3026 sh = ns/2;
3028 else if (ns <= 3 || (bUniform && ns == nc))
3030 /* The optimal situation */
3031 sh = 1;
3033 else
3035 /* We need to check for all pme nodes which nodes they
3036 * could possibly need to communicate with.
3038 xmin = ddpme->pp_min;
3039 xmax = ddpme->pp_max;
3040 /* Allow for atoms to be maximally 2/3 times the cut-off
3041 * out of their DD cell. This is a reasonable balance between
3042 * between performance and support for most charge-group/cut-off
3043 * combinations.
3045 range = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
3046 /* Avoid extra communication when we are exactly at a boundary */
3047 range *= 0.999;
3049 sh = 1;
3050 for (s = 0; s < ns; s++)
3052 /* PME slab s spreads atoms between box frac. s/ns and (s+1)/ns */
3053 pme_boundary = (real)s/ns;
3054 while (sh+1 < ns &&
3055 ((s-(sh+1) >= 0 &&
3056 cell_f[xmax[s-(sh+1) ]+1] + range > pme_boundary) ||
3057 (s-(sh+1) < 0 &&
3058 cell_f[xmax[s-(sh+1)+ns]+1] - 1 + range > pme_boundary)))
3060 sh++;
3062 pme_boundary = (real)(s+1)/ns;
3063 while (sh+1 < ns &&
3064 ((s+(sh+1) < ns &&
3065 cell_f[xmin[s+(sh+1) ] ] - range < pme_boundary) ||
3066 (s+(sh+1) >= ns &&
3067 cell_f[xmin[s+(sh+1)-ns] ] + 1 - range < pme_boundary)))
3069 sh++;
3074 ddpme->maxshift = sh;
3076 if (debug)
3078 fprintf(debug, "PME slab communication range for dim %d is %d\n",
3079 ddpme->dim, ddpme->maxshift);
3083 static void check_box_size(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
3085 int d, dim;
3087 for (d = 0; d < dd->ndim; d++)
3089 dim = dd->dim[d];
3090 if (dim < ddbox->nboundeddim &&
3091 ddbox->box_size[dim]*ddbox->skew_fac[dim] <
3092 dd->nc[dim]*dd->comm->cellsize_limit*DD_CELL_MARGIN)
3094 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",
3095 dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim],
3096 dd->nc[dim], dd->comm->cellsize_limit);
3101 enum {
3102 setcellsizeslbLOCAL, setcellsizeslbMASTER, setcellsizeslbPULSE_ONLY
3105 /* Set the domain boundaries. Use for static (or no) load balancing,
3106 * and also for the starting state for dynamic load balancing.
3107 * setmode determine if and where the boundaries are stored, use enum above.
3108 * Returns the number communication pulses in npulse.
3110 static void set_dd_cell_sizes_slb(gmx_domdec_t *dd, gmx_ddbox_t *ddbox,
3111 int setmode, ivec npulse)
3113 gmx_domdec_comm_t *comm;
3114 int d, j;
3115 rvec cellsize_min;
3116 real *cell_x, cell_dx, cellsize;
3118 comm = dd->comm;
3120 for (d = 0; d < DIM; d++)
3122 cellsize_min[d] = ddbox->box_size[d]*ddbox->skew_fac[d];
3123 npulse[d] = 1;
3124 if (dd->nc[d] == 1 || comm->slb_frac[d] == NULL)
3126 /* Uniform grid */
3127 cell_dx = ddbox->box_size[d]/dd->nc[d];
3128 switch (setmode)
3130 case setcellsizeslbMASTER:
3131 for (j = 0; j < dd->nc[d]+1; j++)
3133 dd->ma->cell_x[d][j] = ddbox->box0[d] + j*cell_dx;
3135 break;
3136 case setcellsizeslbLOCAL:
3137 comm->cell_x0[d] = ddbox->box0[d] + (dd->ci[d] )*cell_dx;
3138 comm->cell_x1[d] = ddbox->box0[d] + (dd->ci[d]+1)*cell_dx;
3139 break;
3140 default:
3141 break;
3143 cellsize = cell_dx*ddbox->skew_fac[d];
3144 while (cellsize*npulse[d] < comm->cutoff)
3146 npulse[d]++;
3148 cellsize_min[d] = cellsize;
3150 else
3152 /* Statically load balanced grid */
3153 /* Also when we are not doing a master distribution we determine
3154 * all cell borders in a loop to obtain identical values
3155 * to the master distribution case and to determine npulse.
3157 if (setmode == setcellsizeslbMASTER)
3159 cell_x = dd->ma->cell_x[d];
3161 else
3163 snew(cell_x, dd->nc[d]+1);
3165 cell_x[0] = ddbox->box0[d];
3166 for (j = 0; j < dd->nc[d]; j++)
3168 cell_dx = ddbox->box_size[d]*comm->slb_frac[d][j];
3169 cell_x[j+1] = cell_x[j] + cell_dx;
3170 cellsize = cell_dx*ddbox->skew_fac[d];
3171 while (cellsize*npulse[d] < comm->cutoff &&
3172 npulse[d] < dd->nc[d]-1)
3174 npulse[d]++;
3176 cellsize_min[d] = std::min(cellsize_min[d], cellsize);
3178 if (setmode == setcellsizeslbLOCAL)
3180 comm->cell_x0[d] = cell_x[dd->ci[d]];
3181 comm->cell_x1[d] = cell_x[dd->ci[d]+1];
3183 if (setmode != setcellsizeslbMASTER)
3185 sfree(cell_x);
3188 /* The following limitation is to avoid that a cell would receive
3189 * some of its own home charge groups back over the periodic boundary.
3190 * Double charge groups cause trouble with the global indices.
3192 if (d < ddbox->npbcdim &&
3193 dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
3195 char error_string[STRLEN];
3197 sprintf(error_string,
3198 "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",
3199 dim2char(d), ddbox->box_size[d], ddbox->skew_fac[d],
3200 comm->cutoff,
3201 dd->nc[d], dd->nc[d],
3202 dd->nnodes > dd->nc[d] ? "cells" : "ranks");
3204 if (setmode == setcellsizeslbLOCAL)
3206 gmx_fatal_collective(FARGS, NULL, dd, error_string);
3208 else
3210 gmx_fatal(FARGS, error_string);
3215 if (!comm->bDynLoadBal)
3217 copy_rvec(cellsize_min, comm->cellsize_min);
3220 for (d = 0; d < comm->npmedecompdim; d++)
3222 set_pme_maxshift(dd, &comm->ddpme[d],
3223 comm->slb_frac[dd->dim[d]] == NULL, ddbox,
3224 comm->ddpme[d].slb_dim_f);
3229 static void dd_cell_sizes_dlb_root_enforce_limits(gmx_domdec_t *dd,
3230 int d, int dim, gmx_domdec_root_t *root,
3231 gmx_ddbox_t *ddbox,
3232 gmx_bool bUniform, gmx_int64_t step, real cellsize_limit_f, int range[])
3234 gmx_domdec_comm_t *comm;
3235 int ncd, i, j, nmin, nmin_old;
3236 gmx_bool bLimLo, bLimHi;
3237 real *cell_size;
3238 real fac, halfway, cellsize_limit_f_i, region_size;
3239 gmx_bool bPBC, bLastHi = FALSE;
3240 int nrange[] = {range[0], range[1]};
3242 region_size = root->cell_f[range[1]]-root->cell_f[range[0]];
3244 comm = dd->comm;
3246 ncd = dd->nc[dim];
3248 bPBC = (dim < ddbox->npbcdim);
3250 cell_size = root->buf_ncd;
3252 if (debug)
3254 fprintf(debug, "enforce_limits: %d %d\n", range[0], range[1]);
3257 /* First we need to check if the scaling does not make cells
3258 * smaller than the smallest allowed size.
3259 * We need to do this iteratively, since if a cell is too small,
3260 * it needs to be enlarged, which makes all the other cells smaller,
3261 * which could in turn make another cell smaller than allowed.
3263 for (i = range[0]; i < range[1]; i++)
3265 root->bCellMin[i] = FALSE;
3267 nmin = 0;
3270 nmin_old = nmin;
3271 /* We need the total for normalization */
3272 fac = 0;
3273 for (i = range[0]; i < range[1]; i++)
3275 if (root->bCellMin[i] == FALSE)
3277 fac += cell_size[i];
3280 fac = ( region_size - nmin*cellsize_limit_f)/fac; /* substracting cells already set to cellsize_limit_f */
3281 /* Determine the cell boundaries */
3282 for (i = range[0]; i < range[1]; i++)
3284 if (root->bCellMin[i] == FALSE)
3286 cell_size[i] *= fac;
3287 if (!bPBC && (i == 0 || i == dd->nc[dim] -1))
3289 cellsize_limit_f_i = 0;
3291 else
3293 cellsize_limit_f_i = cellsize_limit_f;
3295 if (cell_size[i] < cellsize_limit_f_i)
3297 root->bCellMin[i] = TRUE;
3298 cell_size[i] = cellsize_limit_f_i;
3299 nmin++;
3302 root->cell_f[i+1] = root->cell_f[i] + cell_size[i];
3305 while (nmin > nmin_old);
3307 i = range[1]-1;
3308 cell_size[i] = root->cell_f[i+1] - root->cell_f[i];
3309 /* For this check we should not use DD_CELL_MARGIN,
3310 * but a slightly smaller factor,
3311 * since rounding could get use below the limit.
3313 if (bPBC && cell_size[i] < cellsize_limit_f*DD_CELL_MARGIN2/DD_CELL_MARGIN)
3315 char buf[22];
3316 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",
3317 gmx_step_str(step, buf),
3318 dim2char(dim), ddbox->box_size[dim], ddbox->skew_fac[dim],
3319 ncd, comm->cellsize_min[dim]);
3322 root->bLimited = (nmin > 0) || (range[0] > 0) || (range[1] < ncd);
3324 if (!bUniform)
3326 /* Check if the boundary did not displace more than halfway
3327 * each of the cells it bounds, as this could cause problems,
3328 * especially when the differences between cell sizes are large.
3329 * If changes are applied, they will not make cells smaller
3330 * than the cut-off, as we check all the boundaries which
3331 * might be affected by a change and if the old state was ok,
3332 * the cells will at most be shrunk back to their old size.
3334 for (i = range[0]+1; i < range[1]; i++)
3336 halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i-1]);
3337 if (root->cell_f[i] < halfway)
3339 root->cell_f[i] = halfway;
3340 /* Check if the change also causes shifts of the next boundaries */
3341 for (j = i+1; j < range[1]; j++)
3343 if (root->cell_f[j] < root->cell_f[j-1] + cellsize_limit_f)
3345 root->cell_f[j] = root->cell_f[j-1] + cellsize_limit_f;
3349 halfway = 0.5*(root->old_cell_f[i] + root->old_cell_f[i+1]);
3350 if (root->cell_f[i] > halfway)
3352 root->cell_f[i] = halfway;
3353 /* Check if the change also causes shifts of the next boundaries */
3354 for (j = i-1; j >= range[0]+1; j--)
3356 if (root->cell_f[j] > root->cell_f[j+1] - cellsize_limit_f)
3358 root->cell_f[j] = root->cell_f[j+1] - cellsize_limit_f;
3365 /* nrange is defined as [lower, upper) range for new call to enforce_limits */
3366 /* find highest violation of LimLo (a) and the following violation of LimHi (thus the lowest following) (b)
3367 * then call enforce_limits for (oldb,a), (a,b). In the next step: (b,nexta). oldb and nexta can be the boundaries.
3368 * for a and b nrange is used */
3369 if (d > 0)
3371 /* Take care of the staggering of the cell boundaries */
3372 if (bUniform)
3374 for (i = range[0]; i < range[1]; i++)
3376 root->cell_f_max0[i] = root->cell_f[i];
3377 root->cell_f_min1[i] = root->cell_f[i+1];
3380 else
3382 for (i = range[0]+1; i < range[1]; i++)
3384 bLimLo = (root->cell_f[i] < root->bound_min[i]);
3385 bLimHi = (root->cell_f[i] > root->bound_max[i]);
3386 if (bLimLo && bLimHi)
3388 /* Both limits violated, try the best we can */
3389 /* For this case we split the original range (range) in two parts and care about the other limitiations in the next iteration. */
3390 root->cell_f[i] = 0.5*(root->bound_min[i] + root->bound_max[i]);
3391 nrange[0] = range[0];
3392 nrange[1] = i;
3393 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3395 nrange[0] = i;
3396 nrange[1] = range[1];
3397 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3399 return;
3401 else if (bLimLo)
3403 /* root->cell_f[i] = root->bound_min[i]; */
3404 nrange[1] = i; /* only store violation location. There could be a LimLo violation following with an higher index */
3405 bLastHi = FALSE;
3407 else if (bLimHi && !bLastHi)
3409 bLastHi = TRUE;
3410 if (nrange[1] < range[1]) /* found a LimLo before */
3412 root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
3413 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3414 nrange[0] = nrange[1];
3416 root->cell_f[i] = root->bound_max[i];
3417 nrange[1] = i;
3418 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3419 nrange[0] = i;
3420 nrange[1] = range[1];
3423 if (nrange[1] < range[1]) /* found last a LimLo */
3425 root->cell_f[nrange[1]] = root->bound_min[nrange[1]];
3426 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3427 nrange[0] = nrange[1];
3428 nrange[1] = range[1];
3429 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3431 else if (nrange[0] > range[0]) /* found at least one LimHi */
3433 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, nrange);
3440 static void set_dd_cell_sizes_dlb_root(gmx_domdec_t *dd,
3441 int d, int dim, gmx_domdec_root_t *root,
3442 gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3443 gmx_bool bUniform, gmx_int64_t step)
3445 gmx_domdec_comm_t *comm;
3446 int ncd, d1, i, pos;
3447 real *cell_size;
3448 real load_aver, load_i, imbalance, change, change_max, sc;
3449 real cellsize_limit_f, dist_min_f, dist_min_f_hard, space;
3450 real change_limit;
3451 real relax = 0.5;
3452 gmx_bool bPBC;
3453 int range[] = { 0, 0 };
3455 comm = dd->comm;
3457 /* Convert the maximum change from the input percentage to a fraction */
3458 change_limit = comm->dlb_scale_lim*0.01;
3460 ncd = dd->nc[dim];
3462 bPBC = (dim < ddbox->npbcdim);
3464 cell_size = root->buf_ncd;
3466 /* Store the original boundaries */
3467 for (i = 0; i < ncd+1; i++)
3469 root->old_cell_f[i] = root->cell_f[i];
3471 if (bUniform)
3473 for (i = 0; i < ncd; i++)
3475 cell_size[i] = 1.0/ncd;
3478 else if (dd_load_count(comm) > 0)
3480 load_aver = comm->load[d].sum_m/ncd;
3481 change_max = 0;
3482 for (i = 0; i < ncd; i++)
3484 /* Determine the relative imbalance of cell i */
3485 load_i = comm->load[d].load[i*comm->load[d].nload+2];
3486 imbalance = (load_i - load_aver)/(load_aver > 0 ? load_aver : 1);
3487 /* Determine the change of the cell size using underrelaxation */
3488 change = -relax*imbalance;
3489 change_max = std::max(change_max, std::max(change, -change));
3491 /* Limit the amount of scaling.
3492 * We need to use the same rescaling for all cells in one row,
3493 * otherwise the load balancing might not converge.
3495 sc = relax;
3496 if (change_max > change_limit)
3498 sc *= change_limit/change_max;
3500 for (i = 0; i < ncd; i++)
3502 /* Determine the relative imbalance of cell i */
3503 load_i = comm->load[d].load[i*comm->load[d].nload+2];
3504 imbalance = (load_i - load_aver)/(load_aver > 0 ? load_aver : 1);
3505 /* Determine the change of the cell size using underrelaxation */
3506 change = -sc*imbalance;
3507 cell_size[i] = (root->cell_f[i+1]-root->cell_f[i])*(1 + change);
3511 cellsize_limit_f = cellsize_min_dlb(comm, d, dim)/ddbox->box_size[dim];
3512 cellsize_limit_f *= DD_CELL_MARGIN;
3513 dist_min_f_hard = grid_jump_limit(comm, comm->cutoff, d)/ddbox->box_size[dim];
3514 dist_min_f = dist_min_f_hard * DD_CELL_MARGIN;
3515 if (ddbox->tric_dir[dim])
3517 cellsize_limit_f /= ddbox->skew_fac[dim];
3518 dist_min_f /= ddbox->skew_fac[dim];
3520 if (bDynamicBox && d > 0)
3522 dist_min_f *= DD_PRES_SCALE_MARGIN;
3524 if (d > 0 && !bUniform)
3526 /* Make sure that the grid is not shifted too much */
3527 for (i = 1; i < ncd; i++)
3529 if (root->cell_f_min1[i] - root->cell_f_max0[i-1] < 2 * dist_min_f_hard)
3531 gmx_incons("Inconsistent DD boundary staggering limits!");
3533 root->bound_min[i] = root->cell_f_max0[i-1] + dist_min_f;
3534 space = root->cell_f[i] - (root->cell_f_max0[i-1] + dist_min_f);
3535 if (space > 0)
3537 root->bound_min[i] += 0.5*space;
3539 root->bound_max[i] = root->cell_f_min1[i] - dist_min_f;
3540 space = root->cell_f[i] - (root->cell_f_min1[i] - dist_min_f);
3541 if (space < 0)
3543 root->bound_max[i] += 0.5*space;
3545 if (debug)
3547 fprintf(debug,
3548 "dim %d boundary %d %.3f < %.3f < %.3f < %.3f < %.3f\n",
3549 d, i,
3550 root->cell_f_max0[i-1] + dist_min_f,
3551 root->bound_min[i], root->cell_f[i], root->bound_max[i],
3552 root->cell_f_min1[i] - dist_min_f);
3556 range[1] = ncd;
3557 root->cell_f[0] = 0;
3558 root->cell_f[ncd] = 1;
3559 dd_cell_sizes_dlb_root_enforce_limits(dd, d, dim, root, ddbox, bUniform, step, cellsize_limit_f, range);
3562 /* After the checks above, the cells should obey the cut-off
3563 * restrictions, but it does not hurt to check.
3565 for (i = 0; i < ncd; i++)
3567 if (debug)
3569 fprintf(debug, "Relative bounds dim %d cell %d: %f %f\n",
3570 dim, i, root->cell_f[i], root->cell_f[i+1]);
3573 if ((bPBC || (i != 0 && i != dd->nc[dim]-1)) &&
3574 root->cell_f[i+1] - root->cell_f[i] <
3575 cellsize_limit_f/DD_CELL_MARGIN)
3577 char buf[22];
3578 fprintf(stderr,
3579 "\nWARNING step %s: direction %c, cell %d too small: %f\n",
3580 gmx_step_str(step, buf), dim2char(dim), i,
3581 (root->cell_f[i+1] - root->cell_f[i])
3582 *ddbox->box_size[dim]*ddbox->skew_fac[dim]);
3586 pos = ncd + 1;
3587 /* Store the cell boundaries of the lower dimensions at the end */
3588 for (d1 = 0; d1 < d; d1++)
3590 root->cell_f[pos++] = comm->cell_f0[d1];
3591 root->cell_f[pos++] = comm->cell_f1[d1];
3594 if (d < comm->npmedecompdim)
3596 /* The master determines the maximum shift for
3597 * the coordinate communication between separate PME nodes.
3599 set_pme_maxshift(dd, &comm->ddpme[d], bUniform, ddbox, root->cell_f);
3601 root->cell_f[pos++] = comm->ddpme[0].maxshift;
3602 if (d >= 1)
3604 root->cell_f[pos++] = comm->ddpme[1].maxshift;
3608 static void relative_to_absolute_cell_bounds(gmx_domdec_t *dd,
3609 gmx_ddbox_t *ddbox, int dimind)
3611 gmx_domdec_comm_t *comm;
3612 int dim;
3614 comm = dd->comm;
3616 /* Set the cell dimensions */
3617 dim = dd->dim[dimind];
3618 comm->cell_x0[dim] = comm->cell_f0[dimind]*ddbox->box_size[dim];
3619 comm->cell_x1[dim] = comm->cell_f1[dimind]*ddbox->box_size[dim];
3620 if (dim >= ddbox->nboundeddim)
3622 comm->cell_x0[dim] += ddbox->box0[dim];
3623 comm->cell_x1[dim] += ddbox->box0[dim];
3627 static void distribute_dd_cell_sizes_dlb(gmx_domdec_t *dd,
3628 int d, int dim, real *cell_f_row,
3629 gmx_ddbox_t *ddbox)
3631 gmx_domdec_comm_t *comm;
3632 int d1, pos;
3634 comm = dd->comm;
3636 #ifdef GMX_MPI
3637 /* Each node would only need to know two fractions,
3638 * but it is probably cheaper to broadcast the whole array.
3640 MPI_Bcast(cell_f_row, DD_CELL_F_SIZE(dd, d)*sizeof(real), MPI_BYTE,
3641 0, comm->mpi_comm_load[d]);
3642 #endif
3643 /* Copy the fractions for this dimension from the buffer */
3644 comm->cell_f0[d] = cell_f_row[dd->ci[dim] ];
3645 comm->cell_f1[d] = cell_f_row[dd->ci[dim]+1];
3646 /* The whole array was communicated, so set the buffer position */
3647 pos = dd->nc[dim] + 1;
3648 for (d1 = 0; d1 <= d; d1++)
3650 if (d1 < d)
3652 /* Copy the cell fractions of the lower dimensions */
3653 comm->cell_f0[d1] = cell_f_row[pos++];
3654 comm->cell_f1[d1] = cell_f_row[pos++];
3656 relative_to_absolute_cell_bounds(dd, ddbox, d1);
3658 /* Convert the communicated shift from float to int */
3659 comm->ddpme[0].maxshift = (int)(cell_f_row[pos++] + 0.5);
3660 if (d >= 1)
3662 comm->ddpme[1].maxshift = (int)(cell_f_row[pos++] + 0.5);
3666 static void set_dd_cell_sizes_dlb_change(gmx_domdec_t *dd,
3667 gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3668 gmx_bool bUniform, gmx_int64_t step)
3670 gmx_domdec_comm_t *comm;
3671 int d, dim, d1;
3672 gmx_bool bRowMember, bRowRoot;
3673 real *cell_f_row;
3675 comm = dd->comm;
3677 for (d = 0; d < dd->ndim; d++)
3679 dim = dd->dim[d];
3680 bRowMember = TRUE;
3681 bRowRoot = TRUE;
3682 for (d1 = d; d1 < dd->ndim; d1++)
3684 if (dd->ci[dd->dim[d1]] > 0)
3686 if (d1 != d)
3688 bRowMember = FALSE;
3690 bRowRoot = FALSE;
3693 if (bRowMember)
3695 if (bRowRoot)
3697 set_dd_cell_sizes_dlb_root(dd, d, dim, comm->root[d],
3698 ddbox, bDynamicBox, bUniform, step);
3699 cell_f_row = comm->root[d]->cell_f;
3701 else
3703 cell_f_row = comm->cell_f_row;
3705 distribute_dd_cell_sizes_dlb(dd, d, dim, cell_f_row, ddbox);
3710 static void set_dd_cell_sizes_dlb_nochange(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
3712 int d;
3714 /* This function assumes the box is static and should therefore
3715 * not be called when the box has changed since the last
3716 * call to dd_partition_system.
3718 for (d = 0; d < dd->ndim; d++)
3720 relative_to_absolute_cell_bounds(dd, ddbox, d);
3726 static void set_dd_cell_sizes_dlb(gmx_domdec_t *dd,
3727 gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3728 gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
3729 gmx_wallcycle_t wcycle)
3731 gmx_domdec_comm_t *comm;
3732 int dim;
3734 comm = dd->comm;
3736 if (bDoDLB)
3738 wallcycle_start(wcycle, ewcDDCOMMBOUND);
3739 set_dd_cell_sizes_dlb_change(dd, ddbox, bDynamicBox, bUniform, step);
3740 wallcycle_stop(wcycle, ewcDDCOMMBOUND);
3742 else if (bDynamicBox)
3744 set_dd_cell_sizes_dlb_nochange(dd, ddbox);
3747 /* Set the dimensions for which no DD is used */
3748 for (dim = 0; dim < DIM; dim++)
3750 if (dd->nc[dim] == 1)
3752 comm->cell_x0[dim] = 0;
3753 comm->cell_x1[dim] = ddbox->box_size[dim];
3754 if (dim >= ddbox->nboundeddim)
3756 comm->cell_x0[dim] += ddbox->box0[dim];
3757 comm->cell_x1[dim] += ddbox->box0[dim];
3763 static void realloc_comm_ind(gmx_domdec_t *dd, ivec npulse)
3765 int d, np, i;
3766 gmx_domdec_comm_dim_t *cd;
3768 for (d = 0; d < dd->ndim; d++)
3770 cd = &dd->comm->cd[d];
3771 np = npulse[dd->dim[d]];
3772 if (np > cd->np_nalloc)
3774 if (debug)
3776 fprintf(debug, "(Re)allocing cd for %c to %d pulses\n",
3777 dim2char(dd->dim[d]), np);
3779 if (DDMASTER(dd) && cd->np_nalloc > 0)
3781 fprintf(stderr, "\nIncreasing the number of cell to communicate in dimension %c to %d for the first time\n", dim2char(dd->dim[d]), np);
3783 srenew(cd->ind, np);
3784 for (i = cd->np_nalloc; i < np; i++)
3786 cd->ind[i].index = NULL;
3787 cd->ind[i].nalloc = 0;
3789 cd->np_nalloc = np;
3791 cd->np = np;
3796 static void set_dd_cell_sizes(gmx_domdec_t *dd,
3797 gmx_ddbox_t *ddbox, gmx_bool bDynamicBox,
3798 gmx_bool bUniform, gmx_bool bDoDLB, gmx_int64_t step,
3799 gmx_wallcycle_t wcycle)
3801 gmx_domdec_comm_t *comm;
3802 int d;
3803 ivec npulse;
3805 comm = dd->comm;
3807 /* Copy the old cell boundaries for the cg displacement check */
3808 copy_rvec(comm->cell_x0, comm->old_cell_x0);
3809 copy_rvec(comm->cell_x1, comm->old_cell_x1);
3811 if (comm->bDynLoadBal)
3813 if (DDMASTER(dd))
3815 check_box_size(dd, ddbox);
3817 set_dd_cell_sizes_dlb(dd, ddbox, bDynamicBox, bUniform, bDoDLB, step, wcycle);
3819 else
3821 set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbLOCAL, npulse);
3822 realloc_comm_ind(dd, npulse);
3825 if (debug)
3827 for (d = 0; d < DIM; d++)
3829 fprintf(debug, "cell_x[%d] %f - %f skew_fac %f\n",
3830 d, comm->cell_x0[d], comm->cell_x1[d], ddbox->skew_fac[d]);
3835 static void comm_dd_ns_cell_sizes(gmx_domdec_t *dd,
3836 gmx_ddbox_t *ddbox,
3837 rvec cell_ns_x0, rvec cell_ns_x1,
3838 gmx_int64_t step)
3840 gmx_domdec_comm_t *comm;
3841 int dim_ind, dim;
3843 comm = dd->comm;
3845 for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
3847 dim = dd->dim[dim_ind];
3849 /* Without PBC we don't have restrictions on the outer cells */
3850 if (!(dim >= ddbox->npbcdim &&
3851 (dd->ci[dim] == 0 || dd->ci[dim] == dd->nc[dim] - 1)) &&
3852 comm->bDynLoadBal &&
3853 (comm->cell_x1[dim] - comm->cell_x0[dim])*ddbox->skew_fac[dim] <
3854 comm->cellsize_min[dim])
3856 char buf[22];
3857 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",
3858 gmx_step_str(step, buf), dim2char(dim),
3859 comm->cell_x1[dim] - comm->cell_x0[dim],
3860 ddbox->skew_fac[dim],
3861 dd->comm->cellsize_min[dim],
3862 dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
3866 if ((dd->bGridJump && dd->ndim > 1) || ddbox->nboundeddim < DIM)
3868 /* Communicate the boundaries and update cell_ns_x0/1 */
3869 dd_move_cellx(dd, ddbox, cell_ns_x0, cell_ns_x1);
3870 if (dd->bGridJump && dd->ndim > 1)
3872 check_grid_jump(step, dd, dd->comm->cutoff, ddbox, TRUE);
3877 static void make_tric_corr_matrix(int npbcdim, matrix box, matrix tcm)
3879 if (YY < npbcdim)
3881 tcm[YY][XX] = -box[YY][XX]/box[YY][YY];
3883 else
3885 tcm[YY][XX] = 0;
3887 if (ZZ < npbcdim)
3889 tcm[ZZ][XX] = -(box[ZZ][YY]*tcm[YY][XX] + box[ZZ][XX])/box[ZZ][ZZ];
3890 tcm[ZZ][YY] = -box[ZZ][YY]/box[ZZ][ZZ];
3892 else
3894 tcm[ZZ][XX] = 0;
3895 tcm[ZZ][YY] = 0;
3899 static void check_screw_box(matrix box)
3901 /* Mathematical limitation */
3902 if (box[YY][XX] != 0 || box[ZZ][XX] != 0)
3904 gmx_fatal(FARGS, "With screw pbc the unit cell can not have non-zero off-diagonal x-components");
3907 /* Limitation due to the asymmetry of the eighth shell method */
3908 if (box[ZZ][YY] != 0)
3910 gmx_fatal(FARGS, "pbc=screw with non-zero box_zy is not supported");
3914 static void distribute_cg(FILE *fplog, gmx_int64_t step,
3915 matrix box, ivec tric_dir, t_block *cgs, rvec pos[],
3916 gmx_domdec_t *dd)
3918 gmx_domdec_master_t *ma;
3919 int **tmp_ind = NULL, *tmp_nalloc = NULL;
3920 int i, icg, j, k, k0, k1, d;
3921 matrix tcm;
3922 rvec cg_cm;
3923 ivec ind;
3924 real nrcg, inv_ncg, pos_d;
3925 atom_id *cgindex;
3926 gmx_bool bScrew;
3928 ma = dd->ma;
3930 if (tmp_ind == NULL)
3932 snew(tmp_nalloc, dd->nnodes);
3933 snew(tmp_ind, dd->nnodes);
3934 for (i = 0; i < dd->nnodes; i++)
3936 tmp_nalloc[i] = over_alloc_large(cgs->nr/dd->nnodes+1);
3937 snew(tmp_ind[i], tmp_nalloc[i]);
3941 /* Clear the count */
3942 for (i = 0; i < dd->nnodes; i++)
3944 ma->ncg[i] = 0;
3945 ma->nat[i] = 0;
3948 make_tric_corr_matrix(dd->npbcdim, box, tcm);
3950 cgindex = cgs->index;
3952 /* Compute the center of geometry for all charge groups */
3953 for (icg = 0; icg < cgs->nr; icg++)
3955 k0 = cgindex[icg];
3956 k1 = cgindex[icg+1];
3957 nrcg = k1 - k0;
3958 if (nrcg == 1)
3960 copy_rvec(pos[k0], cg_cm);
3962 else
3964 inv_ncg = 1.0/nrcg;
3966 clear_rvec(cg_cm);
3967 for (k = k0; (k < k1); k++)
3969 rvec_inc(cg_cm, pos[k]);
3971 for (d = 0; (d < DIM); d++)
3973 cg_cm[d] *= inv_ncg;
3976 /* Put the charge group in the box and determine the cell index */
3977 for (d = DIM-1; d >= 0; d--)
3979 pos_d = cg_cm[d];
3980 if (d < dd->npbcdim)
3982 bScrew = (dd->bScrewPBC && d == XX);
3983 if (tric_dir[d] && dd->nc[d] > 1)
3985 /* Use triclinic coordintates for this dimension */
3986 for (j = d+1; j < DIM; j++)
3988 pos_d += cg_cm[j]*tcm[j][d];
3991 while (pos_d >= box[d][d])
3993 pos_d -= box[d][d];
3994 rvec_dec(cg_cm, box[d]);
3995 if (bScrew)
3997 cg_cm[YY] = box[YY][YY] - cg_cm[YY];
3998 cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
4000 for (k = k0; (k < k1); k++)
4002 rvec_dec(pos[k], box[d]);
4003 if (bScrew)
4005 pos[k][YY] = box[YY][YY] - pos[k][YY];
4006 pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
4010 while (pos_d < 0)
4012 pos_d += box[d][d];
4013 rvec_inc(cg_cm, box[d]);
4014 if (bScrew)
4016 cg_cm[YY] = box[YY][YY] - cg_cm[YY];
4017 cg_cm[ZZ] = box[ZZ][ZZ] - cg_cm[ZZ];
4019 for (k = k0; (k < k1); k++)
4021 rvec_inc(pos[k], box[d]);
4022 if (bScrew)
4024 pos[k][YY] = box[YY][YY] - pos[k][YY];
4025 pos[k][ZZ] = box[ZZ][ZZ] - pos[k][ZZ];
4030 /* This could be done more efficiently */
4031 ind[d] = 0;
4032 while (ind[d]+1 < dd->nc[d] && pos_d >= ma->cell_x[d][ind[d]+1])
4034 ind[d]++;
4037 i = dd_index(dd->nc, ind);
4038 if (ma->ncg[i] == tmp_nalloc[i])
4040 tmp_nalloc[i] = over_alloc_large(ma->ncg[i]+1);
4041 srenew(tmp_ind[i], tmp_nalloc[i]);
4043 tmp_ind[i][ma->ncg[i]] = icg;
4044 ma->ncg[i]++;
4045 ma->nat[i] += cgindex[icg+1] - cgindex[icg];
4048 k1 = 0;
4049 for (i = 0; i < dd->nnodes; i++)
4051 ma->index[i] = k1;
4052 for (k = 0; k < ma->ncg[i]; k++)
4054 ma->cg[k1++] = tmp_ind[i][k];
4057 ma->index[dd->nnodes] = k1;
4059 for (i = 0; i < dd->nnodes; i++)
4061 sfree(tmp_ind[i]);
4063 sfree(tmp_ind);
4064 sfree(tmp_nalloc);
4066 if (fplog)
4068 char buf[22];
4069 fprintf(fplog, "Charge group distribution at step %s:",
4070 gmx_step_str(step, buf));
4071 for (i = 0; i < dd->nnodes; i++)
4073 fprintf(fplog, " %d", ma->ncg[i]);
4075 fprintf(fplog, "\n");
4079 static void get_cg_distribution(FILE *fplog, gmx_int64_t step, gmx_domdec_t *dd,
4080 t_block *cgs, matrix box, gmx_ddbox_t *ddbox,
4081 rvec pos[])
4083 gmx_domdec_master_t *ma = NULL;
4084 ivec npulse;
4085 int i, cg_gl;
4086 int *ibuf, buf2[2] = { 0, 0 };
4087 gmx_bool bMaster = DDMASTER(dd);
4089 if (bMaster)
4091 ma = dd->ma;
4093 if (dd->bScrewPBC)
4095 check_screw_box(box);
4098 set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbMASTER, npulse);
4100 distribute_cg(fplog, step, box, ddbox->tric_dir, cgs, pos, dd);
4101 for (i = 0; i < dd->nnodes; i++)
4103 ma->ibuf[2*i] = ma->ncg[i];
4104 ma->ibuf[2*i+1] = ma->nat[i];
4106 ibuf = ma->ibuf;
4108 else
4110 ibuf = NULL;
4112 dd_scatter(dd, 2*sizeof(int), ibuf, buf2);
4114 dd->ncg_home = buf2[0];
4115 dd->nat_home = buf2[1];
4116 dd->ncg_tot = dd->ncg_home;
4117 dd->nat_tot = dd->nat_home;
4118 if (dd->ncg_home > dd->cg_nalloc || dd->cg_nalloc == 0)
4120 dd->cg_nalloc = over_alloc_dd(dd->ncg_home);
4121 srenew(dd->index_gl, dd->cg_nalloc);
4122 srenew(dd->cgindex, dd->cg_nalloc+1);
4124 if (bMaster)
4126 for (i = 0; i < dd->nnodes; i++)
4128 ma->ibuf[i] = ma->ncg[i]*sizeof(int);
4129 ma->ibuf[dd->nnodes+i] = ma->index[i]*sizeof(int);
4133 dd_scatterv(dd,
4134 bMaster ? ma->ibuf : NULL,
4135 bMaster ? ma->ibuf+dd->nnodes : NULL,
4136 bMaster ? ma->cg : NULL,
4137 dd->ncg_home*sizeof(int), dd->index_gl);
4139 /* Determine the home charge group sizes */
4140 dd->cgindex[0] = 0;
4141 for (i = 0; i < dd->ncg_home; i++)
4143 cg_gl = dd->index_gl[i];
4144 dd->cgindex[i+1] =
4145 dd->cgindex[i] + cgs->index[cg_gl+1] - cgs->index[cg_gl];
4148 if (debug)
4150 fprintf(debug, "Home charge groups:\n");
4151 for (i = 0; i < dd->ncg_home; i++)
4153 fprintf(debug, " %d", dd->index_gl[i]);
4154 if (i % 10 == 9)
4156 fprintf(debug, "\n");
4159 fprintf(debug, "\n");
4163 static int compact_and_copy_vec_at(int ncg, int *move,
4164 int *cgindex,
4165 int nvec, int vec,
4166 rvec *src, gmx_domdec_comm_t *comm,
4167 gmx_bool bCompact)
4169 int m, icg, i, i0, i1, nrcg;
4170 int home_pos;
4171 int pos_vec[DIM*2];
4173 home_pos = 0;
4175 for (m = 0; m < DIM*2; m++)
4177 pos_vec[m] = 0;
4180 i0 = 0;
4181 for (icg = 0; icg < ncg; icg++)
4183 i1 = cgindex[icg+1];
4184 m = move[icg];
4185 if (m == -1)
4187 if (bCompact)
4189 /* Compact the home array in place */
4190 for (i = i0; i < i1; i++)
4192 copy_rvec(src[i], src[home_pos++]);
4196 else
4198 /* Copy to the communication buffer */
4199 nrcg = i1 - i0;
4200 pos_vec[m] += 1 + vec*nrcg;
4201 for (i = i0; i < i1; i++)
4203 copy_rvec(src[i], comm->cgcm_state[m][pos_vec[m]++]);
4205 pos_vec[m] += (nvec - vec - 1)*nrcg;
4207 if (!bCompact)
4209 home_pos += i1 - i0;
4211 i0 = i1;
4214 return home_pos;
4217 static int compact_and_copy_vec_cg(int ncg, int *move,
4218 int *cgindex,
4219 int nvec, rvec *src, gmx_domdec_comm_t *comm,
4220 gmx_bool bCompact)
4222 int m, icg, i0, i1, nrcg;
4223 int home_pos;
4224 int pos_vec[DIM*2];
4226 home_pos = 0;
4228 for (m = 0; m < DIM*2; m++)
4230 pos_vec[m] = 0;
4233 i0 = 0;
4234 for (icg = 0; icg < ncg; icg++)
4236 i1 = cgindex[icg+1];
4237 m = move[icg];
4238 if (m == -1)
4240 if (bCompact)
4242 /* Compact the home array in place */
4243 copy_rvec(src[icg], src[home_pos++]);
4246 else
4248 nrcg = i1 - i0;
4249 /* Copy to the communication buffer */
4250 copy_rvec(src[icg], comm->cgcm_state[m][pos_vec[m]]);
4251 pos_vec[m] += 1 + nrcg*nvec;
4253 i0 = i1;
4255 if (!bCompact)
4257 home_pos = ncg;
4260 return home_pos;
4263 static int compact_ind(int ncg, int *move,
4264 int *index_gl, int *cgindex,
4265 int *gatindex,
4266 gmx_ga2la_t ga2la, char *bLocalCG,
4267 int *cginfo)
4269 int cg, nat, a0, a1, a, a_gl;
4270 int home_pos;
4272 home_pos = 0;
4273 nat = 0;
4274 for (cg = 0; cg < ncg; cg++)
4276 a0 = cgindex[cg];
4277 a1 = cgindex[cg+1];
4278 if (move[cg] == -1)
4280 /* Compact the home arrays in place.
4281 * Anything that can be done here avoids access to global arrays.
4283 cgindex[home_pos] = nat;
4284 for (a = a0; a < a1; a++)
4286 a_gl = gatindex[a];
4287 gatindex[nat] = a_gl;
4288 /* The cell number stays 0, so we don't need to set it */
4289 ga2la_change_la(ga2la, a_gl, nat);
4290 nat++;
4292 index_gl[home_pos] = index_gl[cg];
4293 cginfo[home_pos] = cginfo[cg];
4294 /* The charge group remains local, so bLocalCG does not change */
4295 home_pos++;
4297 else
4299 /* Clear the global indices */
4300 for (a = a0; a < a1; a++)
4302 ga2la_del(ga2la, gatindex[a]);
4304 if (bLocalCG)
4306 bLocalCG[index_gl[cg]] = FALSE;
4310 cgindex[home_pos] = nat;
4312 return home_pos;
4315 static void clear_and_mark_ind(int ncg, int *move,
4316 int *index_gl, int *cgindex, int *gatindex,
4317 gmx_ga2la_t ga2la, char *bLocalCG,
4318 int *cell_index)
4320 int cg, a0, a1, a;
4322 for (cg = 0; cg < ncg; cg++)
4324 if (move[cg] >= 0)
4326 a0 = cgindex[cg];
4327 a1 = cgindex[cg+1];
4328 /* Clear the global indices */
4329 for (a = a0; a < a1; a++)
4331 ga2la_del(ga2la, gatindex[a]);
4333 if (bLocalCG)
4335 bLocalCG[index_gl[cg]] = FALSE;
4337 /* Signal that this cg has moved using the ns cell index.
4338 * Here we set it to -1. fill_grid will change it
4339 * from -1 to NSGRID_SIGNAL_MOVED_FAC*grid->ncells.
4341 cell_index[cg] = -1;
4346 static void print_cg_move(FILE *fplog,
4347 gmx_domdec_t *dd,
4348 gmx_int64_t step, int cg, int dim, int dir,
4349 gmx_bool bHaveCgcmOld, real limitd,
4350 rvec cm_old, rvec cm_new, real pos_d)
4352 gmx_domdec_comm_t *comm;
4353 char buf[22];
4355 comm = dd->comm;
4357 fprintf(fplog, "\nStep %s:\n", gmx_step_str(step, buf));
4358 if (limitd > 0)
4360 fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition (%f) in direction %c\n",
4361 dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
4362 ddglatnr(dd, dd->cgindex[cg]), limitd, dim2char(dim));
4364 else
4366 /* We don't have a limiting distance available: don't print it */
4367 fprintf(fplog, "%s %d moved more than the distance allowed by the domain decomposition in direction %c\n",
4368 dd->comm->bCGs ? "The charge group starting at atom" : "Atom",
4369 ddglatnr(dd, dd->cgindex[cg]), dim2char(dim));
4371 fprintf(fplog, "distance out of cell %f\n",
4372 dir == 1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
4373 if (bHaveCgcmOld)
4375 fprintf(fplog, "Old coordinates: %8.3f %8.3f %8.3f\n",
4376 cm_old[XX], cm_old[YY], cm_old[ZZ]);
4378 fprintf(fplog, "New coordinates: %8.3f %8.3f %8.3f\n",
4379 cm_new[XX], cm_new[YY], cm_new[ZZ]);
4380 fprintf(fplog, "Old cell boundaries in direction %c: %8.3f %8.3f\n",
4381 dim2char(dim),
4382 comm->old_cell_x0[dim], comm->old_cell_x1[dim]);
4383 fprintf(fplog, "New cell boundaries in direction %c: %8.3f %8.3f\n",
4384 dim2char(dim),
4385 comm->cell_x0[dim], comm->cell_x1[dim]);
4388 static void cg_move_error(FILE *fplog,
4389 gmx_domdec_t *dd,
4390 gmx_int64_t step, int cg, int dim, int dir,
4391 gmx_bool bHaveCgcmOld, real limitd,
4392 rvec cm_old, rvec cm_new, real pos_d)
4394 if (fplog)
4396 print_cg_move(fplog, dd, step, cg, dim, dir,
4397 bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
4399 print_cg_move(stderr, dd, step, cg, dim, dir,
4400 bHaveCgcmOld, limitd, cm_old, cm_new, pos_d);
4401 gmx_fatal(FARGS,
4402 "%s moved too far between two domain decomposition steps\n"
4403 "This usually means that your system is not well equilibrated",
4404 dd->comm->bCGs ? "A charge group" : "An atom");
4407 static void rotate_state_atom(t_state *state, int a)
4409 int est;
4411 for (est = 0; est < estNR; est++)
4413 if (EST_DISTR(est) && (state->flags & (1<<est)))
4415 switch (est)
4417 case estX:
4418 /* Rotate the complete state; for a rectangular box only */
4419 state->x[a][YY] = state->box[YY][YY] - state->x[a][YY];
4420 state->x[a][ZZ] = state->box[ZZ][ZZ] - state->x[a][ZZ];
4421 break;
4422 case estV:
4423 state->v[a][YY] = -state->v[a][YY];
4424 state->v[a][ZZ] = -state->v[a][ZZ];
4425 break;
4426 case estSDX:
4427 state->sd_X[a][YY] = -state->sd_X[a][YY];
4428 state->sd_X[a][ZZ] = -state->sd_X[a][ZZ];
4429 break;
4430 case estCGP:
4431 state->cg_p[a][YY] = -state->cg_p[a][YY];
4432 state->cg_p[a][ZZ] = -state->cg_p[a][ZZ];
4433 break;
4434 case estDISRE_INITF:
4435 case estDISRE_RM3TAV:
4436 case estORIRE_INITF:
4437 case estORIRE_DTAV:
4438 /* These are distances, so not affected by rotation */
4439 break;
4440 default:
4441 gmx_incons("Unknown state entry encountered in rotate_state_atom");
4447 static int *get_moved(gmx_domdec_comm_t *comm, int natoms)
4449 if (natoms > comm->moved_nalloc)
4451 /* Contents should be preserved here */
4452 comm->moved_nalloc = over_alloc_dd(natoms);
4453 srenew(comm->moved, comm->moved_nalloc);
4456 return comm->moved;
4459 static void calc_cg_move(FILE *fplog, gmx_int64_t step,
4460 gmx_domdec_t *dd,
4461 t_state *state,
4462 ivec tric_dir, matrix tcm,
4463 rvec cell_x0, rvec cell_x1,
4464 rvec limitd, rvec limit0, rvec limit1,
4465 const int *cgindex,
4466 int cg_start, int cg_end,
4467 rvec *cg_cm,
4468 int *move)
4470 int npbcdim;
4471 int cg, k, k0, k1, d, dim, d2;
4472 int mc, nrcg;
4473 int flag;
4474 gmx_bool bScrew;
4475 ivec dev;
4476 real inv_ncg, pos_d;
4477 rvec cm_new;
4479 npbcdim = dd->npbcdim;
4481 for (cg = cg_start; cg < cg_end; cg++)
4483 k0 = cgindex[cg];
4484 k1 = cgindex[cg+1];
4485 nrcg = k1 - k0;
4486 if (nrcg == 1)
4488 copy_rvec(state->x[k0], cm_new);
4490 else
4492 inv_ncg = 1.0/nrcg;
4494 clear_rvec(cm_new);
4495 for (k = k0; (k < k1); k++)
4497 rvec_inc(cm_new, state->x[k]);
4499 for (d = 0; (d < DIM); d++)
4501 cm_new[d] = inv_ncg*cm_new[d];
4505 clear_ivec(dev);
4506 /* Do pbc and check DD cell boundary crossings */
4507 for (d = DIM-1; d >= 0; d--)
4509 if (dd->nc[d] > 1)
4511 bScrew = (dd->bScrewPBC && d == XX);
4512 /* Determine the location of this cg in lattice coordinates */
4513 pos_d = cm_new[d];
4514 if (tric_dir[d])
4516 for (d2 = d+1; d2 < DIM; d2++)
4518 pos_d += cm_new[d2]*tcm[d2][d];
4521 /* Put the charge group in the triclinic unit-cell */
4522 if (pos_d >= cell_x1[d])
4524 if (pos_d >= limit1[d])
4526 cg_move_error(fplog, dd, step, cg, d, 1,
4527 cg_cm != state->x, limitd[d],
4528 cg_cm[cg], cm_new, pos_d);
4530 dev[d] = 1;
4531 if (dd->ci[d] == dd->nc[d] - 1)
4533 rvec_dec(cm_new, state->box[d]);
4534 if (bScrew)
4536 cm_new[YY] = state->box[YY][YY] - cm_new[YY];
4537 cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
4539 for (k = k0; (k < k1); k++)
4541 rvec_dec(state->x[k], state->box[d]);
4542 if (bScrew)
4544 rotate_state_atom(state, k);
4549 else if (pos_d < cell_x0[d])
4551 if (pos_d < limit0[d])
4553 cg_move_error(fplog, dd, step, cg, d, -1,
4554 cg_cm != state->x, limitd[d],
4555 cg_cm[cg], cm_new, pos_d);
4557 dev[d] = -1;
4558 if (dd->ci[d] == 0)
4560 rvec_inc(cm_new, state->box[d]);
4561 if (bScrew)
4563 cm_new[YY] = state->box[YY][YY] - cm_new[YY];
4564 cm_new[ZZ] = state->box[ZZ][ZZ] - cm_new[ZZ];
4566 for (k = k0; (k < k1); k++)
4568 rvec_inc(state->x[k], state->box[d]);
4569 if (bScrew)
4571 rotate_state_atom(state, k);
4577 else if (d < npbcdim)
4579 /* Put the charge group in the rectangular unit-cell */
4580 while (cm_new[d] >= state->box[d][d])
4582 rvec_dec(cm_new, state->box[d]);
4583 for (k = k0; (k < k1); k++)
4585 rvec_dec(state->x[k], state->box[d]);
4588 while (cm_new[d] < 0)
4590 rvec_inc(cm_new, state->box[d]);
4591 for (k = k0; (k < k1); k++)
4593 rvec_inc(state->x[k], state->box[d]);
4599 copy_rvec(cm_new, cg_cm[cg]);
4601 /* Determine where this cg should go */
4602 flag = 0;
4603 mc = -1;
4604 for (d = 0; d < dd->ndim; d++)
4606 dim = dd->dim[d];
4607 if (dev[dim] == 1)
4609 flag |= DD_FLAG_FW(d);
4610 if (mc == -1)
4612 mc = d*2;
4615 else if (dev[dim] == -1)
4617 flag |= DD_FLAG_BW(d);
4618 if (mc == -1)
4620 if (dd->nc[dim] > 2)
4622 mc = d*2 + 1;
4624 else
4626 mc = d*2;
4631 /* Temporarily store the flag in move */
4632 move[cg] = mc + flag;
4636 static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
4637 gmx_domdec_t *dd, ivec tric_dir,
4638 t_state *state, rvec **f,
4639 t_forcerec *fr,
4640 gmx_bool bCompact,
4641 t_nrnb *nrnb,
4642 int *ncg_stay_home,
4643 int *ncg_moved)
4645 int *move;
4646 int npbcdim;
4647 int ncg[DIM*2], nat[DIM*2];
4648 int c, i, cg, k, d, dim, dim2, dir, d2, d3;
4649 int mc, cdd, nrcg, ncg_recv, nvs, nvr, nvec, vec;
4650 int sbuf[2], rbuf[2];
4651 int home_pos_cg, home_pos_at, buf_pos;
4652 int flag;
4653 gmx_bool bV = FALSE, bSDX = FALSE, bCGP = FALSE;
4654 real pos_d;
4655 matrix tcm;
4656 rvec *cg_cm = NULL, cell_x0, cell_x1, limitd, limit0, limit1;
4657 atom_id *cgindex;
4658 cginfo_mb_t *cginfo_mb;
4659 gmx_domdec_comm_t *comm;
4660 int *moved;
4661 int nthread, thread;
4663 if (dd->bScrewPBC)
4665 check_screw_box(state->box);
4668 comm = dd->comm;
4669 if (fr->cutoff_scheme == ecutsGROUP)
4671 cg_cm = fr->cg_cm;
4674 for (i = 0; i < estNR; i++)
4676 if (EST_DISTR(i))
4678 switch (i)
4680 case estX: /* Always present */ break;
4681 case estV: bV = (state->flags & (1<<i)); break;
4682 case estSDX: bSDX = (state->flags & (1<<i)); break;
4683 case estCGP: bCGP = (state->flags & (1<<i)); break;
4684 case estLD_RNG:
4685 case estLD_RNGI:
4686 case estDISRE_INITF:
4687 case estDISRE_RM3TAV:
4688 case estORIRE_INITF:
4689 case estORIRE_DTAV:
4690 /* No processing required */
4691 break;
4692 default:
4693 gmx_incons("Unknown state entry encountered in dd_redistribute_cg");
4698 if (dd->ncg_tot > comm->nalloc_int)
4700 comm->nalloc_int = over_alloc_dd(dd->ncg_tot);
4701 srenew(comm->buf_int, comm->nalloc_int);
4703 move = comm->buf_int;
4705 /* Clear the count */
4706 for (c = 0; c < dd->ndim*2; c++)
4708 ncg[c] = 0;
4709 nat[c] = 0;
4712 npbcdim = dd->npbcdim;
4714 for (d = 0; (d < DIM); d++)
4716 limitd[d] = dd->comm->cellsize_min[d];
4717 if (d >= npbcdim && dd->ci[d] == 0)
4719 cell_x0[d] = -GMX_FLOAT_MAX;
4721 else
4723 cell_x0[d] = comm->cell_x0[d];
4725 if (d >= npbcdim && dd->ci[d] == dd->nc[d] - 1)
4727 cell_x1[d] = GMX_FLOAT_MAX;
4729 else
4731 cell_x1[d] = comm->cell_x1[d];
4733 if (d < npbcdim)
4735 limit0[d] = comm->old_cell_x0[d] - limitd[d];
4736 limit1[d] = comm->old_cell_x1[d] + limitd[d];
4738 else
4740 /* We check after communication if a charge group moved
4741 * more than one cell. Set the pre-comm check limit to float_max.
4743 limit0[d] = -GMX_FLOAT_MAX;
4744 limit1[d] = GMX_FLOAT_MAX;
4748 make_tric_corr_matrix(npbcdim, state->box, tcm);
4750 cgindex = dd->cgindex;
4752 nthread = gmx_omp_nthreads_get(emntDomdec);
4754 /* Compute the center of geometry for all home charge groups
4755 * and put them in the box and determine where they should go.
4757 #pragma omp parallel for num_threads(nthread) schedule(static)
4758 for (thread = 0; thread < nthread; thread++)
4760 calc_cg_move(fplog, step, dd, state, tric_dir, tcm,
4761 cell_x0, cell_x1, limitd, limit0, limit1,
4762 cgindex,
4763 ( thread *dd->ncg_home)/nthread,
4764 ((thread+1)*dd->ncg_home)/nthread,
4765 fr->cutoff_scheme == ecutsGROUP ? cg_cm : state->x,
4766 move);
4769 for (cg = 0; cg < dd->ncg_home; cg++)
4771 if (move[cg] >= 0)
4773 mc = move[cg];
4774 flag = mc & ~DD_FLAG_NRCG;
4775 mc = mc & DD_FLAG_NRCG;
4776 move[cg] = mc;
4778 if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
4780 comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
4781 srenew(comm->cggl_flag[mc], comm->cggl_flag_nalloc[mc]*DD_CGIBS);
4783 comm->cggl_flag[mc][ncg[mc]*DD_CGIBS ] = dd->index_gl[cg];
4784 /* We store the cg size in the lower 16 bits
4785 * and the place where the charge group should go
4786 * in the next 6 bits. This saves some communication volume.
4788 nrcg = cgindex[cg+1] - cgindex[cg];
4789 comm->cggl_flag[mc][ncg[mc]*DD_CGIBS+1] = nrcg | flag;
4790 ncg[mc] += 1;
4791 nat[mc] += nrcg;
4795 inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
4796 inc_nrnb(nrnb, eNR_RESETX, dd->ncg_home);
4798 *ncg_moved = 0;
4799 for (i = 0; i < dd->ndim*2; i++)
4801 *ncg_moved += ncg[i];
4804 nvec = 1;
4805 if (bV)
4807 nvec++;
4809 if (bSDX)
4811 nvec++;
4813 if (bCGP)
4815 nvec++;
4818 /* Make sure the communication buffers are large enough */
4819 for (mc = 0; mc < dd->ndim*2; mc++)
4821 nvr = ncg[mc] + nat[mc]*nvec;
4822 if (nvr > comm->cgcm_state_nalloc[mc])
4824 comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr);
4825 srenew(comm->cgcm_state[mc], comm->cgcm_state_nalloc[mc]);
4829 switch (fr->cutoff_scheme)
4831 case ecutsGROUP:
4832 /* Recalculating cg_cm might be cheaper than communicating,
4833 * but that could give rise to rounding issues.
4835 home_pos_cg =
4836 compact_and_copy_vec_cg(dd->ncg_home, move, cgindex,
4837 nvec, cg_cm, comm, bCompact);
4838 break;
4839 case ecutsVERLET:
4840 /* Without charge groups we send the moved atom coordinates
4841 * over twice. This is so the code below can be used without
4842 * many conditionals for both for with and without charge groups.
4844 home_pos_cg =
4845 compact_and_copy_vec_cg(dd->ncg_home, move, cgindex,
4846 nvec, state->x, comm, FALSE);
4847 if (bCompact)
4849 home_pos_cg -= *ncg_moved;
4851 break;
4852 default:
4853 gmx_incons("unimplemented");
4854 home_pos_cg = 0;
4857 vec = 0;
4858 home_pos_at =
4859 compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4860 nvec, vec++, state->x, comm, bCompact);
4861 if (bV)
4863 compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4864 nvec, vec++, state->v, comm, bCompact);
4866 if (bSDX)
4868 compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4869 nvec, vec++, state->sd_X, comm, bCompact);
4871 if (bCGP)
4873 compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
4874 nvec, vec++, state->cg_p, comm, bCompact);
4877 if (bCompact)
4879 compact_ind(dd->ncg_home, move,
4880 dd->index_gl, dd->cgindex, dd->gatindex,
4881 dd->ga2la, comm->bLocalCG,
4882 fr->cginfo);
4884 else
4886 if (fr->cutoff_scheme == ecutsVERLET)
4888 moved = get_moved(comm, dd->ncg_home);
4890 for (k = 0; k < dd->ncg_home; k++)
4892 moved[k] = 0;
4895 else
4897 moved = fr->ns.grid->cell_index;
4900 clear_and_mark_ind(dd->ncg_home, move,
4901 dd->index_gl, dd->cgindex, dd->gatindex,
4902 dd->ga2la, comm->bLocalCG,
4903 moved);
4906 cginfo_mb = fr->cginfo_mb;
4908 *ncg_stay_home = home_pos_cg;
4909 for (d = 0; d < dd->ndim; d++)
4911 dim = dd->dim[d];
4912 ncg_recv = 0;
4913 nvr = 0;
4914 for (dir = 0; dir < (dd->nc[dim] == 2 ? 1 : 2); dir++)
4916 cdd = d*2 + dir;
4917 /* Communicate the cg and atom counts */
4918 sbuf[0] = ncg[cdd];
4919 sbuf[1] = nat[cdd];
4920 if (debug)
4922 fprintf(debug, "Sending ddim %d dir %d: ncg %d nat %d\n",
4923 d, dir, sbuf[0], sbuf[1]);
4925 dd_sendrecv_int(dd, d, dir, sbuf, 2, rbuf, 2);
4927 if ((ncg_recv+rbuf[0])*DD_CGIBS > comm->nalloc_int)
4929 comm->nalloc_int = over_alloc_dd((ncg_recv+rbuf[0])*DD_CGIBS);
4930 srenew(comm->buf_int, comm->nalloc_int);
4933 /* Communicate the charge group indices, sizes and flags */
4934 dd_sendrecv_int(dd, d, dir,
4935 comm->cggl_flag[cdd], sbuf[0]*DD_CGIBS,
4936 comm->buf_int+ncg_recv*DD_CGIBS, rbuf[0]*DD_CGIBS);
4938 nvs = ncg[cdd] + nat[cdd]*nvec;
4939 i = rbuf[0] + rbuf[1] *nvec;
4940 vec_rvec_check_alloc(&comm->vbuf, nvr+i);
4942 /* Communicate cgcm and state */
4943 dd_sendrecv_rvec(dd, d, dir,
4944 comm->cgcm_state[cdd], nvs,
4945 comm->vbuf.v+nvr, i);
4946 ncg_recv += rbuf[0];
4947 nvr += i;
4950 /* Process the received charge groups */
4951 buf_pos = 0;
4952 for (cg = 0; cg < ncg_recv; cg++)
4954 flag = comm->buf_int[cg*DD_CGIBS+1];
4956 if (dim >= npbcdim && dd->nc[dim] > 2)
4958 /* No pbc in this dim and more than one domain boundary.
4959 * We do a separate check if a charge group didn't move too far.
4961 if (((flag & DD_FLAG_FW(d)) &&
4962 comm->vbuf.v[buf_pos][dim] > cell_x1[dim]) ||
4963 ((flag & DD_FLAG_BW(d)) &&
4964 comm->vbuf.v[buf_pos][dim] < cell_x0[dim]))
4966 cg_move_error(fplog, dd, step, cg, dim,
4967 (flag & DD_FLAG_FW(d)) ? 1 : 0,
4968 fr->cutoff_scheme == ecutsGROUP, 0,
4969 comm->vbuf.v[buf_pos],
4970 comm->vbuf.v[buf_pos],
4971 comm->vbuf.v[buf_pos][dim]);
4975 mc = -1;
4976 if (d < dd->ndim-1)
4978 /* Check which direction this cg should go */
4979 for (d2 = d+1; (d2 < dd->ndim && mc == -1); d2++)
4981 if (dd->bGridJump)
4983 /* The cell boundaries for dimension d2 are not equal
4984 * for each cell row of the lower dimension(s),
4985 * therefore we might need to redetermine where
4986 * this cg should go.
4988 dim2 = dd->dim[d2];
4989 /* If this cg crosses the box boundary in dimension d2
4990 * we can use the communicated flag, so we do not
4991 * have to worry about pbc.
4993 if (!((dd->ci[dim2] == dd->nc[dim2]-1 &&
4994 (flag & DD_FLAG_FW(d2))) ||
4995 (dd->ci[dim2] == 0 &&
4996 (flag & DD_FLAG_BW(d2)))))
4998 /* Clear the two flags for this dimension */
4999 flag &= ~(DD_FLAG_FW(d2) | DD_FLAG_BW(d2));
5000 /* Determine the location of this cg
5001 * in lattice coordinates
5003 pos_d = comm->vbuf.v[buf_pos][dim2];
5004 if (tric_dir[dim2])
5006 for (d3 = dim2+1; d3 < DIM; d3++)
5008 pos_d +=
5009 comm->vbuf.v[buf_pos][d3]*tcm[d3][dim2];
5012 /* Check of we are not at the box edge.
5013 * pbc is only handled in the first step above,
5014 * but this check could move over pbc while
5015 * the first step did not due to different rounding.
5017 if (pos_d >= cell_x1[dim2] &&
5018 dd->ci[dim2] != dd->nc[dim2]-1)
5020 flag |= DD_FLAG_FW(d2);
5022 else if (pos_d < cell_x0[dim2] &&
5023 dd->ci[dim2] != 0)
5025 flag |= DD_FLAG_BW(d2);
5027 comm->buf_int[cg*DD_CGIBS+1] = flag;
5030 /* Set to which neighboring cell this cg should go */
5031 if (flag & DD_FLAG_FW(d2))
5033 mc = d2*2;
5035 else if (flag & DD_FLAG_BW(d2))
5037 if (dd->nc[dd->dim[d2]] > 2)
5039 mc = d2*2+1;
5041 else
5043 mc = d2*2;
5049 nrcg = flag & DD_FLAG_NRCG;
5050 if (mc == -1)
5052 if (home_pos_cg+1 > dd->cg_nalloc)
5054 dd->cg_nalloc = over_alloc_dd(home_pos_cg+1);
5055 srenew(dd->index_gl, dd->cg_nalloc);
5056 srenew(dd->cgindex, dd->cg_nalloc+1);
5058 /* Set the global charge group index and size */
5059 dd->index_gl[home_pos_cg] = comm->buf_int[cg*DD_CGIBS];
5060 dd->cgindex[home_pos_cg+1] = dd->cgindex[home_pos_cg] + nrcg;
5061 /* Copy the state from the buffer */
5062 dd_check_alloc_ncg(fr, state, f, home_pos_cg+1);
5063 if (fr->cutoff_scheme == ecutsGROUP)
5065 cg_cm = fr->cg_cm;
5066 copy_rvec(comm->vbuf.v[buf_pos], cg_cm[home_pos_cg]);
5068 buf_pos++;
5070 /* Set the cginfo */
5071 fr->cginfo[home_pos_cg] = ddcginfo(cginfo_mb,
5072 dd->index_gl[home_pos_cg]);
5073 if (comm->bLocalCG)
5075 comm->bLocalCG[dd->index_gl[home_pos_cg]] = TRUE;
5078 if (home_pos_at+nrcg > state->nalloc)
5080 dd_realloc_state(state, f, home_pos_at+nrcg);
5082 for (i = 0; i < nrcg; i++)
5084 copy_rvec(comm->vbuf.v[buf_pos++],
5085 state->x[home_pos_at+i]);
5087 if (bV)
5089 for (i = 0; i < nrcg; i++)
5091 copy_rvec(comm->vbuf.v[buf_pos++],
5092 state->v[home_pos_at+i]);
5095 if (bSDX)
5097 for (i = 0; i < nrcg; i++)
5099 copy_rvec(comm->vbuf.v[buf_pos++],
5100 state->sd_X[home_pos_at+i]);
5103 if (bCGP)
5105 for (i = 0; i < nrcg; i++)
5107 copy_rvec(comm->vbuf.v[buf_pos++],
5108 state->cg_p[home_pos_at+i]);
5111 home_pos_cg += 1;
5112 home_pos_at += nrcg;
5114 else
5116 /* Reallocate the buffers if necessary */
5117 if (ncg[mc]+1 > comm->cggl_flag_nalloc[mc])
5119 comm->cggl_flag_nalloc[mc] = over_alloc_dd(ncg[mc]+1);
5120 srenew(comm->cggl_flag[mc], comm->cggl_flag_nalloc[mc]*DD_CGIBS);
5122 nvr = ncg[mc] + nat[mc]*nvec;
5123 if (nvr + 1 + nrcg*nvec > comm->cgcm_state_nalloc[mc])
5125 comm->cgcm_state_nalloc[mc] = over_alloc_dd(nvr + 1 + nrcg*nvec);
5126 srenew(comm->cgcm_state[mc], comm->cgcm_state_nalloc[mc]);
5128 /* Copy from the receive to the send buffers */
5129 memcpy(comm->cggl_flag[mc] + ncg[mc]*DD_CGIBS,
5130 comm->buf_int + cg*DD_CGIBS,
5131 DD_CGIBS*sizeof(int));
5132 memcpy(comm->cgcm_state[mc][nvr],
5133 comm->vbuf.v[buf_pos],
5134 (1+nrcg*nvec)*sizeof(rvec));
5135 buf_pos += 1 + nrcg*nvec;
5136 ncg[mc] += 1;
5137 nat[mc] += nrcg;
5142 /* With sorting (!bCompact) the indices are now only partially up to date
5143 * and ncg_home and nat_home are not the real count, since there are
5144 * "holes" in the arrays for the charge groups that moved to neighbors.
5146 if (fr->cutoff_scheme == ecutsVERLET)
5148 moved = get_moved(comm, home_pos_cg);
5150 for (i = dd->ncg_home; i < home_pos_cg; i++)
5152 moved[i] = 0;
5155 dd->ncg_home = home_pos_cg;
5156 dd->nat_home = home_pos_at;
5158 if (debug)
5160 fprintf(debug,
5161 "Finished repartitioning: cgs moved out %d, new home %d\n",
5162 *ncg_moved, dd->ncg_home-*ncg_moved);
5167 void dd_cycles_add(gmx_domdec_t *dd, float cycles, int ddCycl)
5169 dd->comm->cycl[ddCycl] += cycles;
5170 dd->comm->cycl_n[ddCycl]++;
5171 if (cycles > dd->comm->cycl_max[ddCycl])
5173 dd->comm->cycl_max[ddCycl] = cycles;
5177 static double force_flop_count(t_nrnb *nrnb)
5179 int i;
5180 double sum;
5181 const char *name;
5183 sum = 0;
5184 for (i = 0; i < eNR_NBKERNEL_FREE_ENERGY; i++)
5186 /* To get closer to the real timings, we half the count
5187 * for the normal loops and again half it for water loops.
5189 name = nrnb_str(i);
5190 if (strstr(name, "W3") != NULL || strstr(name, "W4") != NULL)
5192 sum += nrnb->n[i]*0.25*cost_nrnb(i);
5194 else
5196 sum += nrnb->n[i]*0.50*cost_nrnb(i);
5199 for (i = eNR_NBKERNEL_FREE_ENERGY; i <= eNR_NB14; i++)
5201 name = nrnb_str(i);
5202 if (strstr(name, "W3") != NULL || strstr(name, "W4") != NULL)
5204 sum += nrnb->n[i]*cost_nrnb(i);
5207 for (i = eNR_BONDS; i <= eNR_WALLS; i++)
5209 sum += nrnb->n[i]*cost_nrnb(i);
5212 return sum;
5215 void dd_force_flop_start(gmx_domdec_t *dd, t_nrnb *nrnb)
5217 if (dd->comm->eFlop)
5219 dd->comm->flop -= force_flop_count(nrnb);
5222 void dd_force_flop_stop(gmx_domdec_t *dd, t_nrnb *nrnb)
5224 if (dd->comm->eFlop)
5226 dd->comm->flop += force_flop_count(nrnb);
5227 dd->comm->flop_n++;
5231 static void clear_dd_cycle_counts(gmx_domdec_t *dd)
5233 int i;
5235 for (i = 0; i < ddCyclNr; i++)
5237 dd->comm->cycl[i] = 0;
5238 dd->comm->cycl_n[i] = 0;
5239 dd->comm->cycl_max[i] = 0;
5241 dd->comm->flop = 0;
5242 dd->comm->flop_n = 0;
5245 static void get_load_distribution(gmx_domdec_t *dd, gmx_wallcycle_t wcycle)
5247 gmx_domdec_comm_t *comm;
5248 gmx_domdec_load_t *load;
5249 gmx_domdec_root_t *root = NULL;
5250 int d, dim, i, pos;
5251 float cell_frac = 0, sbuf[DD_NLOAD_MAX];
5252 gmx_bool bSepPME;
5254 if (debug)
5256 fprintf(debug, "get_load_distribution start\n");
5259 wallcycle_start(wcycle, ewcDDCOMMLOAD);
5261 comm = dd->comm;
5263 bSepPME = (dd->pme_nodeid >= 0);
5265 for (d = dd->ndim-1; d >= 0; d--)
5267 dim = dd->dim[d];
5268 /* Check if we participate in the communication in this dimension */
5269 if (d == dd->ndim-1 ||
5270 (dd->ci[dd->dim[d+1]] == 0 && dd->ci[dd->dim[dd->ndim-1]] == 0))
5272 load = &comm->load[d];
5273 if (dd->bGridJump)
5275 cell_frac = comm->cell_f1[d] - comm->cell_f0[d];
5277 pos = 0;
5278 if (d == dd->ndim-1)
5280 sbuf[pos++] = dd_force_load(comm);
5281 sbuf[pos++] = sbuf[0];
5282 if (dd->bGridJump)
5284 sbuf[pos++] = sbuf[0];
5285 sbuf[pos++] = cell_frac;
5286 if (d > 0)
5288 sbuf[pos++] = comm->cell_f_max0[d];
5289 sbuf[pos++] = comm->cell_f_min1[d];
5292 if (bSepPME)
5294 sbuf[pos++] = comm->cycl[ddCyclPPduringPME];
5295 sbuf[pos++] = comm->cycl[ddCyclPME];
5298 else
5300 sbuf[pos++] = comm->load[d+1].sum;
5301 sbuf[pos++] = comm->load[d+1].max;
5302 if (dd->bGridJump)
5304 sbuf[pos++] = comm->load[d+1].sum_m;
5305 sbuf[pos++] = comm->load[d+1].cvol_min*cell_frac;
5306 sbuf[pos++] = comm->load[d+1].flags;
5307 if (d > 0)
5309 sbuf[pos++] = comm->cell_f_max0[d];
5310 sbuf[pos++] = comm->cell_f_min1[d];
5313 if (bSepPME)
5315 sbuf[pos++] = comm->load[d+1].mdf;
5316 sbuf[pos++] = comm->load[d+1].pme;
5319 load->nload = pos;
5320 /* Communicate a row in DD direction d.
5321 * The communicators are setup such that the root always has rank 0.
5323 #ifdef GMX_MPI
5324 MPI_Gather(sbuf, load->nload*sizeof(float), MPI_BYTE,
5325 load->load, load->nload*sizeof(float), MPI_BYTE,
5326 0, comm->mpi_comm_load[d]);
5327 #endif
5328 if (dd->ci[dim] == dd->master_ci[dim])
5330 /* We are the root, process this row */
5331 if (comm->bDynLoadBal)
5333 root = comm->root[d];
5335 load->sum = 0;
5336 load->max = 0;
5337 load->sum_m = 0;
5338 load->cvol_min = 1;
5339 load->flags = 0;
5340 load->mdf = 0;
5341 load->pme = 0;
5342 pos = 0;
5343 for (i = 0; i < dd->nc[dim]; i++)
5345 load->sum += load->load[pos++];
5346 load->max = std::max(load->max, load->load[pos]);
5347 pos++;
5348 if (dd->bGridJump)
5350 if (root->bLimited)
5352 /* This direction could not be load balanced properly,
5353 * therefore we need to use the maximum iso the average load.
5355 load->sum_m = std::max(load->sum_m, load->load[pos]);
5357 else
5359 load->sum_m += load->load[pos];
5361 pos++;
5362 load->cvol_min = std::min(load->cvol_min, load->load[pos]);
5363 pos++;
5364 if (d < dd->ndim-1)
5366 load->flags = (int)(load->load[pos++] + 0.5);
5368 if (d > 0)
5370 root->cell_f_max0[i] = load->load[pos++];
5371 root->cell_f_min1[i] = load->load[pos++];
5374 if (bSepPME)
5376 load->mdf = std::max(load->mdf, load->load[pos]);
5377 pos++;
5378 load->pme = std::max(load->pme, load->load[pos]);
5379 pos++;
5382 if (comm->bDynLoadBal && root->bLimited)
5384 load->sum_m *= dd->nc[dim];
5385 load->flags |= (1<<d);
5391 if (DDMASTER(dd))
5393 comm->nload += dd_load_count(comm);
5394 comm->load_step += comm->cycl[ddCyclStep];
5395 comm->load_sum += comm->load[0].sum;
5396 comm->load_max += comm->load[0].max;
5397 if (comm->bDynLoadBal)
5399 for (d = 0; d < dd->ndim; d++)
5401 if (comm->load[0].flags & (1<<d))
5403 comm->load_lim[d]++;
5407 if (bSepPME)
5409 comm->load_mdf += comm->load[0].mdf;
5410 comm->load_pme += comm->load[0].pme;
5414 wallcycle_stop(wcycle, ewcDDCOMMLOAD);
5416 if (debug)
5418 fprintf(debug, "get_load_distribution finished\n");
5422 static float dd_force_imb_perf_loss(gmx_domdec_t *dd)
5424 /* Return the relative performance loss on the total run time
5425 * due to the force calculation load imbalance.
5427 if (dd->comm->nload > 0)
5429 return
5430 (dd->comm->load_max*dd->nnodes - dd->comm->load_sum)/
5431 (dd->comm->load_step*dd->nnodes);
5433 else
5435 return 0;
5439 static void print_dd_load_av(FILE *fplog, gmx_domdec_t *dd)
5441 char buf[STRLEN];
5442 int npp, npme, nnodes, d, limp;
5443 float imbal, pme_f_ratio, lossf, lossp = 0;
5444 gmx_bool bLim;
5445 gmx_domdec_comm_t *comm;
5447 comm = dd->comm;
5448 if (DDMASTER(dd) && comm->nload > 0)
5450 npp = dd->nnodes;
5451 npme = (dd->pme_nodeid >= 0) ? comm->npmenodes : 0;
5452 nnodes = npp + npme;
5453 imbal = comm->load_max*npp/comm->load_sum - 1;
5454 lossf = dd_force_imb_perf_loss(dd);
5455 sprintf(buf, " Average load imbalance: %.1f %%\n", imbal*100);
5456 fprintf(fplog, "%s", buf);
5457 fprintf(stderr, "\n");
5458 fprintf(stderr, "%s", buf);
5459 sprintf(buf, " Part of the total run time spent waiting due to load imbalance: %.1f %%\n", lossf*100);
5460 fprintf(fplog, "%s", buf);
5461 fprintf(stderr, "%s", buf);
5462 bLim = FALSE;
5463 if (comm->bDynLoadBal)
5465 sprintf(buf, " Steps where the load balancing was limited by -rdd, -rcon and/or -dds:");
5466 for (d = 0; d < dd->ndim; d++)
5468 limp = (200*comm->load_lim[d]+1)/(2*comm->nload);
5469 sprintf(buf+strlen(buf), " %c %d %%", dim2char(dd->dim[d]), limp);
5470 if (limp >= 50)
5472 bLim = TRUE;
5475 sprintf(buf+strlen(buf), "\n");
5476 fprintf(fplog, "%s", buf);
5477 fprintf(stderr, "%s", buf);
5479 if (npme > 0)
5481 pme_f_ratio = comm->load_pme/comm->load_mdf;
5482 lossp = (comm->load_pme -comm->load_mdf)/comm->load_step;
5483 if (lossp <= 0)
5485 lossp *= (float)npme/(float)nnodes;
5487 else
5489 lossp *= (float)npp/(float)nnodes;
5491 sprintf(buf, " Average PME mesh/force load: %5.3f\n", pme_f_ratio);
5492 fprintf(fplog, "%s", buf);
5493 fprintf(stderr, "%s", buf);
5494 sprintf(buf, " Part of the total run time spent waiting due to PP/PME imbalance: %.1f %%\n", fabs(lossp)*100);
5495 fprintf(fplog, "%s", buf);
5496 fprintf(stderr, "%s", buf);
5498 fprintf(fplog, "\n");
5499 fprintf(stderr, "\n");
5501 if (lossf >= DD_PERF_LOSS_WARN)
5503 sprintf(buf,
5504 "NOTE: %.1f %% of the available CPU time was lost due to load imbalance\n"
5505 " in the domain decomposition.\n", lossf*100);
5506 if (!comm->bDynLoadBal)
5508 sprintf(buf+strlen(buf), " You might want to use dynamic load balancing (option -dlb.)\n");
5510 else if (bLim)
5512 sprintf(buf+strlen(buf), " You might want to decrease the cell size limit (options -rdd, -rcon and/or -dds).\n");
5514 fprintf(fplog, "%s\n", buf);
5515 fprintf(stderr, "%s\n", buf);
5517 if (npme > 0 && fabs(lossp) >= DD_PERF_LOSS_WARN)
5519 sprintf(buf,
5520 "NOTE: %.1f %% performance was lost because the PME ranks\n"
5521 " had %s work to do than the PP ranks.\n"
5522 " You might want to %s the number of PME ranks\n"
5523 " or %s the cut-off and the grid spacing.\n",
5524 fabs(lossp*100),
5525 (lossp < 0) ? "less" : "more",
5526 (lossp < 0) ? "decrease" : "increase",
5527 (lossp < 0) ? "decrease" : "increase");
5528 fprintf(fplog, "%s\n", buf);
5529 fprintf(stderr, "%s\n", buf);
5534 static float dd_vol_min(gmx_domdec_t *dd)
5536 return dd->comm->load[0].cvol_min*dd->nnodes;
5539 static gmx_bool dd_load_flags(gmx_domdec_t *dd)
5541 return dd->comm->load[0].flags;
5544 static float dd_f_imbal(gmx_domdec_t *dd)
5546 return dd->comm->load[0].max*dd->nnodes/dd->comm->load[0].sum - 1;
5549 float dd_pme_f_ratio(gmx_domdec_t *dd)
5551 if (dd->comm->cycl_n[ddCyclPME] > 0)
5553 return dd->comm->load[0].pme/dd->comm->load[0].mdf;
5555 else
5557 return -1.0;
5561 static void dd_print_load(FILE *fplog, gmx_domdec_t *dd, gmx_int64_t step)
5563 int flags, d;
5564 char buf[22];
5566 flags = dd_load_flags(dd);
5567 if (flags)
5569 fprintf(fplog,
5570 "DD load balancing is limited by minimum cell size in dimension");
5571 for (d = 0; d < dd->ndim; d++)
5573 if (flags & (1<<d))
5575 fprintf(fplog, " %c", dim2char(dd->dim[d]));
5578 fprintf(fplog, "\n");
5580 fprintf(fplog, "DD step %s", gmx_step_str(step, buf));
5581 if (dd->comm->bDynLoadBal)
5583 fprintf(fplog, " vol min/aver %5.3f%c",
5584 dd_vol_min(dd), flags ? '!' : ' ');
5586 fprintf(fplog, " load imb.: force %4.1f%%", dd_f_imbal(dd)*100);
5587 if (dd->comm->cycl_n[ddCyclPME])
5589 fprintf(fplog, " pme mesh/force %5.3f", dd_pme_f_ratio(dd));
5591 fprintf(fplog, "\n\n");
5594 static void dd_print_load_verbose(gmx_domdec_t *dd)
5596 if (dd->comm->bDynLoadBal)
5598 fprintf(stderr, "vol %4.2f%c ",
5599 dd_vol_min(dd), dd_load_flags(dd) ? '!' : ' ');
5601 fprintf(stderr, "imb F %2d%% ", (int)(dd_f_imbal(dd)*100+0.5));
5602 if (dd->comm->cycl_n[ddCyclPME])
5604 fprintf(stderr, "pme/F %4.2f ", dd_pme_f_ratio(dd));
5608 #ifdef GMX_MPI
5609 static void make_load_communicator(gmx_domdec_t *dd, int dim_ind, ivec loc)
5611 MPI_Comm c_row;
5612 int dim, i, rank;
5613 ivec loc_c;
5614 gmx_domdec_root_t *root;
5615 gmx_bool bPartOfGroup = FALSE;
5617 dim = dd->dim[dim_ind];
5618 copy_ivec(loc, loc_c);
5619 for (i = 0; i < dd->nc[dim]; i++)
5621 loc_c[dim] = i;
5622 rank = dd_index(dd->nc, loc_c);
5623 if (rank == dd->rank)
5625 /* This process is part of the group */
5626 bPartOfGroup = TRUE;
5629 MPI_Comm_split(dd->mpi_comm_all, bPartOfGroup ? 0 : MPI_UNDEFINED, dd->rank,
5630 &c_row);
5631 if (bPartOfGroup)
5633 dd->comm->mpi_comm_load[dim_ind] = c_row;
5634 if (dd->comm->eDLB != edlbNO)
5636 if (dd->ci[dim] == dd->master_ci[dim])
5638 /* This is the root process of this row */
5639 snew(dd->comm->root[dim_ind], 1);
5640 root = dd->comm->root[dim_ind];
5641 snew(root->cell_f, DD_CELL_F_SIZE(dd, dim_ind));
5642 snew(root->old_cell_f, dd->nc[dim]+1);
5643 snew(root->bCellMin, dd->nc[dim]);
5644 if (dim_ind > 0)
5646 snew(root->cell_f_max0, dd->nc[dim]);
5647 snew(root->cell_f_min1, dd->nc[dim]);
5648 snew(root->bound_min, dd->nc[dim]);
5649 snew(root->bound_max, dd->nc[dim]);
5651 snew(root->buf_ncd, dd->nc[dim]);
5653 else
5655 /* This is not a root process, we only need to receive cell_f */
5656 snew(dd->comm->cell_f_row, DD_CELL_F_SIZE(dd, dim_ind));
5659 if (dd->ci[dim] == dd->master_ci[dim])
5661 snew(dd->comm->load[dim_ind].load, dd->nc[dim]*DD_NLOAD_MAX);
5665 #endif
5667 void dd_setup_dlb_resource_sharing(t_commrec gmx_unused *cr,
5668 const gmx_hw_info_t gmx_unused *hwinfo,
5669 const gmx_hw_opt_t gmx_unused *hw_opt)
5671 #ifdef GMX_MPI
5672 int physicalnode_id_hash;
5673 int gpu_id;
5674 gmx_domdec_t *dd;
5675 MPI_Comm mpi_comm_pp_physicalnode;
5677 if (!(cr->duty & DUTY_PP) ||
5678 hw_opt->gpu_opt.ncuda_dev_use == 0)
5680 /* Only PP nodes (currently) use GPUs.
5681 * If we don't have GPUs, there are no resources to share.
5683 return;
5686 physicalnode_id_hash = gmx_physicalnode_id_hash();
5688 gpu_id = get_gpu_device_id(&hwinfo->gpu_info, &hw_opt->gpu_opt, cr->rank_pp_intranode);
5690 dd = cr->dd;
5692 if (debug)
5694 fprintf(debug, "dd_setup_dd_dlb_gpu_sharing:\n");
5695 fprintf(debug, "DD PP rank %d physical node hash %d gpu_id %d\n",
5696 dd->rank, physicalnode_id_hash, gpu_id);
5698 /* Split the PP communicator over the physical nodes */
5699 /* TODO: See if we should store this (before), as it's also used for
5700 * for the nodecomm summution.
5702 MPI_Comm_split(dd->mpi_comm_all, physicalnode_id_hash, dd->rank,
5703 &mpi_comm_pp_physicalnode);
5704 MPI_Comm_split(mpi_comm_pp_physicalnode, gpu_id, dd->rank,
5705 &dd->comm->mpi_comm_gpu_shared);
5706 MPI_Comm_free(&mpi_comm_pp_physicalnode);
5707 MPI_Comm_size(dd->comm->mpi_comm_gpu_shared, &dd->comm->nrank_gpu_shared);
5709 if (debug)
5711 fprintf(debug, "nrank_gpu_shared %d\n", dd->comm->nrank_gpu_shared);
5714 /* Note that some ranks could share a GPU, while others don't */
5716 if (dd->comm->nrank_gpu_shared == 1)
5718 MPI_Comm_free(&dd->comm->mpi_comm_gpu_shared);
5720 #endif
5723 static void make_load_communicators(gmx_domdec_t gmx_unused *dd)
5725 #ifdef GMX_MPI
5726 int dim0, dim1, i, j;
5727 ivec loc;
5729 if (debug)
5731 fprintf(debug, "Making load communicators\n");
5734 snew(dd->comm->load, dd->ndim);
5735 snew(dd->comm->mpi_comm_load, dd->ndim);
5737 clear_ivec(loc);
5738 make_load_communicator(dd, 0, loc);
5739 if (dd->ndim > 1)
5741 dim0 = dd->dim[0];
5742 for (i = 0; i < dd->nc[dim0]; i++)
5744 loc[dim0] = i;
5745 make_load_communicator(dd, 1, loc);
5748 if (dd->ndim > 2)
5750 dim0 = dd->dim[0];
5751 for (i = 0; i < dd->nc[dim0]; i++)
5753 loc[dim0] = i;
5754 dim1 = dd->dim[1];
5755 for (j = 0; j < dd->nc[dim1]; j++)
5757 loc[dim1] = j;
5758 make_load_communicator(dd, 2, loc);
5763 if (debug)
5765 fprintf(debug, "Finished making load communicators\n");
5767 #endif
5770 void setup_dd_grid(FILE *fplog, gmx_domdec_t *dd)
5772 int d, dim, i, j, m;
5773 ivec tmp, s;
5774 int nzone, nzonep;
5775 ivec dd_zp[DD_MAXIZONE];
5776 gmx_domdec_zones_t *zones;
5777 gmx_domdec_ns_ranges_t *izone;
5779 for (d = 0; d < dd->ndim; d++)
5781 dim = dd->dim[d];
5782 copy_ivec(dd->ci, tmp);
5783 tmp[dim] = (tmp[dim] + 1) % dd->nc[dim];
5784 dd->neighbor[d][0] = ddcoord2ddnodeid(dd, tmp);
5785 copy_ivec(dd->ci, tmp);
5786 tmp[dim] = (tmp[dim] - 1 + dd->nc[dim]) % dd->nc[dim];
5787 dd->neighbor[d][1] = ddcoord2ddnodeid(dd, tmp);
5788 if (debug)
5790 fprintf(debug, "DD rank %d neighbor ranks in dir %d are + %d - %d\n",
5791 dd->rank, dim,
5792 dd->neighbor[d][0],
5793 dd->neighbor[d][1]);
5797 if (fplog)
5799 fprintf(fplog, "\nMaking %dD domain decomposition grid %d x %d x %d, home cell index %d %d %d\n\n",
5800 dd->ndim,
5801 dd->nc[XX], dd->nc[YY], dd->nc[ZZ],
5802 dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
5804 switch (dd->ndim)
5806 case 3:
5807 nzone = dd_z3n;
5808 nzonep = dd_zp3n;
5809 for (i = 0; i < nzonep; i++)
5811 copy_ivec(dd_zp3[i], dd_zp[i]);
5813 break;
5814 case 2:
5815 nzone = dd_z2n;
5816 nzonep = dd_zp2n;
5817 for (i = 0; i < nzonep; i++)
5819 copy_ivec(dd_zp2[i], dd_zp[i]);
5821 break;
5822 case 1:
5823 nzone = dd_z1n;
5824 nzonep = dd_zp1n;
5825 for (i = 0; i < nzonep; i++)
5827 copy_ivec(dd_zp1[i], dd_zp[i]);
5829 break;
5830 default:
5831 gmx_fatal(FARGS, "Can only do 1, 2 or 3D domain decomposition");
5832 nzone = 0;
5833 nzonep = 0;
5836 zones = &dd->comm->zones;
5838 for (i = 0; i < nzone; i++)
5840 m = 0;
5841 clear_ivec(zones->shift[i]);
5842 for (d = 0; d < dd->ndim; d++)
5844 zones->shift[i][dd->dim[d]] = dd_zo[i][m++];
5848 zones->n = nzone;
5849 for (i = 0; i < nzone; i++)
5851 for (d = 0; d < DIM; d++)
5853 s[d] = dd->ci[d] - zones->shift[i][d];
5854 if (s[d] < 0)
5856 s[d] += dd->nc[d];
5858 else if (s[d] >= dd->nc[d])
5860 s[d] -= dd->nc[d];
5864 zones->nizone = nzonep;
5865 for (i = 0; i < zones->nizone; i++)
5867 if (dd_zp[i][0] != i)
5869 gmx_fatal(FARGS, "Internal inconsistency in the dd grid setup");
5871 izone = &zones->izone[i];
5872 izone->j0 = dd_zp[i][1];
5873 izone->j1 = dd_zp[i][2];
5874 for (dim = 0; dim < DIM; dim++)
5876 if (dd->nc[dim] == 1)
5878 /* All shifts should be allowed */
5879 izone->shift0[dim] = -1;
5880 izone->shift1[dim] = 1;
5882 else
5885 izone->shift0[d] = 0;
5886 izone->shift1[d] = 0;
5887 for(j=izone->j0; j<izone->j1; j++) {
5888 if (dd->shift[j][d] > dd->shift[i][d])
5889 izone->shift0[d] = -1;
5890 if (dd->shift[j][d] < dd->shift[i][d])
5891 izone->shift1[d] = 1;
5895 int shift_diff;
5897 /* Assume the shift are not more than 1 cell */
5898 izone->shift0[dim] = 1;
5899 izone->shift1[dim] = -1;
5900 for (j = izone->j0; j < izone->j1; j++)
5902 shift_diff = zones->shift[j][dim] - zones->shift[i][dim];
5903 if (shift_diff < izone->shift0[dim])
5905 izone->shift0[dim] = shift_diff;
5907 if (shift_diff > izone->shift1[dim])
5909 izone->shift1[dim] = shift_diff;
5916 if (dd->comm->eDLB != edlbNO)
5918 snew(dd->comm->root, dd->ndim);
5921 if (dd->comm->bRecordLoad)
5923 make_load_communicators(dd);
5927 static void make_pp_communicator(FILE *fplog, t_commrec *cr, int gmx_unused reorder)
5929 gmx_domdec_t *dd;
5930 dd = cr->dd;
5932 #ifdef GMX_MPI
5933 gmx_domdec_comm_t *comm;
5934 int rank, *buf;
5935 ivec periods;
5936 MPI_Comm comm_cart;
5938 comm = dd->comm;
5940 if (comm->bCartesianPP)
5942 /* Set up cartesian communication for the particle-particle part */
5943 if (fplog)
5945 fprintf(fplog, "Will use a Cartesian communicator: %d x %d x %d\n",
5946 dd->nc[XX], dd->nc[YY], dd->nc[ZZ]);
5949 for (int i = 0; i < DIM; i++)
5951 periods[i] = TRUE;
5953 MPI_Cart_create(cr->mpi_comm_mygroup, DIM, dd->nc, periods, reorder,
5954 &comm_cart);
5955 /* We overwrite the old communicator with the new cartesian one */
5956 cr->mpi_comm_mygroup = comm_cart;
5959 dd->mpi_comm_all = cr->mpi_comm_mygroup;
5960 MPI_Comm_rank(dd->mpi_comm_all, &dd->rank);
5962 if (comm->bCartesianPP_PME)
5964 /* Since we want to use the original cartesian setup for sim,
5965 * and not the one after split, we need to make an index.
5967 snew(comm->ddindex2ddnodeid, dd->nnodes);
5968 comm->ddindex2ddnodeid[dd_index(dd->nc, dd->ci)] = dd->rank;
5969 gmx_sumi(dd->nnodes, comm->ddindex2ddnodeid, cr);
5970 /* Get the rank of the DD master,
5971 * above we made sure that the master node is a PP node.
5973 if (MASTER(cr))
5975 rank = dd->rank;
5977 else
5979 rank = 0;
5981 MPI_Allreduce(&rank, &dd->masterrank, 1, MPI_INT, MPI_SUM, dd->mpi_comm_all);
5983 else if (comm->bCartesianPP)
5985 if (cr->npmenodes == 0)
5987 /* The PP communicator is also
5988 * the communicator for this simulation
5990 cr->mpi_comm_mysim = cr->mpi_comm_mygroup;
5992 cr->nodeid = dd->rank;
5994 MPI_Cart_coords(dd->mpi_comm_all, dd->rank, DIM, dd->ci);
5996 /* We need to make an index to go from the coordinates
5997 * to the nodeid of this simulation.
5999 snew(comm->ddindex2simnodeid, dd->nnodes);
6000 snew(buf, dd->nnodes);
6001 if (cr->duty & DUTY_PP)
6003 buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
6005 /* Communicate the ddindex to simulation nodeid index */
6006 MPI_Allreduce(buf, comm->ddindex2simnodeid, dd->nnodes, MPI_INT, MPI_SUM,
6007 cr->mpi_comm_mysim);
6008 sfree(buf);
6010 /* Determine the master coordinates and rank.
6011 * The DD master should be the same node as the master of this sim.
6013 for (int i = 0; i < dd->nnodes; i++)
6015 if (comm->ddindex2simnodeid[i] == 0)
6017 ddindex2xyz(dd->nc, i, dd->master_ci);
6018 MPI_Cart_rank(dd->mpi_comm_all, dd->master_ci, &dd->masterrank);
6021 if (debug)
6023 fprintf(debug, "The master rank is %d\n", dd->masterrank);
6026 else
6028 /* No Cartesian communicators */
6029 /* We use the rank in dd->comm->all as DD index */
6030 ddindex2xyz(dd->nc, dd->rank, dd->ci);
6031 /* The simulation master nodeid is 0, so the DD master rank is also 0 */
6032 dd->masterrank = 0;
6033 clear_ivec(dd->master_ci);
6035 #endif
6037 if (fplog)
6039 fprintf(fplog,
6040 "Domain decomposition rank %d, coordinates %d %d %d\n\n",
6041 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
6043 if (debug)
6045 fprintf(debug,
6046 "Domain decomposition rank %d, coordinates %d %d %d\n\n",
6047 dd->rank, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
6051 static void receive_ddindex2simnodeid(t_commrec gmx_unused *cr)
6053 #ifdef GMX_MPI
6054 gmx_domdec_t *dd;
6055 gmx_domdec_comm_t *comm;
6057 dd = cr->dd;
6058 comm = dd->comm;
6060 if (!comm->bCartesianPP_PME && comm->bCartesianPP)
6062 int *buf;
6063 snew(comm->ddindex2simnodeid, dd->nnodes);
6064 snew(buf, dd->nnodes);
6065 if (cr->duty & DUTY_PP)
6067 buf[dd_index(dd->nc, dd->ci)] = cr->sim_nodeid;
6069 /* Communicate the ddindex to simulation nodeid index */
6070 MPI_Allreduce(buf, comm->ddindex2simnodeid, dd->nnodes, MPI_INT, MPI_SUM,
6071 cr->mpi_comm_mysim);
6072 sfree(buf);
6074 #endif
6077 static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
6078 int ncg, int natoms)
6080 gmx_domdec_master_t *ma;
6081 int i;
6083 snew(ma, 1);
6085 snew(ma->ncg, dd->nnodes);
6086 snew(ma->index, dd->nnodes+1);
6087 snew(ma->cg, ncg);
6088 snew(ma->nat, dd->nnodes);
6089 snew(ma->ibuf, dd->nnodes*2);
6090 snew(ma->cell_x, DIM);
6091 for (i = 0; i < DIM; i++)
6093 snew(ma->cell_x[i], dd->nc[i]+1);
6096 if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
6098 ma->vbuf = NULL;
6100 else
6102 snew(ma->vbuf, natoms);
6105 return ma;
6108 static void split_communicator(FILE *fplog, t_commrec *cr, int gmx_unused dd_node_order,
6109 int gmx_unused reorder)
6111 gmx_domdec_t *dd;
6112 gmx_domdec_comm_t *comm;
6113 int i;
6114 gmx_bool bDiv[DIM];
6115 #ifdef GMX_MPI
6116 MPI_Comm comm_cart;
6117 #endif
6119 dd = cr->dd;
6120 comm = dd->comm;
6122 if (comm->bCartesianPP)
6124 for (i = 1; i < DIM; i++)
6126 bDiv[i] = ((cr->npmenodes*dd->nc[i]) % (dd->nnodes) == 0);
6128 if (bDiv[YY] || bDiv[ZZ])
6130 comm->bCartesianPP_PME = TRUE;
6131 /* If we have 2D PME decomposition, which is always in x+y,
6132 * we stack the PME only nodes in z.
6133 * Otherwise we choose the direction that provides the thinnest slab
6134 * of PME only nodes as this will have the least effect
6135 * on the PP communication.
6136 * But for the PME communication the opposite might be better.
6138 if (bDiv[ZZ] && (comm->npmenodes_y > 1 ||
6139 !bDiv[YY] ||
6140 dd->nc[YY] > dd->nc[ZZ]))
6142 comm->cartpmedim = ZZ;
6144 else
6146 comm->cartpmedim = YY;
6148 comm->ntot[comm->cartpmedim]
6149 += (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
6151 else if (fplog)
6153 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]);
6154 fprintf(fplog,
6155 "Will not use a Cartesian communicator for PP <-> PME\n\n");
6159 #ifdef GMX_MPI
6160 if (comm->bCartesianPP_PME)
6162 int rank;
6163 ivec periods;
6165 if (fplog)
6167 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]);
6170 for (i = 0; i < DIM; i++)
6172 periods[i] = TRUE;
6174 MPI_Cart_create(cr->mpi_comm_mysim, DIM, comm->ntot, periods, reorder,
6175 &comm_cart);
6176 MPI_Comm_rank(comm_cart, &rank);
6177 if (MASTERNODE(cr) && rank != 0)
6179 gmx_fatal(FARGS, "MPI rank 0 was renumbered by MPI_Cart_create, we do not allow this");
6182 /* With this assigment we loose the link to the original communicator
6183 * which will usually be MPI_COMM_WORLD, unless have multisim.
6185 cr->mpi_comm_mysim = comm_cart;
6186 cr->sim_nodeid = rank;
6188 MPI_Cart_coords(cr->mpi_comm_mysim, cr->sim_nodeid, DIM, dd->ci);
6190 if (fplog)
6192 fprintf(fplog, "Cartesian rank %d, coordinates %d %d %d\n\n",
6193 cr->sim_nodeid, dd->ci[XX], dd->ci[YY], dd->ci[ZZ]);
6196 if (dd->ci[comm->cartpmedim] < dd->nc[comm->cartpmedim])
6198 cr->duty = DUTY_PP;
6200 if (cr->npmenodes == 0 ||
6201 dd->ci[comm->cartpmedim] >= dd->nc[comm->cartpmedim])
6203 cr->duty = DUTY_PME;
6206 /* Split the sim communicator into PP and PME only nodes */
6207 MPI_Comm_split(cr->mpi_comm_mysim,
6208 cr->duty,
6209 dd_index(comm->ntot, dd->ci),
6210 &cr->mpi_comm_mygroup);
6212 else
6214 switch (dd_node_order)
6216 case ddnoPP_PME:
6217 if (fplog)
6219 fprintf(fplog, "Order of the ranks: PP first, PME last\n");
6221 break;
6222 case ddnoINTERLEAVE:
6223 /* Interleave the PP-only and PME-only nodes,
6224 * as on clusters with dual-core machines this will double
6225 * the communication bandwidth of the PME processes
6226 * and thus speed up the PP <-> PME and inter PME communication.
6228 if (fplog)
6230 fprintf(fplog, "Interleaving PP and PME ranks\n");
6232 comm->pmenodes = dd_pmenodes(cr);
6233 break;
6234 case ddnoCARTESIAN:
6235 break;
6236 default:
6237 gmx_fatal(FARGS, "Unknown dd_node_order=%d", dd_node_order);
6240 if (dd_simnode2pmenode(cr, cr->sim_nodeid) == -1)
6242 cr->duty = DUTY_PME;
6244 else
6246 cr->duty = DUTY_PP;
6249 /* Split the sim communicator into PP and PME only nodes */
6250 MPI_Comm_split(cr->mpi_comm_mysim,
6251 cr->duty,
6252 cr->nodeid,
6253 &cr->mpi_comm_mygroup);
6254 MPI_Comm_rank(cr->mpi_comm_mygroup, &cr->nodeid);
6256 #endif
6258 if (fplog)
6260 fprintf(fplog, "This rank does only %s work.\n\n",
6261 (cr->duty & DUTY_PP) ? "particle-particle" : "PME-mesh");
6265 void make_dd_communicators(FILE *fplog, t_commrec *cr, int dd_node_order)
6267 gmx_domdec_t *dd;
6268 gmx_domdec_comm_t *comm;
6269 int CartReorder;
6271 dd = cr->dd;
6272 comm = dd->comm;
6274 copy_ivec(dd->nc, comm->ntot);
6276 comm->bCartesianPP = (dd_node_order == ddnoCARTESIAN);
6277 comm->bCartesianPP_PME = FALSE;
6279 /* Reorder the nodes by default. This might change the MPI ranks.
6280 * Real reordering is only supported on very few architectures,
6281 * Blue Gene is one of them.
6283 CartReorder = (getenv("GMX_NO_CART_REORDER") == NULL);
6285 if (cr->npmenodes > 0)
6287 /* Split the communicator into a PP and PME part */
6288 split_communicator(fplog, cr, dd_node_order, CartReorder);
6289 if (comm->bCartesianPP_PME)
6291 /* We (possibly) reordered the nodes in split_communicator,
6292 * so it is no longer required in make_pp_communicator.
6294 CartReorder = FALSE;
6297 else
6299 /* All nodes do PP and PME */
6300 #ifdef GMX_MPI
6301 /* We do not require separate communicators */
6302 cr->mpi_comm_mygroup = cr->mpi_comm_mysim;
6303 #endif
6306 if (cr->duty & DUTY_PP)
6308 /* Copy or make a new PP communicator */
6309 make_pp_communicator(fplog, cr, CartReorder);
6311 else
6313 receive_ddindex2simnodeid(cr);
6316 if (!(cr->duty & DUTY_PME))
6318 /* Set up the commnuication to our PME node */
6319 dd->pme_nodeid = dd_simnode2pmenode(cr, cr->sim_nodeid);
6320 dd->pme_receive_vir_ener = receive_vir_ener(cr);
6321 if (debug)
6323 fprintf(debug, "My pme_nodeid %d receive ener %d\n",
6324 dd->pme_nodeid, dd->pme_receive_vir_ener);
6327 else
6329 dd->pme_nodeid = -1;
6332 if (DDMASTER(dd))
6334 dd->ma = init_gmx_domdec_master_t(dd,
6335 comm->cgs_gl.nr,
6336 comm->cgs_gl.index[comm->cgs_gl.nr]);
6340 static real *get_slb_frac(FILE *fplog, const char *dir, int nc, const char *size_string)
6342 real *slb_frac, tot;
6343 int i, n;
6344 double dbl;
6346 slb_frac = NULL;
6347 if (nc > 1 && size_string != NULL)
6349 if (fplog)
6351 fprintf(fplog, "Using static load balancing for the %s direction\n",
6352 dir);
6354 snew(slb_frac, nc);
6355 tot = 0;
6356 for (i = 0; i < nc; i++)
6358 dbl = 0;
6359 sscanf(size_string, "%20lf%n", &dbl, &n);
6360 if (dbl == 0)
6362 gmx_fatal(FARGS, "Incorrect or not enough DD cell size entries for direction %s: '%s'", dir, size_string);
6364 slb_frac[i] = dbl;
6365 size_string += n;
6366 tot += slb_frac[i];
6368 /* Normalize */
6369 if (fplog)
6371 fprintf(fplog, "Relative cell sizes:");
6373 for (i = 0; i < nc; i++)
6375 slb_frac[i] /= tot;
6376 if (fplog)
6378 fprintf(fplog, " %5.3f", slb_frac[i]);
6381 if (fplog)
6383 fprintf(fplog, "\n");
6387 return slb_frac;
6390 static int multi_body_bondeds_count(gmx_mtop_t *mtop)
6392 int n, nmol, ftype;
6393 gmx_mtop_ilistloop_t iloop;
6394 t_ilist *il;
6396 n = 0;
6397 iloop = gmx_mtop_ilistloop_init(mtop);
6398 while (gmx_mtop_ilistloop_next(iloop, &il, &nmol))
6400 for (ftype = 0; ftype < F_NRE; ftype++)
6402 if ((interaction_function[ftype].flags & IF_BOND) &&
6403 NRAL(ftype) > 2)
6405 n += nmol*il[ftype].nr/(1 + NRAL(ftype));
6410 return n;
6413 static int dd_getenv(FILE *fplog, const char *env_var, int def)
6415 char *val;
6416 int nst;
6418 nst = def;
6419 val = getenv(env_var);
6420 if (val)
6422 if (sscanf(val, "%20d", &nst) <= 0)
6424 nst = 1;
6426 if (fplog)
6428 fprintf(fplog, "Found env.var. %s = %s, using value %d\n",
6429 env_var, val, nst);
6433 return nst;
6436 static void dd_warning(t_commrec *cr, FILE *fplog, const char *warn_string)
6438 if (MASTER(cr))
6440 fprintf(stderr, "\n%s\n", warn_string);
6442 if (fplog)
6444 fprintf(fplog, "\n%s\n", warn_string);
6448 static void check_dd_restrictions(t_commrec *cr, gmx_domdec_t *dd,
6449 t_inputrec *ir, FILE *fplog)
6451 if (ir->ePBC == epbcSCREW &&
6452 (dd->nc[XX] == 1 || dd->nc[YY] > 1 || dd->nc[ZZ] > 1))
6454 gmx_fatal(FARGS, "With pbc=%s can only do domain decomposition in the x-direction", epbc_names[ir->ePBC]);
6457 if (ir->ns_type == ensSIMPLE)
6459 gmx_fatal(FARGS, "Domain decomposition does not support simple neighbor searching, use grid searching or run with one MPI rank");
6462 if (ir->nstlist == 0)
6464 gmx_fatal(FARGS, "Domain decomposition does not work with nstlist=0");
6467 if (ir->comm_mode == ecmANGULAR && ir->ePBC != epbcNONE)
6469 dd_warning(cr, fplog, "comm-mode angular will give incorrect results when the comm group partially crosses a periodic boundary");
6473 static real average_cellsize_min(gmx_domdec_t *dd, gmx_ddbox_t *ddbox)
6475 int di, d;
6476 real r;
6478 r = ddbox->box_size[XX];
6479 for (di = 0; di < dd->ndim; di++)
6481 d = dd->dim[di];
6482 /* Check using the initial average cell size */
6483 r = std::min(r, ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
6486 return r;
6489 static int check_dlb_support(FILE *fplog, t_commrec *cr,
6490 const char *dlb_opt, gmx_bool bRecordLoad,
6491 unsigned long Flags, t_inputrec *ir)
6493 int eDLB = -1;
6494 char buf[STRLEN];
6496 switch (dlb_opt[0])
6498 case 'a': eDLB = edlbAUTO; break;
6499 case 'n': eDLB = edlbNO; break;
6500 case 'y': eDLB = edlbYES; break;
6501 default: gmx_incons("Unknown dlb_opt");
6504 if (Flags & MD_RERUN)
6506 return edlbNO;
6509 if (!EI_DYNAMICS(ir->eI))
6511 if (eDLB == edlbYES)
6513 sprintf(buf, "NOTE: dynamic load balancing is only supported with dynamics, not with integrator '%s'\n", EI(ir->eI));
6514 dd_warning(cr, fplog, buf);
6517 return edlbNO;
6520 if (!bRecordLoad)
6522 dd_warning(cr, fplog, "NOTE: Cycle counting is not supported on this architecture, will not use dynamic load balancing\n");
6524 return edlbNO;
6527 if (Flags & MD_REPRODUCIBLE)
6529 switch (eDLB)
6531 case edlbNO:
6532 break;
6533 case edlbAUTO:
6534 dd_warning(cr, fplog, "NOTE: reproducibility requested, will not use dynamic load balancing\n");
6535 eDLB = edlbNO;
6536 break;
6537 case edlbYES:
6538 dd_warning(cr, fplog, "WARNING: reproducibility requested with dynamic load balancing, the simulation will NOT be binary reproducible\n");
6539 break;
6540 default:
6541 gmx_fatal(FARGS, "Death horror: undefined case (%d) for load balancing choice", eDLB);
6542 break;
6546 return eDLB;
6549 static void set_dd_dim(FILE *fplog, gmx_domdec_t *dd)
6551 int dim;
6553 dd->ndim = 0;
6554 if (getenv("GMX_DD_ORDER_ZYX") != NULL)
6556 /* Decomposition order z,y,x */
6557 if (fplog)
6559 fprintf(fplog, "Using domain decomposition order z, y, x\n");
6561 for (dim = DIM-1; dim >= 0; dim--)
6563 if (dd->nc[dim] > 1)
6565 dd->dim[dd->ndim++] = dim;
6569 else
6571 /* Decomposition order x,y,z */
6572 for (dim = 0; dim < DIM; dim++)
6574 if (dd->nc[dim] > 1)
6576 dd->dim[dd->ndim++] = dim;
6582 static gmx_domdec_comm_t *init_dd_comm()
6584 gmx_domdec_comm_t *comm;
6585 int i;
6587 snew(comm, 1);
6588 snew(comm->cggl_flag, DIM*2);
6589 snew(comm->cgcm_state, DIM*2);
6590 for (i = 0; i < DIM*2; i++)
6592 comm->cggl_flag_nalloc[i] = 0;
6593 comm->cgcm_state_nalloc[i] = 0;
6596 comm->nalloc_int = 0;
6597 comm->buf_int = NULL;
6599 vec_rvec_init(&comm->vbuf);
6601 comm->n_load_have = 0;
6602 comm->n_load_collect = 0;
6604 for (i = 0; i < ddnatNR-ddnatZONE; i++)
6606 comm->sum_nat[i] = 0;
6608 comm->ndecomp = 0;
6609 comm->nload = 0;
6610 comm->load_step = 0;
6611 comm->load_sum = 0;
6612 comm->load_max = 0;
6613 clear_ivec(comm->load_lim);
6614 comm->load_mdf = 0;
6615 comm->load_pme = 0;
6617 return comm;
6620 gmx_domdec_t *init_domain_decomposition(FILE *fplog, t_commrec *cr,
6621 unsigned long Flags,
6622 ivec nc,
6623 real comm_distance_min, real rconstr,
6624 const char *dlb_opt, real dlb_scale,
6625 const char *sizex, const char *sizey, const char *sizez,
6626 gmx_mtop_t *mtop, t_inputrec *ir,
6627 matrix box, rvec *x,
6628 gmx_ddbox_t *ddbox,
6629 int *npme_x, int *npme_y)
6631 gmx_domdec_t *dd;
6632 gmx_domdec_comm_t *comm;
6633 int recload;
6634 real r_2b, r_mb, r_bonded = -1, r_bonded_limit = -1, limit, acs;
6635 gmx_bool bC;
6636 char buf[STRLEN];
6637 const real tenPercentMargin = 1.1;
6639 if (fplog)
6641 fprintf(fplog,
6642 "\nInitializing Domain Decomposition on %d ranks\n", cr->nnodes);
6645 snew(dd, 1);
6647 dd->comm = init_dd_comm();
6648 comm = dd->comm;
6649 snew(comm->cggl_flag, DIM*2);
6650 snew(comm->cgcm_state, DIM*2);
6652 dd->npbcdim = ePBC2npbcdim(ir->ePBC);
6653 dd->bScrewPBC = (ir->ePBC == epbcSCREW);
6655 dd->bSendRecv2 = dd_getenv(fplog, "GMX_DD_USE_SENDRECV2", 0);
6656 comm->dlb_scale_lim = dd_getenv(fplog, "GMX_DLB_MAX_BOX_SCALING", 10);
6657 comm->eFlop = dd_getenv(fplog, "GMX_DLB_BASED_ON_FLOPS", 0);
6658 recload = dd_getenv(fplog, "GMX_DD_RECORD_LOAD", 1);
6659 comm->nstSortCG = dd_getenv(fplog, "GMX_DD_NST_SORT_CHARGE_GROUPS", 1);
6660 comm->nstDDDump = dd_getenv(fplog, "GMX_DD_NST_DUMP", 0);
6661 comm->nstDDDumpGrid = dd_getenv(fplog, "GMX_DD_NST_DUMP_GRID", 0);
6662 comm->DD_debug = dd_getenv(fplog, "GMX_DD_DEBUG", 0);
6664 dd->pme_recv_f_alloc = 0;
6665 dd->pme_recv_f_buf = NULL;
6667 if (dd->bSendRecv2 && fplog)
6669 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");
6671 if (comm->eFlop)
6673 if (fplog)
6675 fprintf(fplog, "Will load balance based on FLOP count\n");
6677 if (comm->eFlop > 1)
6679 srand(1+cr->nodeid);
6681 comm->bRecordLoad = TRUE;
6683 else
6685 comm->bRecordLoad = (wallcycle_have_counter() && recload > 0);
6689 /* Initialize to GPU share count to 0, might change later */
6690 comm->nrank_gpu_shared = 0;
6692 comm->eDLB = check_dlb_support(fplog, cr, dlb_opt, comm->bRecordLoad, Flags, ir);
6693 comm->bDLB_locked = FALSE;
6695 comm->bDynLoadBal = (comm->eDLB == edlbYES);
6696 if (fplog)
6698 fprintf(fplog, "Dynamic load balancing: %s\n", edlb_names[comm->eDLB]);
6700 dd->bGridJump = comm->bDynLoadBal;
6701 comm->bPMELoadBalDLBLimits = FALSE;
6703 if (comm->nstSortCG)
6705 if (fplog)
6707 if (comm->nstSortCG == 1)
6709 fprintf(fplog, "Will sort the charge groups at every domain (re)decomposition\n");
6711 else
6713 fprintf(fplog, "Will sort the charge groups every %d steps\n",
6714 comm->nstSortCG);
6717 snew(comm->sort, 1);
6719 else
6721 if (fplog)
6723 fprintf(fplog, "Will not sort the charge groups\n");
6727 comm->bCGs = (ncg_mtop(mtop) < mtop->natoms);
6729 comm->bInterCGBondeds = (ncg_mtop(mtop) > mtop->mols.nr);
6730 if (comm->bInterCGBondeds)
6732 comm->bInterCGMultiBody = (multi_body_bondeds_count(mtop) > 0);
6734 else
6736 comm->bInterCGMultiBody = FALSE;
6739 dd->bInterCGcons = inter_charge_group_constraints(mtop);
6740 dd->bInterCGsettles = inter_charge_group_settles(mtop);
6742 if (ir->rlistlong == 0)
6744 /* Set the cut-off to some very large value,
6745 * so we don't need if statements everywhere in the code.
6746 * We use sqrt, since the cut-off is squared in some places.
6748 comm->cutoff = GMX_CUTOFF_INF;
6750 else
6752 comm->cutoff = ir->rlistlong;
6754 comm->cutoff_mbody = 0;
6756 comm->cellsize_limit = 0;
6757 comm->bBondComm = FALSE;
6759 /* Atoms should be able to move by up to half the list buffer size (if > 0)
6760 * within nstlist steps. Since boundaries are allowed to displace by half
6761 * a cell size, DD cells should be at least the size of the list buffer.
6763 comm->cellsize_limit = std::max(comm->cellsize_limit,
6764 ir->rlistlong - std::max(ir->rvdw, ir->rcoulomb));
6766 if (comm->bInterCGBondeds)
6768 if (comm_distance_min > 0)
6770 comm->cutoff_mbody = comm_distance_min;
6771 if (Flags & MD_DDBONDCOMM)
6773 comm->bBondComm = (comm->cutoff_mbody > comm->cutoff);
6775 else
6777 comm->cutoff = std::max(comm->cutoff, comm->cutoff_mbody);
6779 r_bonded_limit = comm->cutoff_mbody;
6781 else if (ir->bPeriodicMols)
6783 /* Can not easily determine the required cut-off */
6784 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");
6785 comm->cutoff_mbody = comm->cutoff/2;
6786 r_bonded_limit = comm->cutoff_mbody;
6788 else
6790 if (MASTER(cr))
6792 dd_bonded_cg_distance(fplog, mtop, ir, x, box,
6793 Flags & MD_DDBONDCHECK, &r_2b, &r_mb);
6795 gmx_bcast(sizeof(r_2b), &r_2b, cr);
6796 gmx_bcast(sizeof(r_mb), &r_mb, cr);
6798 /* We use an initial margin of 10% for the minimum cell size,
6799 * except when we are just below the non-bonded cut-off.
6801 if (Flags & MD_DDBONDCOMM)
6803 if (std::max(r_2b, r_mb) > comm->cutoff)
6805 r_bonded = std::max(r_2b, r_mb);
6806 r_bonded_limit = tenPercentMargin*r_bonded;
6807 comm->bBondComm = TRUE;
6809 else
6811 r_bonded = r_mb;
6812 r_bonded_limit = std::min(tenPercentMargin*r_bonded, comm->cutoff);
6814 /* We determine cutoff_mbody later */
6816 else
6818 /* No special bonded communication,
6819 * simply increase the DD cut-off.
6821 r_bonded_limit = tenPercentMargin*std::max(r_2b, r_mb);
6822 comm->cutoff_mbody = r_bonded_limit;
6823 comm->cutoff = std::max(comm->cutoff, comm->cutoff_mbody);
6826 if (fplog)
6828 fprintf(fplog,
6829 "Minimum cell size due to bonded interactions: %.3f nm\n",
6830 r_bonded_limit);
6832 comm->cellsize_limit = std::max(comm->cellsize_limit, r_bonded_limit);
6835 if (dd->bInterCGcons && rconstr <= 0)
6837 /* There is a cell size limit due to the constraints (P-LINCS) */
6838 rconstr = constr_r_max(fplog, mtop, ir);
6839 if (fplog)
6841 fprintf(fplog,
6842 "Estimated maximum distance required for P-LINCS: %.3f nm\n",
6843 rconstr);
6844 if (rconstr > comm->cellsize_limit)
6846 fprintf(fplog, "This distance will limit the DD cell size, you can override this with -rcon\n");
6850 else if (rconstr > 0 && fplog)
6852 /* Here we do not check for dd->bInterCGcons,
6853 * because one can also set a cell size limit for virtual sites only
6854 * and at this point we don't know yet if there are intercg v-sites.
6856 fprintf(fplog,
6857 "User supplied maximum distance required for P-LINCS: %.3f nm\n",
6858 rconstr);
6860 comm->cellsize_limit = std::max(comm->cellsize_limit, rconstr);
6862 comm->cgs_gl = gmx_mtop_global_cgs(mtop);
6864 if (nc[XX] > 0)
6866 copy_ivec(nc, dd->nc);
6867 set_dd_dim(fplog, dd);
6868 set_ddbox_cr(cr, &dd->nc, ir, box, &comm->cgs_gl, x, ddbox);
6870 if (cr->npmenodes == -1)
6872 cr->npmenodes = 0;
6874 acs = average_cellsize_min(dd, ddbox);
6875 if (acs < comm->cellsize_limit)
6877 if (fplog)
6879 fprintf(fplog, "ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n", acs, comm->cellsize_limit);
6881 gmx_fatal_collective(FARGS, cr, NULL,
6882 "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",
6883 acs, comm->cellsize_limit);
6886 else
6888 set_ddbox_cr(cr, NULL, ir, box, &comm->cgs_gl, x, ddbox);
6890 /* We need to choose the optimal DD grid and possibly PME nodes */
6891 limit = dd_choose_grid(fplog, cr, dd, ir, mtop, box, ddbox,
6892 comm->eDLB != edlbNO, dlb_scale,
6893 comm->cellsize_limit, comm->cutoff,
6894 comm->bInterCGBondeds);
6896 if (dd->nc[XX] == 0)
6898 bC = (dd->bInterCGcons && rconstr > r_bonded_limit);
6899 sprintf(buf, "Change the number of ranks or mdrun option %s%s%s",
6900 !bC ? "-rdd" : "-rcon",
6901 comm->eDLB != edlbNO ? " or -dds" : "",
6902 bC ? " or your LINCS settings" : "");
6904 gmx_fatal_collective(FARGS, cr, NULL,
6905 "There is no domain decomposition for %d ranks that is compatible with the given box and a minimum cell size of %g nm\n"
6906 "%s\n"
6907 "Look in the log file for details on the domain decomposition",
6908 cr->nnodes-cr->npmenodes, limit, buf);
6910 set_dd_dim(fplog, dd);
6913 if (fplog)
6915 fprintf(fplog,
6916 "Domain decomposition grid %d x %d x %d, separate PME ranks %d\n",
6917 dd->nc[XX], dd->nc[YY], dd->nc[ZZ], cr->npmenodes);
6920 dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
6921 if (cr->nnodes - dd->nnodes != cr->npmenodes)
6923 gmx_fatal_collective(FARGS, cr, NULL,
6924 "The size of the domain decomposition grid (%d) does not match the number of ranks (%d). The total number of ranks is %d",
6925 dd->nnodes, cr->nnodes - cr->npmenodes, cr->nnodes);
6927 if (cr->npmenodes > dd->nnodes)
6929 gmx_fatal_collective(FARGS, cr, NULL,
6930 "The number of separate PME ranks (%d) is larger than the number of PP ranks (%d), this is not supported.", cr->npmenodes, dd->nnodes);
6932 if (cr->npmenodes > 0)
6934 comm->npmenodes = cr->npmenodes;
6936 else
6938 comm->npmenodes = dd->nnodes;
6941 if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
6943 /* The following choices should match those
6944 * in comm_cost_est in domdec_setup.c.
6945 * Note that here the checks have to take into account
6946 * that the decomposition might occur in a different order than xyz
6947 * (for instance through the env.var. GMX_DD_ORDER_ZYX),
6948 * in which case they will not match those in comm_cost_est,
6949 * but since that is mainly for testing purposes that's fine.
6951 if (dd->ndim >= 2 && dd->dim[0] == XX && dd->dim[1] == YY &&
6952 comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
6953 getenv("GMX_PMEONEDD") == NULL)
6955 comm->npmedecompdim = 2;
6956 comm->npmenodes_x = dd->nc[XX];
6957 comm->npmenodes_y = comm->npmenodes/comm->npmenodes_x;
6959 else
6961 /* In case nc is 1 in both x and y we could still choose to
6962 * decompose pme in y instead of x, but we use x for simplicity.
6964 comm->npmedecompdim = 1;
6965 if (dd->dim[0] == YY)
6967 comm->npmenodes_x = 1;
6968 comm->npmenodes_y = comm->npmenodes;
6970 else
6972 comm->npmenodes_x = comm->npmenodes;
6973 comm->npmenodes_y = 1;
6976 if (fplog)
6978 fprintf(fplog, "PME domain decomposition: %d x %d x %d\n",
6979 comm->npmenodes_x, comm->npmenodes_y, 1);
6982 else
6984 comm->npmedecompdim = 0;
6985 comm->npmenodes_x = 0;
6986 comm->npmenodes_y = 0;
6989 /* Technically we don't need both of these,
6990 * but it simplifies code not having to recalculate it.
6992 *npme_x = comm->npmenodes_x;
6993 *npme_y = comm->npmenodes_y;
6995 snew(comm->slb_frac, DIM);
6996 if (comm->eDLB == edlbNO)
6998 comm->slb_frac[XX] = get_slb_frac(fplog, "x", dd->nc[XX], sizex);
6999 comm->slb_frac[YY] = get_slb_frac(fplog, "y", dd->nc[YY], sizey);
7000 comm->slb_frac[ZZ] = get_slb_frac(fplog, "z", dd->nc[ZZ], sizez);
7003 if (comm->bInterCGBondeds && comm->cutoff_mbody == 0)
7005 if (comm->bBondComm || comm->eDLB != edlbNO)
7007 /* Set the bonded communication distance to halfway
7008 * the minimum and the maximum,
7009 * since the extra communication cost is nearly zero.
7011 acs = average_cellsize_min(dd, ddbox);
7012 comm->cutoff_mbody = 0.5*(r_bonded + acs);
7013 if (comm->eDLB != edlbNO)
7015 /* Check if this does not limit the scaling */
7016 comm->cutoff_mbody = std::min(comm->cutoff_mbody, dlb_scale*acs);
7018 if (!comm->bBondComm)
7020 /* Without bBondComm do not go beyond the n.b. cut-off */
7021 comm->cutoff_mbody = std::min(comm->cutoff_mbody, comm->cutoff);
7022 if (comm->cellsize_limit >= comm->cutoff)
7024 /* We don't loose a lot of efficieny
7025 * when increasing it to the n.b. cut-off.
7026 * It can even be slightly faster, because we need
7027 * less checks for the communication setup.
7029 comm->cutoff_mbody = comm->cutoff;
7032 /* Check if we did not end up below our original limit */
7033 comm->cutoff_mbody = std::max(comm->cutoff_mbody, r_bonded_limit);
7035 if (comm->cutoff_mbody > comm->cellsize_limit)
7037 comm->cellsize_limit = comm->cutoff_mbody;
7040 /* Without DLB and cutoff_mbody<cutoff, cutoff_mbody is dynamic */
7043 if (debug)
7045 fprintf(debug, "Bonded atom communication beyond the cut-off: %d\n"
7046 "cellsize limit %f\n",
7047 comm->bBondComm, comm->cellsize_limit);
7050 if (MASTER(cr))
7052 check_dd_restrictions(cr, dd, ir, fplog);
7055 comm->partition_step = INT_MIN;
7056 dd->ddp_count = 0;
7058 clear_dd_cycle_counts(dd);
7060 return dd;
7063 static void set_dlb_limits(gmx_domdec_t *dd)
7066 int d;
7068 for (d = 0; d < dd->ndim; d++)
7070 dd->comm->cd[d].np = dd->comm->cd[d].np_dlb;
7071 dd->comm->cellsize_min[dd->dim[d]] =
7072 dd->comm->cellsize_min_dlb[dd->dim[d]];
7077 static void turn_on_dlb(FILE *fplog, t_commrec *cr, gmx_int64_t step)
7079 gmx_domdec_t *dd;
7080 gmx_domdec_comm_t *comm;
7081 real cellsize_min;
7082 int d, nc, i;
7083 char buf[STRLEN];
7085 dd = cr->dd;
7086 comm = dd->comm;
7088 if (fplog)
7090 fprintf(fplog, "At step %s the performance loss due to force load imbalance is %.1f %%\n", gmx_step_str(step, buf), dd_force_imb_perf_loss(dd)*100);
7093 cellsize_min = comm->cellsize_min[dd->dim[0]];
7094 for (d = 1; d < dd->ndim; d++)
7096 cellsize_min = std::min(cellsize_min, comm->cellsize_min[dd->dim[d]]);
7099 if (cellsize_min < comm->cellsize_limit*1.05)
7101 dd_warning(cr, fplog, "NOTE: the minimum cell size is smaller than 1.05 times the cell size limit, will not turn on dynamic load balancing\n");
7103 /* Change DLB from "auto" to "no". */
7104 comm->eDLB = edlbNO;
7106 return;
7109 dd_warning(cr, fplog, "NOTE: Turning on dynamic load balancing\n");
7110 comm->bDynLoadBal = TRUE;
7111 dd->bGridJump = TRUE;
7113 set_dlb_limits(dd);
7115 /* We can set the required cell size info here,
7116 * so we do not need to communicate this.
7117 * The grid is completely uniform.
7119 for (d = 0; d < dd->ndim; d++)
7121 if (comm->root[d])
7123 comm->load[d].sum_m = comm->load[d].sum;
7125 nc = dd->nc[dd->dim[d]];
7126 for (i = 0; i < nc; i++)
7128 comm->root[d]->cell_f[i] = i/(real)nc;
7129 if (d > 0)
7131 comm->root[d]->cell_f_max0[i] = i /(real)nc;
7132 comm->root[d]->cell_f_min1[i] = (i+1)/(real)nc;
7135 comm->root[d]->cell_f[nc] = 1.0;
7140 static char *init_bLocalCG(gmx_mtop_t *mtop)
7142 int ncg, cg;
7143 char *bLocalCG;
7145 ncg = ncg_mtop(mtop);
7146 snew(bLocalCG, ncg);
7147 for (cg = 0; cg < ncg; cg++)
7149 bLocalCG[cg] = FALSE;
7152 return bLocalCG;
7155 void dd_init_bondeds(FILE *fplog,
7156 gmx_domdec_t *dd, gmx_mtop_t *mtop,
7157 gmx_vsite_t *vsite,
7158 t_inputrec *ir, gmx_bool bBCheck, cginfo_mb_t *cginfo_mb)
7160 gmx_domdec_comm_t *comm;
7162 dd_make_reverse_top(fplog, dd, mtop, vsite, ir, bBCheck);
7164 comm = dd->comm;
7166 if (comm->bBondComm)
7168 /* Communicate atoms beyond the cut-off for bonded interactions */
7169 comm = dd->comm;
7171 comm->cglink = make_charge_group_links(mtop, dd, cginfo_mb);
7173 comm->bLocalCG = init_bLocalCG(mtop);
7175 else
7177 /* Only communicate atoms based on cut-off */
7178 comm->cglink = NULL;
7179 comm->bLocalCG = NULL;
7183 static void print_dd_settings(FILE *fplog, gmx_domdec_t *dd,
7184 t_inputrec *ir,
7185 gmx_bool bDynLoadBal, real dlb_scale,
7186 gmx_ddbox_t *ddbox)
7188 gmx_domdec_comm_t *comm;
7189 int d;
7190 ivec np;
7191 real limit, shrink;
7192 char buf[64];
7194 if (fplog == NULL)
7196 return;
7199 comm = dd->comm;
7201 if (bDynLoadBal)
7203 fprintf(fplog, "The maximum number of communication pulses is:");
7204 for (d = 0; d < dd->ndim; d++)
7206 fprintf(fplog, " %c %d", dim2char(dd->dim[d]), comm->cd[d].np_dlb);
7208 fprintf(fplog, "\n");
7209 fprintf(fplog, "The minimum size for domain decomposition cells is %.3f nm\n", comm->cellsize_limit);
7210 fprintf(fplog, "The requested allowed shrink of DD cells (option -dds) is: %.2f\n", dlb_scale);
7211 fprintf(fplog, "The allowed shrink of domain decomposition cells is:");
7212 for (d = 0; d < DIM; d++)
7214 if (dd->nc[d] > 1)
7216 if (d >= ddbox->npbcdim && dd->nc[d] == 2)
7218 shrink = 0;
7220 else
7222 shrink =
7223 comm->cellsize_min_dlb[d]/
7224 (ddbox->box_size[d]*ddbox->skew_fac[d]/dd->nc[d]);
7226 fprintf(fplog, " %c %.2f", dim2char(d), shrink);
7229 fprintf(fplog, "\n");
7231 else
7233 set_dd_cell_sizes_slb(dd, ddbox, setcellsizeslbPULSE_ONLY, np);
7234 fprintf(fplog, "The initial number of communication pulses is:");
7235 for (d = 0; d < dd->ndim; d++)
7237 fprintf(fplog, " %c %d", dim2char(dd->dim[d]), np[dd->dim[d]]);
7239 fprintf(fplog, "\n");
7240 fprintf(fplog, "The initial domain decomposition cell size is:");
7241 for (d = 0; d < DIM; d++)
7243 if (dd->nc[d] > 1)
7245 fprintf(fplog, " %c %.2f nm",
7246 dim2char(d), dd->comm->cellsize_min[d]);
7249 fprintf(fplog, "\n\n");
7252 if (comm->bInterCGBondeds || dd->vsite_comm || dd->constraint_comm)
7254 fprintf(fplog, "The maximum allowed distance for charge groups involved in interactions is:\n");
7255 fprintf(fplog, "%40s %-7s %6.3f nm\n",
7256 "non-bonded interactions", "", comm->cutoff);
7258 if (bDynLoadBal)
7260 limit = dd->comm->cellsize_limit;
7262 else
7264 if (dynamic_dd_box(ddbox, ir))
7266 fprintf(fplog, "(the following are initial values, they could change due to box deformation)\n");
7268 limit = dd->comm->cellsize_min[XX];
7269 for (d = 1; d < DIM; d++)
7271 limit = std::min(limit, dd->comm->cellsize_min[d]);
7275 if (comm->bInterCGBondeds)
7277 fprintf(fplog, "%40s %-7s %6.3f nm\n",
7278 "two-body bonded interactions", "(-rdd)",
7279 std::max(comm->cutoff, comm->cutoff_mbody));
7280 fprintf(fplog, "%40s %-7s %6.3f nm\n",
7281 "multi-body bonded interactions", "(-rdd)",
7282 (comm->bBondComm || dd->bGridJump) ? comm->cutoff_mbody : std::min(comm->cutoff, limit));
7284 if (dd->vsite_comm)
7286 fprintf(fplog, "%40s %-7s %6.3f nm\n",
7287 "virtual site constructions", "(-rcon)", limit);
7289 if (dd->constraint_comm)
7291 sprintf(buf, "atoms separated by up to %d constraints",
7292 1+ir->nProjOrder);
7293 fprintf(fplog, "%40s %-7s %6.3f nm\n",
7294 buf, "(-rcon)", limit);
7296 fprintf(fplog, "\n");
7299 fflush(fplog);
7302 static void set_cell_limits_dlb(gmx_domdec_t *dd,
7303 real dlb_scale,
7304 const t_inputrec *ir,
7305 const gmx_ddbox_t *ddbox)
7307 gmx_domdec_comm_t *comm;
7308 int d, dim, npulse, npulse_d_max, npulse_d;
7309 gmx_bool bNoCutOff;
7311 comm = dd->comm;
7313 bNoCutOff = (ir->rvdw == 0 || ir->rcoulomb == 0);
7315 /* Determine the maximum number of comm. pulses in one dimension */
7317 comm->cellsize_limit = std::max(comm->cellsize_limit, comm->cutoff_mbody);
7319 /* Determine the maximum required number of grid pulses */
7320 if (comm->cellsize_limit >= comm->cutoff)
7322 /* Only a single pulse is required */
7323 npulse = 1;
7325 else if (!bNoCutOff && comm->cellsize_limit > 0)
7327 /* We round down slightly here to avoid overhead due to the latency
7328 * of extra communication calls when the cut-off
7329 * would be only slightly longer than the cell size.
7330 * Later cellsize_limit is redetermined,
7331 * so we can not miss interactions due to this rounding.
7333 npulse = (int)(0.96 + comm->cutoff/comm->cellsize_limit);
7335 else
7337 /* There is no cell size limit */
7338 npulse = std::max(dd->nc[XX]-1, std::max(dd->nc[YY]-1, dd->nc[ZZ]-1));
7341 if (!bNoCutOff && npulse > 1)
7343 /* See if we can do with less pulses, based on dlb_scale */
7344 npulse_d_max = 0;
7345 for (d = 0; d < dd->ndim; d++)
7347 dim = dd->dim[d];
7348 npulse_d = (int)(1 + dd->nc[dim]*comm->cutoff
7349 /(ddbox->box_size[dim]*ddbox->skew_fac[dim]*dlb_scale));
7350 npulse_d_max = std::max(npulse_d_max, npulse_d);
7352 npulse = std::min(npulse, npulse_d_max);
7355 /* This env var can override npulse */
7356 d = dd_getenv(debug, "GMX_DD_NPULSE", 0);
7357 if (d > 0)
7359 npulse = d;
7362 comm->maxpulse = 1;
7363 comm->bVacDLBNoLimit = (ir->ePBC == epbcNONE);
7364 for (d = 0; d < dd->ndim; d++)
7366 comm->cd[d].np_dlb = std::min(npulse, dd->nc[dd->dim[d]]-1);
7367 comm->cd[d].np_nalloc = comm->cd[d].np_dlb;
7368 snew(comm->cd[d].ind, comm->cd[d].np_nalloc);
7369 comm->maxpulse = std::max(comm->maxpulse, comm->cd[d].np_dlb);
7370 if (comm->cd[d].np_dlb < dd->nc[dd->dim[d]]-1)
7372 comm->bVacDLBNoLimit = FALSE;
7376 /* cellsize_limit is set for LINCS in init_domain_decomposition */
7377 if (!comm->bVacDLBNoLimit)
7379 comm->cellsize_limit = std::max(comm->cellsize_limit,
7380 comm->cutoff/comm->maxpulse);
7382 comm->cellsize_limit = std::max(comm->cellsize_limit, comm->cutoff_mbody);
7383 /* Set the minimum cell size for each DD dimension */
7384 for (d = 0; d < dd->ndim; d++)
7386 if (comm->bVacDLBNoLimit ||
7387 comm->cd[d].np_dlb*comm->cellsize_limit >= comm->cutoff)
7389 comm->cellsize_min_dlb[dd->dim[d]] = comm->cellsize_limit;
7391 else
7393 comm->cellsize_min_dlb[dd->dim[d]] =
7394 comm->cutoff/comm->cd[d].np_dlb;
7397 if (comm->cutoff_mbody <= 0)
7399 comm->cutoff_mbody = std::min(comm->cutoff, comm->cellsize_limit);
7401 if (comm->bDynLoadBal)
7403 set_dlb_limits(dd);
7407 gmx_bool dd_bonded_molpbc(gmx_domdec_t *dd, int ePBC)
7409 /* If each molecule is a single charge group
7410 * or we use domain decomposition for each periodic dimension,
7411 * we do not need to take pbc into account for the bonded interactions.
7413 return (ePBC != epbcNONE && dd->comm->bInterCGBondeds &&
7414 !(dd->nc[XX] > 1 &&
7415 dd->nc[YY] > 1 &&
7416 (dd->nc[ZZ] > 1 || ePBC == epbcXY)));
7419 void set_dd_parameters(FILE *fplog, gmx_domdec_t *dd, real dlb_scale,
7420 t_inputrec *ir, gmx_ddbox_t *ddbox)
7422 gmx_domdec_comm_t *comm;
7423 int natoms_tot;
7424 real vol_frac;
7426 comm = dd->comm;
7428 /* Initialize the thread data.
7429 * This can not be done in init_domain_decomposition,
7430 * as the numbers of threads is determined later.
7432 comm->nth = gmx_omp_nthreads_get(emntDomdec);
7433 if (comm->nth > 1)
7435 snew(comm->dth, comm->nth);
7438 if (EEL_PME(ir->coulombtype) || EVDW_PME(ir->vdwtype))
7440 init_ddpme(dd, &comm->ddpme[0], 0);
7441 if (comm->npmedecompdim >= 2)
7443 init_ddpme(dd, &comm->ddpme[1], 1);
7446 else
7448 comm->npmenodes = 0;
7449 if (dd->pme_nodeid >= 0)
7451 gmx_fatal_collective(FARGS, NULL, dd,
7452 "Can not have separate PME ranks without PME electrostatics");
7456 if (debug)
7458 fprintf(debug, "The DD cut-off is %f\n", comm->cutoff);
7460 if (comm->eDLB != edlbNO)
7462 set_cell_limits_dlb(dd, dlb_scale, ir, ddbox);
7465 print_dd_settings(fplog, dd, ir, comm->bDynLoadBal, dlb_scale, ddbox);
7466 if (comm->eDLB == edlbAUTO)
7468 if (fplog)
7470 fprintf(fplog, "When dynamic load balancing gets turned on, these settings will change to:\n");
7472 print_dd_settings(fplog, dd, ir, TRUE, dlb_scale, ddbox);
7475 if (ir->ePBC == epbcNONE)
7477 vol_frac = 1 - 1/(double)dd->nnodes;
7479 else
7481 vol_frac =
7482 (1 + comm_box_frac(dd->nc, comm->cutoff, ddbox))/(double)dd->nnodes;
7484 if (debug)
7486 fprintf(debug, "Volume fraction for all DD zones: %f\n", vol_frac);
7488 natoms_tot = comm->cgs_gl.index[comm->cgs_gl.nr];
7490 dd->ga2la = ga2la_init(natoms_tot, static_cast<int>(vol_frac*natoms_tot));
7493 static gmx_bool test_dd_cutoff(t_commrec *cr,
7494 t_state *state, t_inputrec *ir,
7495 real cutoff_req)
7497 gmx_domdec_t *dd;
7498 gmx_ddbox_t ddbox;
7499 int d, dim, np;
7500 real inv_cell_size;
7501 int LocallyLimited;
7503 dd = cr->dd;
7505 set_ddbox(dd, FALSE, cr, ir, state->box,
7506 TRUE, &dd->comm->cgs_gl, state->x, &ddbox);
7508 LocallyLimited = 0;
7510 for (d = 0; d < dd->ndim; d++)
7512 dim = dd->dim[d];
7514 inv_cell_size = DD_CELL_MARGIN*dd->nc[dim]/ddbox.box_size[dim];
7515 if (dynamic_dd_box(&ddbox, ir))
7517 inv_cell_size *= DD_PRES_SCALE_MARGIN;
7520 np = 1 + (int)(cutoff_req*inv_cell_size*ddbox.skew_fac[dim]);
7522 if (dd->comm->eDLB != edlbNO && dim < ddbox.npbcdim &&
7523 dd->comm->cd[d].np_dlb > 0)
7525 if (np > dd->comm->cd[d].np_dlb)
7527 return FALSE;
7530 /* If a current local cell size is smaller than the requested
7531 * cut-off, we could still fix it, but this gets very complicated.
7532 * Without fixing here, we might actually need more checks.
7534 if ((dd->comm->cell_x1[dim] - dd->comm->cell_x0[dim])*ddbox.skew_fac[dim]*dd->comm->cd[d].np_dlb < cutoff_req)
7536 LocallyLimited = 1;
7541 if (dd->comm->eDLB != edlbNO)
7543 /* If DLB is not active yet, we don't need to check the grid jumps.
7544 * Actually we shouldn't, because then the grid jump data is not set.
7546 if (dd->comm->bDynLoadBal &&
7547 check_grid_jump(0, dd, cutoff_req, &ddbox, FALSE))
7549 LocallyLimited = 1;
7552 gmx_sumi(1, &LocallyLimited, cr);
7554 if (LocallyLimited > 0)
7556 return FALSE;
7560 return TRUE;
7563 gmx_bool change_dd_cutoff(t_commrec *cr, t_state *state, t_inputrec *ir,
7564 real cutoff_req)
7566 gmx_bool bCutoffAllowed;
7568 bCutoffAllowed = test_dd_cutoff(cr, state, ir, cutoff_req);
7570 if (bCutoffAllowed)
7572 cr->dd->comm->cutoff = cutoff_req;
7575 return bCutoffAllowed;
7578 void change_dd_dlb_cutoff_limit(t_commrec *cr)
7580 gmx_domdec_comm_t *comm;
7582 comm = cr->dd->comm;
7584 /* Turn on the DLB limiting (might have been on already) */
7585 comm->bPMELoadBalDLBLimits = TRUE;
7587 /* Change the cut-off limit */
7588 comm->PMELoadBal_max_cutoff = comm->cutoff;
7591 gmx_bool dd_dlb_is_locked(const gmx_domdec_t *dd)
7593 return dd->comm->bDLB_locked;
7596 void dd_dlb_set_lock(gmx_domdec_t *dd, gmx_bool bValue)
7598 /* We can only lock the DLB when it is set to auto, otherwise don't lock */
7599 if (dd->comm->eDLB == edlbAUTO)
7601 dd->comm->bDLB_locked = bValue;
7605 static void merge_cg_buffers(int ncell,
7606 gmx_domdec_comm_dim_t *cd, int pulse,
7607 int *ncg_cell,
7608 int *index_gl, int *recv_i,
7609 rvec *cg_cm, rvec *recv_vr,
7610 int *cgindex,
7611 cginfo_mb_t *cginfo_mb, int *cginfo)
7613 gmx_domdec_ind_t *ind, *ind_p;
7614 int p, cell, c, cg, cg0, cg1, cg_gl, nat;
7615 int shift, shift_at;
7617 ind = &cd->ind[pulse];
7619 /* First correct the already stored data */
7620 shift = ind->nrecv[ncell];
7621 for (cell = ncell-1; cell >= 0; cell--)
7623 shift -= ind->nrecv[cell];
7624 if (shift > 0)
7626 /* Move the cg's present from previous grid pulses */
7627 cg0 = ncg_cell[ncell+cell];
7628 cg1 = ncg_cell[ncell+cell+1];
7629 cgindex[cg1+shift] = cgindex[cg1];
7630 for (cg = cg1-1; cg >= cg0; cg--)
7632 index_gl[cg+shift] = index_gl[cg];
7633 copy_rvec(cg_cm[cg], cg_cm[cg+shift]);
7634 cgindex[cg+shift] = cgindex[cg];
7635 cginfo[cg+shift] = cginfo[cg];
7637 /* Correct the already stored send indices for the shift */
7638 for (p = 1; p <= pulse; p++)
7640 ind_p = &cd->ind[p];
7641 cg0 = 0;
7642 for (c = 0; c < cell; c++)
7644 cg0 += ind_p->nsend[c];
7646 cg1 = cg0 + ind_p->nsend[cell];
7647 for (cg = cg0; cg < cg1; cg++)
7649 ind_p->index[cg] += shift;
7655 /* Merge in the communicated buffers */
7656 shift = 0;
7657 shift_at = 0;
7658 cg0 = 0;
7659 for (cell = 0; cell < ncell; cell++)
7661 cg1 = ncg_cell[ncell+cell+1] + shift;
7662 if (shift_at > 0)
7664 /* Correct the old cg indices */
7665 for (cg = ncg_cell[ncell+cell]; cg < cg1; cg++)
7667 cgindex[cg+1] += shift_at;
7670 for (cg = 0; cg < ind->nrecv[cell]; cg++)
7672 /* Copy this charge group from the buffer */
7673 index_gl[cg1] = recv_i[cg0];
7674 copy_rvec(recv_vr[cg0], cg_cm[cg1]);
7675 /* Add it to the cgindex */
7676 cg_gl = index_gl[cg1];
7677 cginfo[cg1] = ddcginfo(cginfo_mb, cg_gl);
7678 nat = GET_CGINFO_NATOMS(cginfo[cg1]);
7679 cgindex[cg1+1] = cgindex[cg1] + nat;
7680 cg0++;
7681 cg1++;
7682 shift_at += nat;
7684 shift += ind->nrecv[cell];
7685 ncg_cell[ncell+cell+1] = cg1;
7689 static void make_cell2at_index(gmx_domdec_comm_dim_t *cd,
7690 int nzone, int cg0, const int *cgindex)
7692 int cg, zone, p;
7694 /* Store the atom block boundaries for easy copying of communication buffers
7696 cg = cg0;
7697 for (zone = 0; zone < nzone; zone++)
7699 for (p = 0; p < cd->np; p++)
7701 cd->ind[p].cell2at0[zone] = cgindex[cg];
7702 cg += cd->ind[p].nrecv[zone];
7703 cd->ind[p].cell2at1[zone] = cgindex[cg];
7708 static gmx_bool missing_link(t_blocka *link, int cg_gl, char *bLocalCG)
7710 int i;
7711 gmx_bool bMiss;
7713 bMiss = FALSE;
7714 for (i = link->index[cg_gl]; i < link->index[cg_gl+1]; i++)
7716 if (!bLocalCG[link->a[i]])
7718 bMiss = TRUE;
7722 return bMiss;
7725 /* Domain corners for communication, a maximum of 4 i-zones see a j domain */
7726 typedef struct {
7727 real c[DIM][4]; /* the corners for the non-bonded communication */
7728 real cr0; /* corner for rounding */
7729 real cr1[4]; /* corners for rounding */
7730 real bc[DIM]; /* corners for bounded communication */
7731 real bcr1; /* corner for rounding for bonded communication */
7732 } dd_corners_t;
7734 /* Determine the corners of the domain(s) we are communicating with */
7735 static void
7736 set_dd_corners(const gmx_domdec_t *dd,
7737 int dim0, int dim1, int dim2,
7738 gmx_bool bDistMB,
7739 dd_corners_t *c)
7741 const gmx_domdec_comm_t *comm;
7742 const gmx_domdec_zones_t *zones;
7743 int i, j;
7745 comm = dd->comm;
7747 zones = &comm->zones;
7749 /* Keep the compiler happy */
7750 c->cr0 = 0;
7751 c->bcr1 = 0;
7753 /* The first dimension is equal for all cells */
7754 c->c[0][0] = comm->cell_x0[dim0];
7755 if (bDistMB)
7757 c->bc[0] = c->c[0][0];
7759 if (dd->ndim >= 2)
7761 dim1 = dd->dim[1];
7762 /* This cell row is only seen from the first row */
7763 c->c[1][0] = comm->cell_x0[dim1];
7764 /* All rows can see this row */
7765 c->c[1][1] = comm->cell_x0[dim1];
7766 if (dd->bGridJump)
7768 c->c[1][1] = std::max(comm->cell_x0[dim1], comm->zone_d1[1].mch0);
7769 if (bDistMB)
7771 /* For the multi-body distance we need the maximum */
7772 c->bc[1] = std::max(comm->cell_x0[dim1], comm->zone_d1[1].p1_0);
7775 /* Set the upper-right corner for rounding */
7776 c->cr0 = comm->cell_x1[dim0];
7778 if (dd->ndim >= 3)
7780 dim2 = dd->dim[2];
7781 for (j = 0; j < 4; j++)
7783 c->c[2][j] = comm->cell_x0[dim2];
7785 if (dd->bGridJump)
7787 /* Use the maximum of the i-cells that see a j-cell */
7788 for (i = 0; i < zones->nizone; i++)
7790 for (j = zones->izone[i].j0; j < zones->izone[i].j1; j++)
7792 if (j >= 4)
7794 c->c[2][j-4] =
7795 std::max(c->c[2][j-4],
7796 comm->zone_d2[zones->shift[i][dim0]][zones->shift[i][dim1]].mch0);
7800 if (bDistMB)
7802 /* For the multi-body distance we need the maximum */
7803 c->bc[2] = comm->cell_x0[dim2];
7804 for (i = 0; i < 2; i++)
7806 for (j = 0; j < 2; j++)
7808 c->bc[2] = std::max(c->bc[2], comm->zone_d2[i][j].p1_0);
7814 /* Set the upper-right corner for rounding */
7815 /* Cell (0,0,0) and cell (1,0,0) can see cell 4 (0,1,1)
7816 * Only cell (0,0,0) can see cell 7 (1,1,1)
7818 c->cr1[0] = comm->cell_x1[dim1];
7819 c->cr1[3] = comm->cell_x1[dim1];
7820 if (dd->bGridJump)
7822 c->cr1[0] = std::max(comm->cell_x1[dim1], comm->zone_d1[1].mch1);
7823 if (bDistMB)
7825 /* For the multi-body distance we need the maximum */
7826 c->bcr1 = std::max(comm->cell_x1[dim1], comm->zone_d1[1].p1_1);
7833 /* Determine which cg's we need to send in this pulse from this zone */
7834 static void
7835 get_zone_pulse_cgs(gmx_domdec_t *dd,
7836 int zonei, int zone,
7837 int cg0, int cg1,
7838 const int *index_gl,
7839 const int *cgindex,
7840 int dim, int dim_ind,
7841 int dim0, int dim1, int dim2,
7842 real r_comm2, real r_bcomm2,
7843 matrix box,
7844 ivec tric_dist,
7845 rvec *normal,
7846 real skew_fac2_d, real skew_fac_01,
7847 rvec *v_d, rvec *v_0, rvec *v_1,
7848 const dd_corners_t *c,
7849 rvec sf2_round,
7850 gmx_bool bDistBonded,
7851 gmx_bool bBondComm,
7852 gmx_bool bDist2B,
7853 gmx_bool bDistMB,
7854 rvec *cg_cm,
7855 int *cginfo,
7856 gmx_domdec_ind_t *ind,
7857 int **ibuf, int *ibuf_nalloc,
7858 vec_rvec_t *vbuf,
7859 int *nsend_ptr,
7860 int *nat_ptr,
7861 int *nsend_z_ptr)
7863 gmx_domdec_comm_t *comm;
7864 gmx_bool bScrew;
7865 gmx_bool bDistMB_pulse;
7866 int cg, i;
7867 real r2, rb2, r, tric_sh;
7868 rvec rn, rb;
7869 int dimd;
7870 int nsend_z, nsend, nat;
7872 comm = dd->comm;
7874 bScrew = (dd->bScrewPBC && dim == XX);
7876 bDistMB_pulse = (bDistMB && bDistBonded);
7878 nsend_z = 0;
7879 nsend = *nsend_ptr;
7880 nat = *nat_ptr;
7882 for (cg = cg0; cg < cg1; cg++)
7884 r2 = 0;
7885 rb2 = 0;
7886 if (tric_dist[dim_ind] == 0)
7888 /* Rectangular direction, easy */
7889 r = cg_cm[cg][dim] - c->c[dim_ind][zone];
7890 if (r > 0)
7892 r2 += r*r;
7894 if (bDistMB_pulse)
7896 r = cg_cm[cg][dim] - c->bc[dim_ind];
7897 if (r > 0)
7899 rb2 += r*r;
7902 /* Rounding gives at most a 16% reduction
7903 * in communicated atoms
7905 if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
7907 r = cg_cm[cg][dim0] - c->cr0;
7908 /* This is the first dimension, so always r >= 0 */
7909 r2 += r*r;
7910 if (bDistMB_pulse)
7912 rb2 += r*r;
7915 if (dim_ind == 2 && (zonei == 2 || zonei == 3))
7917 r = cg_cm[cg][dim1] - c->cr1[zone];
7918 if (r > 0)
7920 r2 += r*r;
7922 if (bDistMB_pulse)
7924 r = cg_cm[cg][dim1] - c->bcr1;
7925 if (r > 0)
7927 rb2 += r*r;
7932 else
7934 /* Triclinic direction, more complicated */
7935 clear_rvec(rn);
7936 clear_rvec(rb);
7937 /* Rounding, conservative as the skew_fac multiplication
7938 * will slightly underestimate the distance.
7940 if (dim_ind >= 1 && (zonei == 1 || zonei == 2))
7942 rn[dim0] = cg_cm[cg][dim0] - c->cr0;
7943 for (i = dim0+1; i < DIM; i++)
7945 rn[dim0] -= cg_cm[cg][i]*v_0[i][dim0];
7947 r2 = rn[dim0]*rn[dim0]*sf2_round[dim0];
7948 if (bDistMB_pulse)
7950 rb[dim0] = rn[dim0];
7951 rb2 = r2;
7953 /* Take care that the cell planes along dim0 might not
7954 * be orthogonal to those along dim1 and dim2.
7956 for (i = 1; i <= dim_ind; i++)
7958 dimd = dd->dim[i];
7959 if (normal[dim0][dimd] > 0)
7961 rn[dimd] -= rn[dim0]*normal[dim0][dimd];
7962 if (bDistMB_pulse)
7964 rb[dimd] -= rb[dim0]*normal[dim0][dimd];
7969 if (dim_ind == 2 && (zonei == 2 || zonei == 3))
7971 rn[dim1] += cg_cm[cg][dim1] - c->cr1[zone];
7972 tric_sh = 0;
7973 for (i = dim1+1; i < DIM; i++)
7975 tric_sh -= cg_cm[cg][i]*v_1[i][dim1];
7977 rn[dim1] += tric_sh;
7978 if (rn[dim1] > 0)
7980 r2 += rn[dim1]*rn[dim1]*sf2_round[dim1];
7981 /* Take care of coupling of the distances
7982 * to the planes along dim0 and dim1 through dim2.
7984 r2 -= rn[dim0]*rn[dim1]*skew_fac_01;
7985 /* Take care that the cell planes along dim1
7986 * might not be orthogonal to that along dim2.
7988 if (normal[dim1][dim2] > 0)
7990 rn[dim2] -= rn[dim1]*normal[dim1][dim2];
7993 if (bDistMB_pulse)
7995 rb[dim1] +=
7996 cg_cm[cg][dim1] - c->bcr1 + tric_sh;
7997 if (rb[dim1] > 0)
7999 rb2 += rb[dim1]*rb[dim1]*sf2_round[dim1];
8000 /* Take care of coupling of the distances
8001 * to the planes along dim0 and dim1 through dim2.
8003 rb2 -= rb[dim0]*rb[dim1]*skew_fac_01;
8004 /* Take care that the cell planes along dim1
8005 * might not be orthogonal to that along dim2.
8007 if (normal[dim1][dim2] > 0)
8009 rb[dim2] -= rb[dim1]*normal[dim1][dim2];
8014 /* The distance along the communication direction */
8015 rn[dim] += cg_cm[cg][dim] - c->c[dim_ind][zone];
8016 tric_sh = 0;
8017 for (i = dim+1; i < DIM; i++)
8019 tric_sh -= cg_cm[cg][i]*v_d[i][dim];
8021 rn[dim] += tric_sh;
8022 if (rn[dim] > 0)
8024 r2 += rn[dim]*rn[dim]*skew_fac2_d;
8025 /* Take care of coupling of the distances
8026 * to the planes along dim0 and dim1 through dim2.
8028 if (dim_ind == 1 && zonei == 1)
8030 r2 -= rn[dim0]*rn[dim]*skew_fac_01;
8033 if (bDistMB_pulse)
8035 clear_rvec(rb);
8036 rb[dim] += cg_cm[cg][dim] - c->bc[dim_ind] + tric_sh;
8037 if (rb[dim] > 0)
8039 rb2 += rb[dim]*rb[dim]*skew_fac2_d;
8040 /* Take care of coupling of the distances
8041 * to the planes along dim0 and dim1 through dim2.
8043 if (dim_ind == 1 && zonei == 1)
8045 rb2 -= rb[dim0]*rb[dim]*skew_fac_01;
8051 if (r2 < r_comm2 ||
8052 (bDistBonded &&
8053 ((bDistMB && rb2 < r_bcomm2) ||
8054 (bDist2B && r2 < r_bcomm2)) &&
8055 (!bBondComm ||
8056 (GET_CGINFO_BOND_INTER(cginfo[cg]) &&
8057 missing_link(comm->cglink, index_gl[cg],
8058 comm->bLocalCG)))))
8060 /* Make an index to the local charge groups */
8061 if (nsend+1 > ind->nalloc)
8063 ind->nalloc = over_alloc_large(nsend+1);
8064 srenew(ind->index, ind->nalloc);
8066 if (nsend+1 > *ibuf_nalloc)
8068 *ibuf_nalloc = over_alloc_large(nsend+1);
8069 srenew(*ibuf, *ibuf_nalloc);
8071 ind->index[nsend] = cg;
8072 (*ibuf)[nsend] = index_gl[cg];
8073 nsend_z++;
8074 vec_rvec_check_alloc(vbuf, nsend+1);
8076 if (dd->ci[dim] == 0)
8078 /* Correct cg_cm for pbc */
8079 rvec_add(cg_cm[cg], box[dim], vbuf->v[nsend]);
8080 if (bScrew)
8082 vbuf->v[nsend][YY] = box[YY][YY] - vbuf->v[nsend][YY];
8083 vbuf->v[nsend][ZZ] = box[ZZ][ZZ] - vbuf->v[nsend][ZZ];
8086 else
8088 copy_rvec(cg_cm[cg], vbuf->v[nsend]);
8090 nsend++;
8091 nat += cgindex[cg+1] - cgindex[cg];
8095 *nsend_ptr = nsend;
8096 *nat_ptr = nat;
8097 *nsend_z_ptr = nsend_z;
8100 static void setup_dd_communication(gmx_domdec_t *dd,
8101 matrix box, gmx_ddbox_t *ddbox,
8102 t_forcerec *fr, t_state *state, rvec **f)
8104 int dim_ind, dim, dim0, dim1, dim2, dimd, p, nat_tot;
8105 int nzone, nzone_send, zone, zonei, cg0, cg1;
8106 int c, i, cg, cg_gl, nrcg;
8107 int *zone_cg_range, pos_cg, *index_gl, *cgindex, *recv_i;
8108 gmx_domdec_comm_t *comm;
8109 gmx_domdec_zones_t *zones;
8110 gmx_domdec_comm_dim_t *cd;
8111 gmx_domdec_ind_t *ind;
8112 cginfo_mb_t *cginfo_mb;
8113 gmx_bool bBondComm, bDist2B, bDistMB, bDistBonded;
8114 real r_comm2, r_bcomm2;
8115 dd_corners_t corners;
8116 ivec tric_dist;
8117 rvec *cg_cm, *normal, *v_d, *v_0 = NULL, *v_1 = NULL, *recv_vr;
8118 real skew_fac2_d, skew_fac_01;
8119 rvec sf2_round;
8120 int nsend, nat;
8121 int th;
8123 if (debug)
8125 fprintf(debug, "Setting up DD communication\n");
8128 comm = dd->comm;
8130 switch (fr->cutoff_scheme)
8132 case ecutsGROUP:
8133 cg_cm = fr->cg_cm;
8134 break;
8135 case ecutsVERLET:
8136 cg_cm = state->x;
8137 break;
8138 default:
8139 gmx_incons("unimplemented");
8140 cg_cm = NULL;
8143 for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
8145 /* Check if we need to use triclinic distances */
8146 tric_dist[dim_ind] = 0;
8147 for (i = 0; i <= dim_ind; i++)
8149 if (ddbox->tric_dir[dd->dim[i]])
8151 tric_dist[dim_ind] = 1;
8156 bBondComm = comm->bBondComm;
8158 /* Do we need to determine extra distances for multi-body bondeds? */
8159 bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
8161 /* Do we need to determine extra distances for only two-body bondeds? */
8162 bDist2B = (bBondComm && !bDistMB);
8164 r_comm2 = sqr(comm->cutoff);
8165 r_bcomm2 = sqr(comm->cutoff_mbody);
8167 if (debug)
8169 fprintf(debug, "bBondComm %d, r_bc %f\n", bBondComm, sqrt(r_bcomm2));
8172 zones = &comm->zones;
8174 dim0 = dd->dim[0];
8175 dim1 = (dd->ndim >= 2 ? dd->dim[1] : -1);
8176 dim2 = (dd->ndim >= 3 ? dd->dim[2] : -1);
8178 set_dd_corners(dd, dim0, dim1, dim2, bDistMB, &corners);
8180 /* Triclinic stuff */
8181 normal = ddbox->normal;
8182 skew_fac_01 = 0;
8183 if (dd->ndim >= 2)
8185 v_0 = ddbox->v[dim0];
8186 if (ddbox->tric_dir[dim0] && ddbox->tric_dir[dim1])
8188 /* Determine the coupling coefficient for the distances
8189 * to the cell planes along dim0 and dim1 through dim2.
8190 * This is required for correct rounding.
8192 skew_fac_01 =
8193 ddbox->v[dim0][dim1+1][dim0]*ddbox->v[dim1][dim1+1][dim1];
8194 if (debug)
8196 fprintf(debug, "\nskew_fac_01 %f\n", skew_fac_01);
8200 if (dd->ndim >= 3)
8202 v_1 = ddbox->v[dim1];
8205 zone_cg_range = zones->cg_range;
8206 index_gl = dd->index_gl;
8207 cgindex = dd->cgindex;
8208 cginfo_mb = fr->cginfo_mb;
8210 zone_cg_range[0] = 0;
8211 zone_cg_range[1] = dd->ncg_home;
8212 comm->zone_ncg1[0] = dd->ncg_home;
8213 pos_cg = dd->ncg_home;
8215 nat_tot = dd->nat_home;
8216 nzone = 1;
8217 for (dim_ind = 0; dim_ind < dd->ndim; dim_ind++)
8219 dim = dd->dim[dim_ind];
8220 cd = &comm->cd[dim_ind];
8222 if (dim >= ddbox->npbcdim && dd->ci[dim] == 0)
8224 /* No pbc in this dimension, the first node should not comm. */
8225 nzone_send = 0;
8227 else
8229 nzone_send = nzone;
8232 v_d = ddbox->v[dim];
8233 skew_fac2_d = sqr(ddbox->skew_fac[dim]);
8235 cd->bInPlace = TRUE;
8236 for (p = 0; p < cd->np; p++)
8238 /* Only atoms communicated in the first pulse are used
8239 * for multi-body bonded interactions or for bBondComm.
8241 bDistBonded = ((bDistMB || bDist2B) && p == 0);
8243 ind = &cd->ind[p];
8244 nsend = 0;
8245 nat = 0;
8246 for (zone = 0; zone < nzone_send; zone++)
8248 if (tric_dist[dim_ind] && dim_ind > 0)
8250 /* Determine slightly more optimized skew_fac's
8251 * for rounding.
8252 * This reduces the number of communicated atoms
8253 * by about 10% for 3D DD of rhombic dodecahedra.
8255 for (dimd = 0; dimd < dim; dimd++)
8257 sf2_round[dimd] = 1;
8258 if (ddbox->tric_dir[dimd])
8260 for (i = dd->dim[dimd]+1; i < DIM; i++)
8262 /* If we are shifted in dimension i
8263 * and the cell plane is tilted forward
8264 * in dimension i, skip this coupling.
8266 if (!(zones->shift[nzone+zone][i] &&
8267 ddbox->v[dimd][i][dimd] >= 0))
8269 sf2_round[dimd] +=
8270 sqr(ddbox->v[dimd][i][dimd]);
8273 sf2_round[dimd] = 1/sf2_round[dimd];
8278 zonei = zone_perm[dim_ind][zone];
8279 if (p == 0)
8281 /* Here we permutate the zones to obtain a convenient order
8282 * for neighbor searching
8284 cg0 = zone_cg_range[zonei];
8285 cg1 = zone_cg_range[zonei+1];
8287 else
8289 /* Look only at the cg's received in the previous grid pulse
8291 cg1 = zone_cg_range[nzone+zone+1];
8292 cg0 = cg1 - cd->ind[p-1].nrecv[zone];
8295 #pragma omp parallel for num_threads(comm->nth) schedule(static)
8296 for (th = 0; th < comm->nth; th++)
8298 gmx_domdec_ind_t *ind_p;
8299 int **ibuf_p, *ibuf_nalloc_p;
8300 vec_rvec_t *vbuf_p;
8301 int *nsend_p, *nat_p;
8302 int *nsend_zone_p;
8303 int cg0_th, cg1_th;
8305 if (th == 0)
8307 /* Thread 0 writes in the comm buffers */
8308 ind_p = ind;
8309 ibuf_p = &comm->buf_int;
8310 ibuf_nalloc_p = &comm->nalloc_int;
8311 vbuf_p = &comm->vbuf;
8312 nsend_p = &nsend;
8313 nat_p = &nat;
8314 nsend_zone_p = &ind->nsend[zone];
8316 else
8318 /* Other threads write into temp buffers */
8319 ind_p = &comm->dth[th].ind;
8320 ibuf_p = &comm->dth[th].ibuf;
8321 ibuf_nalloc_p = &comm->dth[th].ibuf_nalloc;
8322 vbuf_p = &comm->dth[th].vbuf;
8323 nsend_p = &comm->dth[th].nsend;
8324 nat_p = &comm->dth[th].nat;
8325 nsend_zone_p = &comm->dth[th].nsend_zone;
8327 comm->dth[th].nsend = 0;
8328 comm->dth[th].nat = 0;
8329 comm->dth[th].nsend_zone = 0;
8332 if (comm->nth == 1)
8334 cg0_th = cg0;
8335 cg1_th = cg1;
8337 else
8339 cg0_th = cg0 + ((cg1 - cg0)* th )/comm->nth;
8340 cg1_th = cg0 + ((cg1 - cg0)*(th+1))/comm->nth;
8343 /* Get the cg's for this pulse in this zone */
8344 get_zone_pulse_cgs(dd, zonei, zone, cg0_th, cg1_th,
8345 index_gl, cgindex,
8346 dim, dim_ind, dim0, dim1, dim2,
8347 r_comm2, r_bcomm2,
8348 box, tric_dist,
8349 normal, skew_fac2_d, skew_fac_01,
8350 v_d, v_0, v_1, &corners, sf2_round,
8351 bDistBonded, bBondComm,
8352 bDist2B, bDistMB,
8353 cg_cm, fr->cginfo,
8354 ind_p,
8355 ibuf_p, ibuf_nalloc_p,
8356 vbuf_p,
8357 nsend_p, nat_p,
8358 nsend_zone_p);
8361 /* Append data of threads>=1 to the communication buffers */
8362 for (th = 1; th < comm->nth; th++)
8364 dd_comm_setup_work_t *dth;
8365 int i, ns1;
8367 dth = &comm->dth[th];
8369 ns1 = nsend + dth->nsend_zone;
8370 if (ns1 > ind->nalloc)
8372 ind->nalloc = over_alloc_dd(ns1);
8373 srenew(ind->index, ind->nalloc);
8375 if (ns1 > comm->nalloc_int)
8377 comm->nalloc_int = over_alloc_dd(ns1);
8378 srenew(comm->buf_int, comm->nalloc_int);
8380 if (ns1 > comm->vbuf.nalloc)
8382 comm->vbuf.nalloc = over_alloc_dd(ns1);
8383 srenew(comm->vbuf.v, comm->vbuf.nalloc);
8386 for (i = 0; i < dth->nsend_zone; i++)
8388 ind->index[nsend] = dth->ind.index[i];
8389 comm->buf_int[nsend] = dth->ibuf[i];
8390 copy_rvec(dth->vbuf.v[i],
8391 comm->vbuf.v[nsend]);
8392 nsend++;
8394 nat += dth->nat;
8395 ind->nsend[zone] += dth->nsend_zone;
8398 /* Clear the counts in case we do not have pbc */
8399 for (zone = nzone_send; zone < nzone; zone++)
8401 ind->nsend[zone] = 0;
8403 ind->nsend[nzone] = nsend;
8404 ind->nsend[nzone+1] = nat;
8405 /* Communicate the number of cg's and atoms to receive */
8406 dd_sendrecv_int(dd, dim_ind, dddirBackward,
8407 ind->nsend, nzone+2,
8408 ind->nrecv, nzone+2);
8410 /* The rvec buffer is also required for atom buffers of size nsend
8411 * in dd_move_x and dd_move_f.
8413 vec_rvec_check_alloc(&comm->vbuf, ind->nsend[nzone+1]);
8415 if (p > 0)
8417 /* We can receive in place if only the last zone is not empty */
8418 for (zone = 0; zone < nzone-1; zone++)
8420 if (ind->nrecv[zone] > 0)
8422 cd->bInPlace = FALSE;
8425 if (!cd->bInPlace)
8427 /* The int buffer is only required here for the cg indices */
8428 if (ind->nrecv[nzone] > comm->nalloc_int2)
8430 comm->nalloc_int2 = over_alloc_dd(ind->nrecv[nzone]);
8431 srenew(comm->buf_int2, comm->nalloc_int2);
8433 /* The rvec buffer is also required for atom buffers
8434 * of size nrecv in dd_move_x and dd_move_f.
8436 i = std::max(cd->ind[0].nrecv[nzone+1], ind->nrecv[nzone+1]);
8437 vec_rvec_check_alloc(&comm->vbuf2, i);
8441 /* Make space for the global cg indices */
8442 if (pos_cg + ind->nrecv[nzone] > dd->cg_nalloc
8443 || dd->cg_nalloc == 0)
8445 dd->cg_nalloc = over_alloc_dd(pos_cg + ind->nrecv[nzone]);
8446 srenew(index_gl, dd->cg_nalloc);
8447 srenew(cgindex, dd->cg_nalloc+1);
8449 /* Communicate the global cg indices */
8450 if (cd->bInPlace)
8452 recv_i = index_gl + pos_cg;
8454 else
8456 recv_i = comm->buf_int2;
8458 dd_sendrecv_int(dd, dim_ind, dddirBackward,
8459 comm->buf_int, nsend,
8460 recv_i, ind->nrecv[nzone]);
8462 /* Make space for cg_cm */
8463 dd_check_alloc_ncg(fr, state, f, pos_cg + ind->nrecv[nzone]);
8464 if (fr->cutoff_scheme == ecutsGROUP)
8466 cg_cm = fr->cg_cm;
8468 else
8470 cg_cm = state->x;
8472 /* Communicate cg_cm */
8473 if (cd->bInPlace)
8475 recv_vr = cg_cm + pos_cg;
8477 else
8479 recv_vr = comm->vbuf2.v;
8481 dd_sendrecv_rvec(dd, dim_ind, dddirBackward,
8482 comm->vbuf.v, nsend,
8483 recv_vr, ind->nrecv[nzone]);
8485 /* Make the charge group index */
8486 if (cd->bInPlace)
8488 zone = (p == 0 ? 0 : nzone - 1);
8489 while (zone < nzone)
8491 for (cg = 0; cg < ind->nrecv[zone]; cg++)
8493 cg_gl = index_gl[pos_cg];
8494 fr->cginfo[pos_cg] = ddcginfo(cginfo_mb, cg_gl);
8495 nrcg = GET_CGINFO_NATOMS(fr->cginfo[pos_cg]);
8496 cgindex[pos_cg+1] = cgindex[pos_cg] + nrcg;
8497 if (bBondComm)
8499 /* Update the charge group presence,
8500 * so we can use it in the next pass of the loop.
8502 comm->bLocalCG[cg_gl] = TRUE;
8504 pos_cg++;
8506 if (p == 0)
8508 comm->zone_ncg1[nzone+zone] = ind->nrecv[zone];
8510 zone++;
8511 zone_cg_range[nzone+zone] = pos_cg;
8514 else
8516 /* This part of the code is never executed with bBondComm. */
8517 merge_cg_buffers(nzone, cd, p, zone_cg_range,
8518 index_gl, recv_i, cg_cm, recv_vr,
8519 cgindex, fr->cginfo_mb, fr->cginfo);
8520 pos_cg += ind->nrecv[nzone];
8522 nat_tot += ind->nrecv[nzone+1];
8524 if (!cd->bInPlace)
8526 /* Store the atom block for easy copying of communication buffers */
8527 make_cell2at_index(cd, nzone, zone_cg_range[nzone], cgindex);
8529 nzone += nzone;
8531 dd->index_gl = index_gl;
8532 dd->cgindex = cgindex;
8534 dd->ncg_tot = zone_cg_range[zones->n];
8535 dd->nat_tot = nat_tot;
8536 comm->nat[ddnatHOME] = dd->nat_home;
8537 for (i = ddnatZONE; i < ddnatNR; i++)
8539 comm->nat[i] = dd->nat_tot;
8542 if (!bBondComm)
8544 /* We don't need to update cginfo, since that was alrady done above.
8545 * So we pass NULL for the forcerec.
8547 dd_set_cginfo(dd->index_gl, dd->ncg_home, dd->ncg_tot,
8548 NULL, comm->bLocalCG);
8551 if (debug)
8553 fprintf(debug, "Finished setting up DD communication, zones:");
8554 for (c = 0; c < zones->n; c++)
8556 fprintf(debug, " %d", zones->cg_range[c+1]-zones->cg_range[c]);
8558 fprintf(debug, "\n");
8562 static void set_cg_boundaries(gmx_domdec_zones_t *zones)
8564 int c;
8566 for (c = 0; c < zones->nizone; c++)
8568 zones->izone[c].cg1 = zones->cg_range[c+1];
8569 zones->izone[c].jcg0 = zones->cg_range[zones->izone[c].j0];
8570 zones->izone[c].jcg1 = zones->cg_range[zones->izone[c].j1];
8574 static void set_zones_size(gmx_domdec_t *dd,
8575 matrix box, const gmx_ddbox_t *ddbox,
8576 int zone_start, int zone_end)
8578 gmx_domdec_comm_t *comm;
8579 gmx_domdec_zones_t *zones;
8580 gmx_bool bDistMB;
8581 int z, zi, d, dim;
8582 real rcs, rcmbs;
8583 int i, j;
8584 real vol;
8586 comm = dd->comm;
8588 zones = &comm->zones;
8590 /* Do we need to determine extra distances for multi-body bondeds? */
8591 bDistMB = (comm->bInterCGMultiBody && dd->bGridJump && dd->ndim > 1);
8593 for (z = zone_start; z < zone_end; z++)
8595 /* Copy cell limits to zone limits.
8596 * Valid for non-DD dims and non-shifted dims.
8598 copy_rvec(comm->cell_x0, zones->size[z].x0);
8599 copy_rvec(comm->cell_x1, zones->size[z].x1);
8602 for (d = 0; d < dd->ndim; d++)
8604 dim = dd->dim[d];
8606 for (z = 0; z < zones->n; z++)
8608 /* With a staggered grid we have different sizes
8609 * for non-shifted dimensions.
8611 if (dd->bGridJump && zones->shift[z][dim] == 0)
8613 if (d == 1)
8615 zones->size[z].x0[dim] = comm->zone_d1[zones->shift[z][dd->dim[d-1]]].min0;
8616 zones->size[z].x1[dim] = comm->zone_d1[zones->shift[z][dd->dim[d-1]]].max1;
8618 else if (d == 2)
8620 zones->size[z].x0[dim] = comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].min0;
8621 zones->size[z].x1[dim] = comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].max1;
8626 rcs = comm->cutoff;
8627 rcmbs = comm->cutoff_mbody;
8628 if (ddbox->tric_dir[dim])
8630 rcs /= ddbox->skew_fac[dim];
8631 rcmbs /= ddbox->skew_fac[dim];
8634 /* Set the lower limit for the shifted zone dimensions */
8635 for (z = zone_start; z < zone_end; z++)
8637 if (zones->shift[z][dim] > 0)
8639 dim = dd->dim[d];
8640 if (!dd->bGridJump || d == 0)
8642 zones->size[z].x0[dim] = comm->cell_x1[dim];
8643 zones->size[z].x1[dim] = comm->cell_x1[dim] + rcs;
8645 else
8647 /* Here we take the lower limit of the zone from
8648 * the lowest domain of the zone below.
8650 if (z < 4)
8652 zones->size[z].x0[dim] =
8653 comm->zone_d1[zones->shift[z][dd->dim[d-1]]].min1;
8655 else
8657 if (d == 1)
8659 zones->size[z].x0[dim] =
8660 zones->size[zone_perm[2][z-4]].x0[dim];
8662 else
8664 zones->size[z].x0[dim] =
8665 comm->zone_d2[zones->shift[z][dd->dim[d-2]]][zones->shift[z][dd->dim[d-1]]].min1;
8668 /* A temporary limit, is updated below */
8669 zones->size[z].x1[dim] = zones->size[z].x0[dim];
8671 if (bDistMB)
8673 for (zi = 0; zi < zones->nizone; zi++)
8675 if (zones->shift[zi][dim] == 0)
8677 /* This takes the whole zone into account.
8678 * With multiple pulses this will lead
8679 * to a larger zone then strictly necessary.
8681 zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim],
8682 zones->size[zi].x1[dim]+rcmbs);
8690 /* Loop over the i-zones to set the upper limit of each
8691 * j-zone they see.
8693 for (zi = 0; zi < zones->nizone; zi++)
8695 if (zones->shift[zi][dim] == 0)
8697 for (z = zones->izone[zi].j0; z < zones->izone[zi].j1; z++)
8699 if (zones->shift[z][dim] > 0)
8701 zones->size[z].x1[dim] = std::max(zones->size[z].x1[dim],
8702 zones->size[zi].x1[dim]+rcs);
8709 for (z = zone_start; z < zone_end; z++)
8711 /* Initialization only required to keep the compiler happy */
8712 rvec corner_min = {0, 0, 0}, corner_max = {0, 0, 0}, corner;
8713 int nc, c;
8715 /* To determine the bounding box for a zone we need to find
8716 * the extreme corners of 4, 2 or 1 corners.
8718 nc = 1 << (ddbox->npbcdim - 1);
8720 for (c = 0; c < nc; c++)
8722 /* Set up a zone corner at x=0, ignoring trilinic couplings */
8723 corner[XX] = 0;
8724 if ((c & 1) == 0)
8726 corner[YY] = zones->size[z].x0[YY];
8728 else
8730 corner[YY] = zones->size[z].x1[YY];
8732 if ((c & 2) == 0)
8734 corner[ZZ] = zones->size[z].x0[ZZ];
8736 else
8738 corner[ZZ] = zones->size[z].x1[ZZ];
8740 /* Apply the triclinic couplings */
8741 assert(ddbox->npbcdim <= DIM);
8742 for (i = YY; i < ddbox->npbcdim; i++)
8744 for (j = XX; j < i; j++)
8746 /* With 1D domain decomposition the cg's are not in
8747 * a triclinic box, but triclinic x-y and rectangular y/x-z.
8748 * So we should ignore the coupling for the non
8749 * domain-decomposed dimension of the pair x and y.
8751 if (!(dd->ndim == 1 && ((dd->dim[0] == XX && j == YY) ||
8752 (dd->dim[0] == YY && j == XX))))
8754 corner[j] += corner[i]*box[i][j]/box[i][i];
8758 if (c == 0)
8760 copy_rvec(corner, corner_min);
8761 copy_rvec(corner, corner_max);
8763 else
8765 for (i = 0; i < DIM; i++)
8767 corner_min[i] = std::min(corner_min[i], corner[i]);
8768 corner_max[i] = std::max(corner_max[i], corner[i]);
8772 /* Copy the extreme cornes without offset along x */
8773 for (i = 0; i < DIM; i++)
8775 zones->size[z].bb_x0[i] = corner_min[i];
8776 zones->size[z].bb_x1[i] = corner_max[i];
8778 /* Add the offset along x */
8779 zones->size[z].bb_x0[XX] += zones->size[z].x0[XX];
8780 zones->size[z].bb_x1[XX] += zones->size[z].x1[XX];
8783 if (zone_start == 0)
8785 vol = 1;
8786 for (dim = 0; dim < DIM; dim++)
8788 vol *= zones->size[0].x1[dim] - zones->size[0].x0[dim];
8790 zones->dens_zone0 = (zones->cg_range[1] - zones->cg_range[0])/vol;
8793 if (debug)
8795 for (z = zone_start; z < zone_end; z++)
8797 fprintf(debug, "zone %d %6.3f - %6.3f %6.3f - %6.3f %6.3f - %6.3f\n",
8799 zones->size[z].x0[XX], zones->size[z].x1[XX],
8800 zones->size[z].x0[YY], zones->size[z].x1[YY],
8801 zones->size[z].x0[ZZ], zones->size[z].x1[ZZ]);
8802 fprintf(debug, "zone %d bb %6.3f - %6.3f %6.3f - %6.3f %6.3f - %6.3f\n",
8804 zones->size[z].bb_x0[XX], zones->size[z].bb_x1[XX],
8805 zones->size[z].bb_x0[YY], zones->size[z].bb_x1[YY],
8806 zones->size[z].bb_x0[ZZ], zones->size[z].bb_x1[ZZ]);
8811 static int comp_cgsort(const void *a, const void *b)
8813 int comp;
8815 gmx_cgsort_t *cga, *cgb;
8816 cga = (gmx_cgsort_t *)a;
8817 cgb = (gmx_cgsort_t *)b;
8819 comp = cga->nsc - cgb->nsc;
8820 if (comp == 0)
8822 comp = cga->ind_gl - cgb->ind_gl;
8825 return comp;
8828 static void order_int_cg(int n, const gmx_cgsort_t *sort,
8829 int *a, int *buf)
8831 int i;
8833 /* Order the data */
8834 for (i = 0; i < n; i++)
8836 buf[i] = a[sort[i].ind];
8839 /* Copy back to the original array */
8840 for (i = 0; i < n; i++)
8842 a[i] = buf[i];
8846 static void order_vec_cg(int n, const gmx_cgsort_t *sort,
8847 rvec *v, rvec *buf)
8849 int i;
8851 /* Order the data */
8852 for (i = 0; i < n; i++)
8854 copy_rvec(v[sort[i].ind], buf[i]);
8857 /* Copy back to the original array */
8858 for (i = 0; i < n; i++)
8860 copy_rvec(buf[i], v[i]);
8864 static void order_vec_atom(int ncg, const int *cgindex, const gmx_cgsort_t *sort,
8865 rvec *v, rvec *buf)
8867 int a, atot, cg, cg0, cg1, i;
8869 if (cgindex == NULL)
8871 /* Avoid the useless loop of the atoms within a cg */
8872 order_vec_cg(ncg, sort, v, buf);
8874 return;
8877 /* Order the data */
8878 a = 0;
8879 for (cg = 0; cg < ncg; cg++)
8881 cg0 = cgindex[sort[cg].ind];
8882 cg1 = cgindex[sort[cg].ind+1];
8883 for (i = cg0; i < cg1; i++)
8885 copy_rvec(v[i], buf[a]);
8886 a++;
8889 atot = a;
8891 /* Copy back to the original array */
8892 for (a = 0; a < atot; a++)
8894 copy_rvec(buf[a], v[a]);
8898 static void ordered_sort(int nsort2, gmx_cgsort_t *sort2,
8899 int nsort_new, gmx_cgsort_t *sort_new,
8900 gmx_cgsort_t *sort1)
8902 int i1, i2, i_new;
8904 /* The new indices are not very ordered, so we qsort them */
8905 gmx_qsort_threadsafe(sort_new, nsort_new, sizeof(sort_new[0]), comp_cgsort);
8907 /* sort2 is already ordered, so now we can merge the two arrays */
8908 i1 = 0;
8909 i2 = 0;
8910 i_new = 0;
8911 while (i2 < nsort2 || i_new < nsort_new)
8913 if (i2 == nsort2)
8915 sort1[i1++] = sort_new[i_new++];
8917 else if (i_new == nsort_new)
8919 sort1[i1++] = sort2[i2++];
8921 else if (sort2[i2].nsc < sort_new[i_new].nsc ||
8922 (sort2[i2].nsc == sort_new[i_new].nsc &&
8923 sort2[i2].ind_gl < sort_new[i_new].ind_gl))
8925 sort1[i1++] = sort2[i2++];
8927 else
8929 sort1[i1++] = sort_new[i_new++];
8934 static int dd_sort_order(gmx_domdec_t *dd, t_forcerec *fr, int ncg_home_old)
8936 gmx_domdec_sort_t *sort;
8937 gmx_cgsort_t *cgsort, *sort_i;
8938 int ncg_new, nsort2, nsort_new, i, *a, moved;
8940 sort = dd->comm->sort;
8942 a = fr->ns.grid->cell_index;
8944 moved = NSGRID_SIGNAL_MOVED_FAC*fr->ns.grid->ncells;
8946 if (ncg_home_old >= 0)
8948 /* The charge groups that remained in the same ns grid cell
8949 * are completely ordered. So we can sort efficiently by sorting
8950 * the charge groups that did move into the stationary list.
8952 ncg_new = 0;
8953 nsort2 = 0;
8954 nsort_new = 0;
8955 for (i = 0; i < dd->ncg_home; i++)
8957 /* Check if this cg did not move to another node */
8958 if (a[i] < moved)
8960 if (i >= ncg_home_old || a[i] != sort->sort[i].nsc)
8962 /* This cg is new on this node or moved ns grid cell */
8963 if (nsort_new >= sort->sort_new_nalloc)
8965 sort->sort_new_nalloc = over_alloc_dd(nsort_new+1);
8966 srenew(sort->sort_new, sort->sort_new_nalloc);
8968 sort_i = &(sort->sort_new[nsort_new++]);
8970 else
8972 /* This cg did not move */
8973 sort_i = &(sort->sort2[nsort2++]);
8975 /* Sort on the ns grid cell indices
8976 * and the global topology index.
8977 * index_gl is irrelevant with cell ns,
8978 * but we set it here anyhow to avoid a conditional.
8980 sort_i->nsc = a[i];
8981 sort_i->ind_gl = dd->index_gl[i];
8982 sort_i->ind = i;
8983 ncg_new++;
8986 if (debug)
8988 fprintf(debug, "ordered sort cgs: stationary %d moved %d\n",
8989 nsort2, nsort_new);
8991 /* Sort efficiently */
8992 ordered_sort(nsort2, sort->sort2, nsort_new, sort->sort_new,
8993 sort->sort);
8995 else
8997 cgsort = sort->sort;
8998 ncg_new = 0;
8999 for (i = 0; i < dd->ncg_home; i++)
9001 /* Sort on the ns grid cell indices
9002 * and the global topology index
9004 cgsort[i].nsc = a[i];
9005 cgsort[i].ind_gl = dd->index_gl[i];
9006 cgsort[i].ind = i;
9007 if (cgsort[i].nsc < moved)
9009 ncg_new++;
9012 if (debug)
9014 fprintf(debug, "qsort cgs: %d new home %d\n", dd->ncg_home, ncg_new);
9016 /* Determine the order of the charge groups using qsort */
9017 gmx_qsort_threadsafe(cgsort, dd->ncg_home, sizeof(cgsort[0]), comp_cgsort);
9020 return ncg_new;
9023 static int dd_sort_order_nbnxn(gmx_domdec_t *dd, t_forcerec *fr)
9025 gmx_cgsort_t *sort;
9026 int ncg_new, i, *a, na;
9028 sort = dd->comm->sort->sort;
9030 nbnxn_get_atomorder(fr->nbv->nbs, &a, &na);
9032 ncg_new = 0;
9033 for (i = 0; i < na; i++)
9035 if (a[i] >= 0)
9037 sort[ncg_new].ind = a[i];
9038 ncg_new++;
9042 return ncg_new;
9045 static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state *state,
9046 int ncg_home_old)
9048 gmx_domdec_sort_t *sort;
9049 gmx_cgsort_t *cgsort;
9050 int *cgindex;
9051 int ncg_new, i, *ibuf, cgsize;
9052 rvec *vbuf;
9054 sort = dd->comm->sort;
9056 if (dd->ncg_home > sort->sort_nalloc)
9058 sort->sort_nalloc = over_alloc_dd(dd->ncg_home);
9059 srenew(sort->sort, sort->sort_nalloc);
9060 srenew(sort->sort2, sort->sort_nalloc);
9062 cgsort = sort->sort;
9064 switch (fr->cutoff_scheme)
9066 case ecutsGROUP:
9067 ncg_new = dd_sort_order(dd, fr, ncg_home_old);
9068 break;
9069 case ecutsVERLET:
9070 ncg_new = dd_sort_order_nbnxn(dd, fr);
9071 break;
9072 default:
9073 gmx_incons("unimplemented");
9074 ncg_new = 0;
9077 /* We alloc with the old size, since cgindex is still old */
9078 vec_rvec_check_alloc(&dd->comm->vbuf, dd->cgindex[dd->ncg_home]);
9079 vbuf = dd->comm->vbuf.v;
9081 if (dd->comm->bCGs)
9083 cgindex = dd->cgindex;
9085 else
9087 cgindex = NULL;
9090 /* Remove the charge groups which are no longer at home here */
9091 dd->ncg_home = ncg_new;
9092 if (debug)
9094 fprintf(debug, "Set the new home charge group count to %d\n",
9095 dd->ncg_home);
9098 /* Reorder the state */
9099 for (i = 0; i < estNR; i++)
9101 if (EST_DISTR(i) && (state->flags & (1<<i)))
9103 switch (i)
9105 case estX:
9106 order_vec_atom(dd->ncg_home, cgindex, cgsort, state->x, vbuf);
9107 break;
9108 case estV:
9109 order_vec_atom(dd->ncg_home, cgindex, cgsort, state->v, vbuf);
9110 break;
9111 case estSDX:
9112 order_vec_atom(dd->ncg_home, cgindex, cgsort, state->sd_X, vbuf);
9113 break;
9114 case estCGP:
9115 order_vec_atom(dd->ncg_home, cgindex, cgsort, state->cg_p, vbuf);
9116 break;
9117 case estLD_RNG:
9118 case estLD_RNGI:
9119 case estDISRE_INITF:
9120 case estDISRE_RM3TAV:
9121 case estORIRE_INITF:
9122 case estORIRE_DTAV:
9123 /* No ordering required */
9124 break;
9125 default:
9126 gmx_incons("Unknown state entry encountered in dd_sort_state");
9127 break;
9131 if (fr->cutoff_scheme == ecutsGROUP)
9133 /* Reorder cgcm */
9134 order_vec_cg(dd->ncg_home, cgsort, cgcm, vbuf);
9137 if (dd->ncg_home+1 > sort->ibuf_nalloc)
9139 sort->ibuf_nalloc = over_alloc_dd(dd->ncg_home+1);
9140 srenew(sort->ibuf, sort->ibuf_nalloc);
9142 ibuf = sort->ibuf;
9143 /* Reorder the global cg index */
9144 order_int_cg(dd->ncg_home, cgsort, dd->index_gl, ibuf);
9145 /* Reorder the cginfo */
9146 order_int_cg(dd->ncg_home, cgsort, fr->cginfo, ibuf);
9147 /* Rebuild the local cg index */
9148 if (dd->comm->bCGs)
9150 ibuf[0] = 0;
9151 for (i = 0; i < dd->ncg_home; i++)
9153 cgsize = dd->cgindex[cgsort[i].ind+1] - dd->cgindex[cgsort[i].ind];
9154 ibuf[i+1] = ibuf[i] + cgsize;
9156 for (i = 0; i < dd->ncg_home+1; i++)
9158 dd->cgindex[i] = ibuf[i];
9161 else
9163 for (i = 0; i < dd->ncg_home+1; i++)
9165 dd->cgindex[i] = i;
9168 /* Set the home atom number */
9169 dd->nat_home = dd->cgindex[dd->ncg_home];
9171 if (fr->cutoff_scheme == ecutsVERLET)
9173 /* The atoms are now exactly in grid order, update the grid order */
9174 nbnxn_set_atomorder(fr->nbv->nbs);
9176 else
9178 /* Copy the sorted ns cell indices back to the ns grid struct */
9179 for (i = 0; i < dd->ncg_home; i++)
9181 fr->ns.grid->cell_index[i] = cgsort[i].nsc;
9183 fr->ns.grid->nr = dd->ncg_home;
9187 static void add_dd_statistics(gmx_domdec_t *dd)
9189 gmx_domdec_comm_t *comm;
9190 int ddnat;
9192 comm = dd->comm;
9194 for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9196 comm->sum_nat[ddnat-ddnatZONE] +=
9197 comm->nat[ddnat] - comm->nat[ddnat-1];
9199 comm->ndecomp++;
9202 void reset_dd_statistics_counters(gmx_domdec_t *dd)
9204 gmx_domdec_comm_t *comm;
9205 int ddnat;
9207 comm = dd->comm;
9209 /* Reset all the statistics and counters for total run counting */
9210 for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9212 comm->sum_nat[ddnat-ddnatZONE] = 0;
9214 comm->ndecomp = 0;
9215 comm->nload = 0;
9216 comm->load_step = 0;
9217 comm->load_sum = 0;
9218 comm->load_max = 0;
9219 clear_ivec(comm->load_lim);
9220 comm->load_mdf = 0;
9221 comm->load_pme = 0;
9224 void print_dd_statistics(t_commrec *cr, t_inputrec *ir, FILE *fplog)
9226 gmx_domdec_comm_t *comm;
9227 int ddnat;
9228 double av;
9230 comm = cr->dd->comm;
9232 gmx_sumd(ddnatNR-ddnatZONE, comm->sum_nat, cr);
9234 if (fplog == NULL)
9236 return;
9239 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");
9241 for (ddnat = ddnatZONE; ddnat < ddnatNR; ddnat++)
9243 av = comm->sum_nat[ddnat-ddnatZONE]/comm->ndecomp;
9244 switch (ddnat)
9246 case ddnatZONE:
9247 fprintf(fplog,
9248 " av. #atoms communicated per step for force: %d x %.1f\n",
9249 2, av);
9250 break;
9251 case ddnatVSITE:
9252 if (cr->dd->vsite_comm)
9254 fprintf(fplog,
9255 " av. #atoms communicated per step for vsites: %d x %.1f\n",
9256 (EEL_PME(ir->coulombtype) || ir->coulombtype == eelEWALD) ? 3 : 2,
9257 av);
9259 break;
9260 case ddnatCON:
9261 if (cr->dd->constraint_comm)
9263 fprintf(fplog,
9264 " av. #atoms communicated per step for LINCS: %d x %.1f\n",
9265 1 + ir->nLincsIter, av);
9267 break;
9268 default:
9269 gmx_incons(" Unknown type for DD statistics");
9272 fprintf(fplog, "\n");
9274 if (comm->bRecordLoad && EI_DYNAMICS(ir->eI))
9276 print_dd_load_av(fplog, cr->dd);
9280 void dd_partition_system(FILE *fplog,
9281 gmx_int64_t step,
9282 t_commrec *cr,
9283 gmx_bool bMasterState,
9284 int nstglobalcomm,
9285 t_state *state_global,
9286 gmx_mtop_t *top_global,
9287 t_inputrec *ir,
9288 t_state *state_local,
9289 rvec **f,
9290 t_mdatoms *mdatoms,
9291 gmx_localtop_t *top_local,
9292 t_forcerec *fr,
9293 gmx_vsite_t *vsite,
9294 gmx_shellfc_t shellfc,
9295 gmx_constr_t constr,
9296 t_nrnb *nrnb,
9297 gmx_wallcycle_t wcycle,
9298 gmx_bool bVerbose)
9300 gmx_domdec_t *dd;
9301 gmx_domdec_comm_t *comm;
9302 gmx_ddbox_t ddbox = {0};
9303 t_block *cgs_gl;
9304 gmx_int64_t step_pcoupl;
9305 rvec cell_ns_x0, cell_ns_x1;
9306 int i, n, ncgindex_set, ncg_home_old = -1, ncg_moved, nat_f_novirsum;
9307 gmx_bool bBoxChanged, bNStGlobalComm, bDoDLB, bCheckDLB, bTurnOnDLB, bLogLoad;
9308 gmx_bool bRedist, bSortCG, bResortAll;
9309 ivec ncells_old = {0, 0, 0}, ncells_new = {0, 0, 0}, np;
9310 real grid_density;
9311 char sbuf[22];
9313 dd = cr->dd;
9314 comm = dd->comm;
9316 bBoxChanged = (bMasterState || DEFORM(*ir));
9317 if (ir->epc != epcNO)
9319 /* With nstpcouple > 1 pressure coupling happens.
9320 * one step after calculating the pressure.
9321 * Box scaling happens at the end of the MD step,
9322 * after the DD partitioning.
9323 * We therefore have to do DLB in the first partitioning
9324 * after an MD step where P-coupling occured.
9325 * We need to determine the last step in which p-coupling occurred.
9326 * MRS -- need to validate this for vv?
9328 n = ir->nstpcouple;
9329 if (n == 1)
9331 step_pcoupl = step - 1;
9333 else
9335 step_pcoupl = ((step - 1)/n)*n + 1;
9337 if (step_pcoupl >= comm->partition_step)
9339 bBoxChanged = TRUE;
9343 bNStGlobalComm = (step % nstglobalcomm == 0);
9345 if (!comm->bDynLoadBal)
9347 bDoDLB = FALSE;
9349 else
9351 /* Should we do dynamic load balacing this step?
9352 * Since it requires (possibly expensive) global communication,
9353 * we might want to do DLB less frequently.
9355 if (bBoxChanged || ir->epc != epcNO)
9357 bDoDLB = bBoxChanged;
9359 else
9361 bDoDLB = bNStGlobalComm;
9365 /* Check if we have recorded loads on the nodes */
9366 if (comm->bRecordLoad && dd_load_count(comm) > 0)
9368 if (comm->eDLB == edlbAUTO && !comm->bDynLoadBal && !dd_dlb_is_locked(dd))
9370 /* Check if we should use DLB at the second partitioning
9371 * and every 100 partitionings,
9372 * so the extra communication cost is negligible.
9374 const int nddp_chk_dlb = 100;
9375 bCheckDLB = (comm->n_load_collect == 0 ||
9376 comm->n_load_have % nddp_chk_dlb == nddp_chk_dlb - 1);
9378 else
9380 bCheckDLB = FALSE;
9383 /* Print load every nstlog, first and last step to the log file */
9384 bLogLoad = ((ir->nstlog > 0 && step % ir->nstlog == 0) ||
9385 comm->n_load_collect == 0 ||
9386 (ir->nsteps >= 0 &&
9387 (step + ir->nstlist > ir->init_step + ir->nsteps)));
9389 /* Avoid extra communication due to verbose screen output
9390 * when nstglobalcomm is set.
9392 if (bDoDLB || bLogLoad || bCheckDLB ||
9393 (bVerbose && (ir->nstlist == 0 || nstglobalcomm <= ir->nstlist)))
9395 get_load_distribution(dd, wcycle);
9396 if (DDMASTER(dd))
9398 if (bLogLoad)
9400 dd_print_load(fplog, dd, step-1);
9402 if (bVerbose)
9404 dd_print_load_verbose(dd);
9407 comm->n_load_collect++;
9409 if (bCheckDLB)
9411 /* Since the timings are node dependent, the master decides */
9412 if (DDMASTER(dd))
9414 /* Here we check if the max PME rank load is more than 0.98
9415 * the max PP force load. If so, PP DLB will not help,
9416 * since we are (almost) limited by PME. Furthermore,
9417 * DLB will cause a significant extra x/f redistribution
9418 * cost on the PME ranks, which will then surely result
9419 * in lower total performance.
9420 * This check might be fragile, since one measurement
9421 * below 0.98 (although only done once every 100 DD part.)
9422 * could turn on DLB for the rest of the run.
9424 if (cr->npmenodes > 0 &&
9425 dd_pme_f_ratio(dd) > 1 - DD_PERF_LOSS_DLB_ON)
9427 bTurnOnDLB = FALSE;
9429 else
9431 bTurnOnDLB =
9432 (dd_force_imb_perf_loss(dd) >= DD_PERF_LOSS_DLB_ON);
9434 if (debug)
9436 fprintf(debug, "step %s, imb loss %f\n",
9437 gmx_step_str(step, sbuf),
9438 dd_force_imb_perf_loss(dd));
9441 dd_bcast(dd, sizeof(bTurnOnDLB), &bTurnOnDLB);
9442 if (bTurnOnDLB)
9444 turn_on_dlb(fplog, cr, step);
9445 bDoDLB = TRUE;
9449 comm->n_load_have++;
9452 cgs_gl = &comm->cgs_gl;
9454 bRedist = FALSE;
9455 if (bMasterState)
9457 /* Clear the old state */
9458 clear_dd_indices(dd, 0, 0);
9459 ncgindex_set = 0;
9461 set_ddbox(dd, bMasterState, cr, ir, state_global->box,
9462 TRUE, cgs_gl, state_global->x, &ddbox);
9464 get_cg_distribution(fplog, step, dd, cgs_gl,
9465 state_global->box, &ddbox, state_global->x);
9467 dd_distribute_state(dd, cgs_gl,
9468 state_global, state_local, f);
9470 dd_make_local_cgs(dd, &top_local->cgs);
9472 /* Ensure that we have space for the new distribution */
9473 dd_check_alloc_ncg(fr, state_local, f, dd->ncg_home);
9475 if (fr->cutoff_scheme == ecutsGROUP)
9477 calc_cgcm(fplog, 0, dd->ncg_home,
9478 &top_local->cgs, state_local->x, fr->cg_cm);
9481 inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
9483 dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
9485 else if (state_local->ddp_count != dd->ddp_count)
9487 if (state_local->ddp_count > dd->ddp_count)
9489 gmx_fatal(FARGS, "Internal inconsistency state_local->ddp_count (%d) > dd->ddp_count (%d)", state_local->ddp_count, dd->ddp_count);
9492 if (state_local->ddp_count_cg_gl != state_local->ddp_count)
9494 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);
9497 /* Clear the old state */
9498 clear_dd_indices(dd, 0, 0);
9500 /* Build the new indices */
9501 rebuild_cgindex(dd, cgs_gl->index, state_local);
9502 make_dd_indices(dd, cgs_gl->index, 0);
9503 ncgindex_set = dd->ncg_home;
9505 if (fr->cutoff_scheme == ecutsGROUP)
9507 /* Redetermine the cg COMs */
9508 calc_cgcm(fplog, 0, dd->ncg_home,
9509 &top_local->cgs, state_local->x, fr->cg_cm);
9512 inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
9514 dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
9516 set_ddbox(dd, bMasterState, cr, ir, state_local->box,
9517 TRUE, &top_local->cgs, state_local->x, &ddbox);
9519 bRedist = comm->bDynLoadBal;
9521 else
9523 /* We have the full state, only redistribute the cgs */
9525 /* Clear the non-home indices */
9526 clear_dd_indices(dd, dd->ncg_home, dd->nat_home);
9527 ncgindex_set = 0;
9529 /* Avoid global communication for dim's without pbc and -gcom */
9530 if (!bNStGlobalComm)
9532 copy_rvec(comm->box0, ddbox.box0 );
9533 copy_rvec(comm->box_size, ddbox.box_size);
9535 set_ddbox(dd, bMasterState, cr, ir, state_local->box,
9536 bNStGlobalComm, &top_local->cgs, state_local->x, &ddbox);
9538 bBoxChanged = TRUE;
9539 bRedist = TRUE;
9541 /* For dim's without pbc and -gcom */
9542 copy_rvec(ddbox.box0, comm->box0 );
9543 copy_rvec(ddbox.box_size, comm->box_size);
9545 set_dd_cell_sizes(dd, &ddbox, dynamic_dd_box(&ddbox, ir), bMasterState, bDoDLB,
9546 step, wcycle);
9548 if (comm->nstDDDumpGrid > 0 && step % comm->nstDDDumpGrid == 0)
9550 write_dd_grid_pdb("dd_grid", step, dd, state_local->box, &ddbox);
9553 /* Check if we should sort the charge groups */
9554 if (comm->nstSortCG > 0)
9556 bSortCG = (bMasterState ||
9557 (bRedist && (step % comm->nstSortCG == 0)));
9559 else
9561 bSortCG = FALSE;
9564 ncg_home_old = dd->ncg_home;
9566 ncg_moved = 0;
9567 if (bRedist)
9569 wallcycle_sub_start(wcycle, ewcsDD_REDIST);
9571 dd_redistribute_cg(fplog, step, dd, ddbox.tric_dir,
9572 state_local, f, fr,
9573 !bSortCG, nrnb, &ncgindex_set, &ncg_moved);
9575 wallcycle_sub_stop(wcycle, ewcsDD_REDIST);
9578 get_nsgrid_boundaries(ddbox.nboundeddim, state_local->box,
9579 dd, &ddbox,
9580 &comm->cell_x0, &comm->cell_x1,
9581 dd->ncg_home, fr->cg_cm,
9582 cell_ns_x0, cell_ns_x1, &grid_density);
9584 if (bBoxChanged)
9586 comm_dd_ns_cell_sizes(dd, &ddbox, cell_ns_x0, cell_ns_x1, step);
9589 switch (fr->cutoff_scheme)
9591 case ecutsGROUP:
9592 copy_ivec(fr->ns.grid->n, ncells_old);
9593 grid_first(fplog, fr->ns.grid, dd, &ddbox,
9594 state_local->box, cell_ns_x0, cell_ns_x1,
9595 fr->rlistlong, grid_density);
9596 break;
9597 case ecutsVERLET:
9598 nbnxn_get_ncells(fr->nbv->nbs, &ncells_old[XX], &ncells_old[YY]);
9599 break;
9600 default:
9601 gmx_incons("unimplemented");
9603 /* We need to store tric_dir for dd_get_ns_ranges called from ns.c */
9604 copy_ivec(ddbox.tric_dir, comm->tric_dir);
9606 if (bSortCG)
9608 wallcycle_sub_start(wcycle, ewcsDD_GRID);
9610 /* Sort the state on charge group position.
9611 * This enables exact restarts from this step.
9612 * It also improves performance by about 15% with larger numbers
9613 * of atoms per node.
9616 /* Fill the ns grid with the home cell,
9617 * so we can sort with the indices.
9619 set_zones_ncg_home(dd);
9621 switch (fr->cutoff_scheme)
9623 case ecutsVERLET:
9624 set_zones_size(dd, state_local->box, &ddbox, 0, 1);
9626 nbnxn_put_on_grid(fr->nbv->nbs, fr->ePBC, state_local->box,
9628 comm->zones.size[0].bb_x0,
9629 comm->zones.size[0].bb_x1,
9630 0, dd->ncg_home,
9631 comm->zones.dens_zone0,
9632 fr->cginfo,
9633 state_local->x,
9634 ncg_moved, bRedist ? comm->moved : NULL,
9635 fr->nbv->grp[eintLocal].kernel_type,
9636 fr->nbv->grp[eintLocal].nbat);
9638 nbnxn_get_ncells(fr->nbv->nbs, &ncells_new[XX], &ncells_new[YY]);
9639 break;
9640 case ecutsGROUP:
9641 fill_grid(&comm->zones, fr->ns.grid, dd->ncg_home,
9642 0, dd->ncg_home, fr->cg_cm);
9644 copy_ivec(fr->ns.grid->n, ncells_new);
9645 break;
9646 default:
9647 gmx_incons("unimplemented");
9650 bResortAll = bMasterState;
9652 /* Check if we can user the old order and ns grid cell indices
9653 * of the charge groups to sort the charge groups efficiently.
9655 if (ncells_new[XX] != ncells_old[XX] ||
9656 ncells_new[YY] != ncells_old[YY] ||
9657 ncells_new[ZZ] != ncells_old[ZZ])
9659 bResortAll = TRUE;
9662 if (debug)
9664 fprintf(debug, "Step %s, sorting the %d home charge groups\n",
9665 gmx_step_str(step, sbuf), dd->ncg_home);
9667 dd_sort_state(dd, fr->cg_cm, fr, state_local,
9668 bResortAll ? -1 : ncg_home_old);
9669 /* Rebuild all the indices */
9670 ga2la_clear(dd->ga2la);
9671 ncgindex_set = 0;
9673 wallcycle_sub_stop(wcycle, ewcsDD_GRID);
9676 wallcycle_sub_start(wcycle, ewcsDD_SETUPCOMM);
9678 /* Setup up the communication and communicate the coordinates */
9679 setup_dd_communication(dd, state_local->box, &ddbox, fr, state_local, f);
9681 /* Set the indices */
9682 make_dd_indices(dd, cgs_gl->index, ncgindex_set);
9684 /* Set the charge group boundaries for neighbor searching */
9685 set_cg_boundaries(&comm->zones);
9687 if (fr->cutoff_scheme == ecutsVERLET)
9689 set_zones_size(dd, state_local->box, &ddbox,
9690 bSortCG ? 1 : 0, comm->zones.n);
9693 wallcycle_sub_stop(wcycle, ewcsDD_SETUPCOMM);
9696 write_dd_pdb("dd_home",step,"dump",top_global,cr,
9697 -1,state_local->x,state_local->box);
9700 wallcycle_sub_start(wcycle, ewcsDD_MAKETOP);
9702 /* Extract a local topology from the global topology */
9703 for (i = 0; i < dd->ndim; i++)
9705 np[dd->dim[i]] = comm->cd[i].np;
9707 dd_make_local_top(dd, &comm->zones, dd->npbcdim, state_local->box,
9708 comm->cellsize_min, np,
9710 fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : state_local->x,
9711 vsite, top_global, top_local);
9713 wallcycle_sub_stop(wcycle, ewcsDD_MAKETOP);
9715 wallcycle_sub_start(wcycle, ewcsDD_MAKECONSTR);
9717 /* Set up the special atom communication */
9718 n = comm->nat[ddnatZONE];
9719 for (i = ddnatZONE+1; i < ddnatNR; i++)
9721 switch (i)
9723 case ddnatVSITE:
9724 if (vsite && vsite->n_intercg_vsite)
9726 n = dd_make_local_vsites(dd, n, top_local->idef.il);
9728 break;
9729 case ddnatCON:
9730 if (dd->bInterCGcons || dd->bInterCGsettles)
9732 /* Only for inter-cg constraints we need special code */
9733 n = dd_make_local_constraints(dd, n, top_global, fr->cginfo,
9734 constr, ir->nProjOrder,
9735 top_local->idef.il);
9737 break;
9738 default:
9739 gmx_incons("Unknown special atom type setup");
9741 comm->nat[i] = n;
9744 wallcycle_sub_stop(wcycle, ewcsDD_MAKECONSTR);
9746 wallcycle_sub_start(wcycle, ewcsDD_TOPOTHER);
9748 /* Make space for the extra coordinates for virtual site
9749 * or constraint communication.
9751 state_local->natoms = comm->nat[ddnatNR-1];
9752 if (state_local->natoms > state_local->nalloc)
9754 dd_realloc_state(state_local, f, state_local->natoms);
9757 if (fr->bF_NoVirSum)
9759 if (vsite && vsite->n_intercg_vsite)
9761 nat_f_novirsum = comm->nat[ddnatVSITE];
9763 else
9765 if (EEL_FULL(ir->coulombtype) && dd->n_intercg_excl > 0)
9767 nat_f_novirsum = dd->nat_tot;
9769 else
9771 nat_f_novirsum = dd->nat_home;
9775 else
9777 nat_f_novirsum = 0;
9780 /* Set the number of atoms required for the force calculation.
9781 * Forces need to be constrained when using a twin-range setup
9782 * or with energy minimization. For simple simulations we could
9783 * avoid some allocation, zeroing and copying, but this is
9784 * probably not worth the complications ande checking.
9786 forcerec_set_ranges(fr, dd->ncg_home, dd->ncg_tot,
9787 dd->nat_tot, comm->nat[ddnatCON], nat_f_novirsum);
9789 /* We make the all mdatoms up to nat_tot_con.
9790 * We could save some work by only setting invmass
9791 * between nat_tot and nat_tot_con.
9793 /* This call also sets the new number of home particles to dd->nat_home */
9794 atoms2md(top_global, ir,
9795 comm->nat[ddnatCON], dd->gatindex, dd->nat_home, mdatoms);
9797 /* Now we have the charges we can sort the FE interactions */
9798 dd_sort_local_top(dd, mdatoms, top_local);
9800 if (vsite != NULL)
9802 /* Now we have updated mdatoms, we can do the last vsite bookkeeping */
9803 split_vsites_over_threads(top_local->idef.il, top_local->idef.iparams,
9804 mdatoms, FALSE, vsite);
9807 if (shellfc)
9809 /* Make the local shell stuff, currently no communication is done */
9810 make_local_shells(cr, mdatoms, shellfc);
9813 if (ir->implicit_solvent)
9815 make_local_gb(cr, fr->born, ir->gb_algorithm);
9818 setup_bonded_threading(fr, &top_local->idef);
9820 if (!(cr->duty & DUTY_PME))
9822 /* Send the charges and/or c6/sigmas to our PME only node */
9823 gmx_pme_send_parameters(cr,
9824 fr->ic,
9825 mdatoms->nChargePerturbed, mdatoms->nTypePerturbed,
9826 mdatoms->chargeA, mdatoms->chargeB,
9827 mdatoms->sqrt_c6A, mdatoms->sqrt_c6B,
9828 mdatoms->sigmaA, mdatoms->sigmaB,
9829 dd_pme_maxshift_x(dd), dd_pme_maxshift_y(dd));
9832 if (constr)
9834 set_constraints(constr, top_local, ir, mdatoms, cr);
9837 if (ir->ePull != epullNO)
9839 /* Update the local pull groups */
9840 dd_make_local_pull_groups(dd, ir->pull, mdatoms);
9843 if (ir->bRot)
9845 /* Update the local rotation groups */
9846 dd_make_local_rotation_groups(dd, ir->rot);
9849 if (ir->eSwapCoords != eswapNO)
9851 /* Update the local groups needed for ion swapping */
9852 dd_make_local_swap_groups(dd, ir->swap);
9855 /* Update the local atoms to be communicated via the IMD protocol if bIMD is TRUE. */
9856 dd_make_local_IMD_atoms(ir->bIMD, dd, ir->imd);
9858 add_dd_statistics(dd);
9860 /* Make sure we only count the cycles for this DD partitioning */
9861 clear_dd_cycle_counts(dd);
9863 /* Because the order of the atoms might have changed since
9864 * the last vsite construction, we need to communicate the constructing
9865 * atom coordinates again (for spreading the forces this MD step).
9867 dd_move_x_vsites(dd, state_local->box, state_local->x);
9869 wallcycle_sub_stop(wcycle, ewcsDD_TOPOTHER);
9871 if (comm->nstDDDump > 0 && step % comm->nstDDDump == 0)
9873 dd_move_x(dd, state_local->box, state_local->x);
9874 write_dd_pdb("dd_dump", step, "dump", top_global, cr,
9875 -1, state_local->x, state_local->box);
9878 /* Store the partitioning step */
9879 comm->partition_step = step;
9881 /* Increase the DD partitioning counter */
9882 dd->ddp_count++;
9883 /* The state currently matches this DD partitioning count, store it */
9884 state_local->ddp_count = dd->ddp_count;
9885 if (bMasterState)
9887 /* The DD master node knows the complete cg distribution,
9888 * store the count so we can possibly skip the cg info communication.
9890 comm->master_cg_ddp_count = (bSortCG ? 0 : dd->ddp_count);
9893 if (comm->DD_debug > 0)
9895 /* Set the env var GMX_DD_DEBUG if you suspect corrupted indices */
9896 check_index_consistency(dd, top_global->natoms, ncg_mtop(top_global),
9897 "after partitioning");