600a944692b31dc8ccf8553fa88c952e2d237c53
[alexxy/gromacs.git] / src / gromacs / mdlib / nsgrid.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2017,2018, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 /* This file is completely threadsafe - keep it that way! */
38 #include "gmxpre.h"
39
40 #include "nsgrid.h"
41
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #include <cmath>
46
47 #include <algorithm>
48
49 #include "gromacs/domdec/domdec.h"
50 #include "gromacs/domdec/domdec_struct.h"
51 #include "gromacs/fileio/pdbio.h"
52 #include "gromacs/gmxlib/network.h"
53 #include "gromacs/math/vec.h"
54 #include "gromacs/mdtypes/forcerec.h"
55 #include "gromacs/pbcutil/pbc.h"
56 #include "gromacs/utility/fatalerror.h"
57 #include "gromacs/utility/futil.h"
58 #include "gromacs/utility/smalloc.h"
59
60 /***********************************
61  *         Grid Routines
62  ***********************************/
63
64 const char *range_warn =
65     "Explanation: During neighborsearching, we assign each particle to a grid\n"
66     "based on its coordinates. If your system contains collisions or parameter\n"
67     "errors that give particles very high velocities you might end up with some\n"
68     "coordinates being +-Infinity or NaN (not-a-number). Obviously, we cannot\n"
69     "put these on a grid, so this is usually where we detect those errors.\n"
70     "Make sure your system is properly energy-minimized and that the potential\n"
71     "energy seems reasonable before trying again.";
72
73 static void calc_x_av_stddev(int n, rvec *x, rvec av, rvec stddev)
74 {
75     dvec s1, s2;
76     int  i, d;
77
78     clear_dvec(s1);
79     clear_dvec(s2);
80
81     for (i = 0; i < n; i++)
82     {
83         for (d = 0; d < DIM; d++)
84         {
85             s1[d] += x[i][d];
86             s2[d] += x[i][d]*x[i][d];
87         }
88     }
89
90     dsvmul(1.0/n, s1, s1);
91     dsvmul(1.0/n, s2, s2);
92
93     for (d = 0; d < DIM; d++)
94     {
95         av[d]     = s1[d];
96         stddev[d] = std::sqrt(s2[d] - s1[d]*s1[d]);
97     }
98 }
99
100 static void get_nsgrid_boundaries_vac(real av, real stddev,
101                                       real *bound0, real *bound1,
102                                       real *bdens0, real *bdens1)
103 {
104     /* Set the grid to 2 times the standard deviation of
105      * the charge group centers in both directions.
106      * For a uniform bounded distribution the width is sqrt(3)*stddev,
107      * so all charge groups fall within the width.
108      * For a sphere stddev is r/sqrt(5): 99.2% falls within the width.
109      * For a Gaussian distribution 98% fall within the width.
110      */
111     *bound0 = av - NSGRID_STDDEV_FAC*stddev;
112     *bound1 = av + NSGRID_STDDEV_FAC*stddev;
113
114     *bdens0 = av - GRID_STDDEV_FAC*stddev;
115     *bdens1 = av + GRID_STDDEV_FAC*stddev;
116 }
117
118 static void dd_box_bounds_to_ns_bounds(real box0, real box_size,
119                                        real *gr0, real *gr1)
120 {
121     real av, stddev;
122
123     /* Redetermine av and stddev from the DD box boundaries */
124     av     = box0 + 0.5*box_size;
125     stddev = 0.5*box_size/GRID_STDDEV_FAC;
126
127     *gr0 = av - NSGRID_STDDEV_FAC*stddev;
128     *gr1 = av + NSGRID_STDDEV_FAC*stddev;
129 }
130
131 void get_nsgrid_boundaries(int nboundeddim, matrix box,
132                            gmx_domdec_t *dd,
133                            gmx_ddbox_t *ddbox, rvec *gr0, rvec *gr1,
134                            int ncg, rvec *cgcm,
135                            rvec grid_x0, rvec grid_x1,
136                            real *grid_density)
137 {
138     rvec av, stddev;
139     real vol, bdens0, bdens1;
140     int  d;
141
142     if (nboundeddim < DIM)
143     {
144         calc_x_av_stddev(ncg, cgcm, av, stddev);
145     }
146
147     vol = 1;
148     for (d = 0; d < DIM; d++)
149     {
150         if (d < nboundeddim)
151         {
152             grid_x0[d] = (gr0 != nullptr ? (*gr0)[d] : 0);
153             grid_x1[d] = (gr1 != nullptr ? (*gr1)[d] : box[d][d]);
154             vol       *= (grid_x1[d] - grid_x0[d]);
155         }
156         else
157         {
158             if (ddbox == nullptr)
159             {
160                 get_nsgrid_boundaries_vac(av[d], stddev[d],
161                                           &grid_x0[d], &grid_x1[d],
162                                           &bdens0, &bdens1);
163             }
164             else
165             {
166                 /* Temporary fix which uses global ddbox boundaries
167                  * for unbounded dimensions.
168                  * Should be replaced by local boundaries, which makes
169                  * the ns grid smaller and does not require global comm.
170                  */
171                 dd_box_bounds_to_ns_bounds(ddbox->box0[d], ddbox->box_size[d],
172                                            &grid_x0[d], &grid_x1[d]);
173                 bdens0 = grid_x0[d];
174                 bdens1 = grid_x1[d];
175             }
176             /* Check for a DD cell not at a lower edge */
177             if (dd != nullptr && gr0 != nullptr && dd->ci[d] > 0)
178             {
179                 grid_x0[d] = (*gr0)[d];
180                 bdens0     = (*gr0)[d];
181             }
182             /* Check for a DD cell not at a higher edge */
183             if (dd != nullptr && gr1 != nullptr && dd->ci[d] < dd->nc[d]-1)
184             {
185                 grid_x1[d] = (*gr1)[d];
186                 bdens1     = (*gr1)[d];
187             }
188             vol *= (bdens1 - bdens0);
189         }
190
191         if (debug)
192         {
193             fprintf(debug, "Set grid boundaries dim %d: %f %f\n",
194                     d, grid_x0[d], grid_x1[d]);
195         }
196     }
197
198     *grid_density = ncg/vol;
199 }
200
201 static void set_grid_sizes(matrix box, rvec izones_x0, rvec izones_x1, real rlist,
202                            const gmx_domdec_t *dd, const gmx_ddbox_t *ddbox,
203                            t_grid *grid,
204                            real grid_density)
205 {
206     int      i, j;
207     gmx_bool bDD, bDDRect;
208     rvec     izones_size;
209     real     inv_r_ideal, size, add_tric, radd;
210
211     for (i = 0; (i < DIM); i++)
212     {
213         if (debug)
214         {
215             fprintf(debug,
216                     "set_grid_sizes, i-zone bounds for dim %d: %6.3f %6.3f\n",
217                     i, izones_x0[i], izones_x1[i]);
218         }
219         izones_size[i] = izones_x1[i] - izones_x0[i];
220     }
221
222     /* Use the ideal number of cg's per cell to set the ideal cell size */
223     inv_r_ideal = std::cbrt(grid_density/grid->ncg_ideal);
224     if (rlist > 0 && inv_r_ideal*rlist < 1)
225     {
226         inv_r_ideal = 1/rlist;
227     }
228     if (debug)
229     {
230         fprintf(debug, "CG density %f ideal ns cell size %f\n",
231                 grid_density, 1/inv_r_ideal);
232     }
233
234     clear_rvec(grid->cell_offset);
235     for (i = 0; (i < DIM); i++)
236     {
237         /* Initial settings, for DD might change below */
238         grid->cell_offset[i] = izones_x0[i];
239         size                 = izones_size[i];
240
241         bDD = dd && (dd->nc[i] > 1);
242         if (!bDD)
243         {
244             bDDRect = FALSE;
245         }
246         else
247         {
248             /* With DD grid cell jumps only the first decomposition
249              * direction has uniform DD cell boundaries.
250              */
251             bDDRect = !(ddbox->tric_dir[i] ||
252                         (dd_dlb_is_on(dd) && i != dd->dim[0]));
253
254             radd = rlist;
255             if (i >= ddbox->npbcdim &&
256                 (rlist == 0 ||
257                  izones_x1[i] + radd > ddbox->box0[i] + ddbox->box_size[i]))
258             {
259                 radd = ddbox->box0[i] + ddbox->box_size[i] - izones_x1[i];
260                 if (radd < 0)
261                 {
262                     radd = 0;
263                 }
264             }
265
266             /* With DD we only need a grid of one DD cell size + rlist */
267             if (bDDRect)
268             {
269                 size += radd;
270             }
271             else
272             {
273                 size += radd/ddbox->skew_fac[i];
274             }
275
276             /* Check if the cell boundary in this direction is
277              * perpendicular to the Cartesian axis.
278              * Since grid->npbcdim isan integer that in principle can take
279              * any value, we help the compiler avoid warnings and potentially
280              * optimize by ensuring that j < DIM here.
281              */
282             for (j = i+1; j < grid->npbcdim && j < DIM; j++)
283             {
284                 if (box[j][i] != 0)
285                 {
286                     /* Correct the offset for the home cell location */
287                     grid->cell_offset[i] += izones_x0[j]*box[j][i]/box[j][j];
288
289                     /* Correct the offset and size for the off-diagonal
290                      * displacement of opposing DD cell corners.
291                      */
292                     /* Without rouding we would need to add:
293                      * box[j][i]*rlist/(dd->skew_fac[i]*box[j][j])
294                      */
295                     /* Determine the shift for the corners of the triclinic box */
296                     add_tric = izones_size[j]*box[j][i]/box[j][j];
297                     if (dd->ndim == 1 && j == ZZ)
298                     {
299                         /* With 1D domain decomposition the cg's are not in
300                          * the triclinic box, but trilinic x-y and rectangular y-z.
301                          * Therefore we need to add the shift from the trilinic
302                          * corner to the corner at y=0.
303                          */
304                         add_tric += -box[YY][XX]*box[ZZ][YY]/box[YY][YY];
305                     }
306                     if (box[j][i] < 0)
307                     {
308                         grid->cell_offset[i] += add_tric;
309                         size                 -= add_tric;
310                     }
311                     else
312                     {
313                         size += add_tric;
314                     }
315                 }
316             }
317         }
318         if (!bDDRect)
319         {
320             /* No DD or the box is triclinic is this direction:
321              * we will use the normal grid ns that checks all cells
322              * that are within cut-off distance of the i-particle.
323              */
324             grid->n[i] = (int)(size*inv_r_ideal + 0.5);
325             if (grid->n[i] < 2)
326             {
327                 grid->n[i] = 2;
328             }
329             grid->cell_size[i] = size/grid->n[i];
330             grid->ncpddc[i]    = 0;
331         }
332         else
333         {
334             /* We use grid->ncpddc[i] such that all particles
335              * in one ns cell belong to a single DD cell only.
336              * We can then beforehand exclude certain ns grid cells
337              * for non-home i-particles.
338              */
339             grid->ncpddc[i] = (int)(izones_size[i]*inv_r_ideal + 0.5);
340             if (grid->ncpddc[i] < 2)
341             {
342                 grid->ncpddc[i] = 2;
343             }
344             grid->cell_size[i] = izones_size[i]/grid->ncpddc[i];
345             grid->n[i]         = grid->ncpddc[i] + (int)(radd/grid->cell_size[i]) + 1;
346         }
347         if (debug)
348         {
349             fprintf(debug, "grid dim %d size %d x %f: %f - %f\n",
350                     i, grid->n[i], grid->cell_size[i],
351                     grid->cell_offset[i],
352                     grid->cell_offset[i]+grid->n[i]*grid->cell_size[i]);
353         }
354     }
355
356     if (debug)
357     {
358         fprintf(debug, "CG ncg ideal %d, actual density %.1f\n",
359                 grid->ncg_ideal, grid_density*grid->cell_size[XX]*grid->cell_size[YY]*grid->cell_size[ZZ]);
360     }
361 }
362
363 t_grid *init_grid(FILE *fplog, t_forcerec *fr)
364 {
365     char   *ptr;
366     t_grid *grid;
367
368     snew(grid, 1);
369
370     grid->npbcdim = ePBC2npbcdim(fr->ePBC);
371
372     if (fr->ePBC == epbcXY && fr->nwall == 2)
373     {
374         grid->nboundeddim = 3;
375     }
376     else
377     {
378         grid->nboundeddim = grid->npbcdim;
379     }
380
381     if (debug)
382     {
383         fprintf(debug, "The coordinates are bounded in %d dimensions\n",
384                 grid->nboundeddim);
385     }
386
387     /* The ideal number of cg's per ns grid cell seems to be 10 */
388     grid->ncg_ideal = 10;
389     ptr             = getenv("GMX_NSCELL_NCG");
390     if (ptr)
391     {
392         sscanf(ptr, "%d", &grid->ncg_ideal);
393         if (fplog)
394         {
395             fprintf(fplog, "Set ncg_ideal to %d\n", grid->ncg_ideal);
396         }
397         if (grid->ncg_ideal <= 0)
398         {
399             gmx_fatal(FARGS, "The number of cg's per cell should be > 0");
400         }
401     }
402     if (debug)
403     {
404         fprintf(debug, "Set ncg_ideal to %d\n", grid->ncg_ideal);
405     }
406
407     return grid;
408 }
409
410 void done_grid(t_grid *grid)
411 {
412     if (grid == nullptr)
413     {
414         return;
415     }
416     grid->nr      = 0;
417     clear_ivec(grid->n);
418     grid->ncells  = 0;
419     sfree(grid->cell_index);
420     sfree(grid->a);
421     sfree(grid->index);
422     sfree(grid->nra);
423     grid->cells_nalloc = 0;
424     sfree(grid->dcx2);
425     sfree(grid->dcy2);
426     sfree(grid->dcz2);
427     grid->dc_nalloc = 0;
428
429     if (debug)
430     {
431         fprintf(debug, "Successfully freed memory for grid pointers.");
432     }
433     sfree(grid);
434 }
435
436 int xyz2ci_(int nry, int nrz, int x, int y, int z)
437 /* Return the cell index */
438 {
439     return (nry*nrz*x+nrz*y+z);
440 }
441
442 void ci2xyz(t_grid *grid, int i, int *x, int *y, int *z)
443 /* Return x,y and z from the cell index */
444 {
445     int ci;
446
447     range_check_mesg(i, 0, grid->nr, range_warn);
448
449     ci  = grid->cell_index[i];
450     *x  = ci / (grid->n[YY]*grid->n[ZZ]);
451     ci -= (*x)*grid->n[YY]*grid->n[ZZ];
452     *y  = ci / grid->n[ZZ];
453     ci -= (*y)*grid->n[ZZ];
454     *z  = ci;
455 }
456
457 static int ci_not_used(ivec n)
458 {
459     /* Return an improbable value */
460     return xyz2ci(n[YY], n[ZZ], 3*n[XX], 3*n[YY], 3*n[ZZ]);
461 }
462
463 static void set_grid_ncg(t_grid *grid, int ncg)
464 {
465     int nr_old, i;
466
467     grid->nr = ncg;
468     if (grid->nr+1 > grid->nr_alloc)
469     {
470         nr_old         = grid->nr_alloc;
471         grid->nr_alloc = over_alloc_dd(grid->nr) + 1;
472         srenew(grid->cell_index, grid->nr_alloc);
473         for (i = nr_old; i < grid->nr_alloc; i++)
474         {
475             grid->cell_index[i] = 0;
476         }
477         srenew(grid->a, grid->nr_alloc);
478     }
479 }
480
481 void grid_first(FILE *fplog, t_grid *grid,
482                 gmx_domdec_t *dd, const gmx_ddbox_t *ddbox,
483                 matrix box, rvec izones_x0, rvec izones_x1,
484                 real rlist, real grid_density)
485 {
486     int    i, m;
487
488     set_grid_sizes(box, izones_x0, izones_x1, rlist, dd, ddbox, grid, grid_density);
489
490     grid->ncells = grid->n[XX]*grid->n[YY]*grid->n[ZZ];
491
492     if (grid->ncells+1 > grid->cells_nalloc)
493     {
494         /* Allocate double the size so we have some headroom */
495         grid->cells_nalloc = 2*grid->ncells;
496         srenew(grid->nra,  grid->cells_nalloc+1);
497         srenew(grid->index, grid->cells_nalloc+1);
498
499         if (fplog)
500         {
501             fprintf(fplog, "Grid: %d x %d x %d cells\n",
502                     grid->n[XX], grid->n[YY], grid->n[ZZ]);
503         }
504     }
505
506     m = std::max(grid->n[XX], std::max(grid->n[YY], grid->n[ZZ]));
507     if (m > grid->dc_nalloc)
508     {
509         /* Allocate with double the initial size for box scaling */
510         grid->dc_nalloc = 2*m;
511         srenew(grid->dcx2, grid->dc_nalloc);
512         srenew(grid->dcy2, grid->dc_nalloc);
513         srenew(grid->dcz2, grid->dc_nalloc);
514     }
515
516     grid->nr = 0;
517     for (i = 0; (i < grid->ncells); i++)
518     {
519         grid->nra[i] = 0;
520     }
521 }
522
523 static void calc_bor(int cg0, int cg1, int ncg, int CG0[2], int CG1[2])
524 {
525     if (cg1 > ncg)
526     {
527         CG0[0] = cg0;
528         CG1[0] = ncg;
529         CG0[1] = 0;
530         CG1[1] = cg1-ncg;
531     }
532     else
533     {
534         CG0[0] = cg0;
535         CG1[0] = cg1;
536         CG0[1] = 0;
537         CG1[1] = 0;
538     }
539     if (debug)
540     {
541         int m;
542
543         fprintf(debug, "calc_bor: cg0=%d, cg1=%d, ncg=%d\n", cg0, cg1, ncg);
544         for (m = 0; (m < 2); m++)
545         {
546             fprintf(debug, "CG0[%d]=%d, CG1[%d]=%d\n", m, CG0[m], m, CG1[m]);
547         }
548     }
549
550 }
551
552 void calc_elemnr(t_grid *grid, int cg0, int cg1, int ncg)
553 {
554     int     CG0[2], CG1[2];
555     int    *cell_index = grid->cell_index;
556     int    *nra        = grid->nra;
557     int     i, m, ncells;
558     int     ci, not_used;
559
560     ncells = grid->ncells;
561     if (ncells <= 0)
562     {
563         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
564     }
565
566     not_used = ci_not_used(grid->n);
567
568     calc_bor(cg0, cg1, ncg, CG0, CG1);
569     for (m = 0; (m < 2); m++)
570     {
571         for (i = CG0[m]; (i < CG1[m]); i++)
572         {
573             ci = cell_index[i];
574             if (ci != not_used)
575             {
576                 range_check_mesg(ci, 0, ncells, range_warn);
577                 nra[ci]++;
578             }
579         }
580     }
581 }
582
583 void calc_ptrs(t_grid *grid)
584 {
585     int *index = grid->index;
586     int *nra   = grid->nra;
587     int  ix, iy, iz, ci, nr;
588     int  nnra, ncells;
589
590     ncells = grid->ncells;
591     if (ncells <= 0)
592     {
593         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
594     }
595
596     ci = nr = 0;
597     for (ix = 0; (ix < grid->n[XX]); ix++)
598     {
599         for (iy = 0; (iy < grid->n[YY]); iy++)
600         {
601             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
602             {
603                 range_check_mesg(ci, 0, ncells, range_warn);
604                 index[ci] = nr;
605                 nnra      = nra[ci];
606                 nr       += nnra;
607                 nra[ci]   = 0;
608             }
609         }
610     }
611 }
612
613 void grid_last(t_grid *grid, int cg0, int cg1, int ncg)
614 {
615     int     CG0[2], CG1[2];
616     int     i, m;
617     int     ci, not_used, ind, ncells;
618     int    *cell_index = grid->cell_index;
619     int    *nra        = grid->nra;
620     int    *index      = grid->index;
621     int    *a          = grid->a;
622
623     ncells = grid->ncells;
624     if (ncells <= 0)
625     {
626         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
627     }
628
629     not_used = ci_not_used(grid->n);
630
631     calc_bor(cg0, cg1, ncg, CG0, CG1);
632     for (m = 0; (m < 2); m++)
633     {
634         for (i = CG0[m]; (i < CG1[m]); i++)
635         {
636             ci     = cell_index[i];
637             if (ci != not_used)
638             {
639                 range_check_mesg(ci, 0, ncells, range_warn);
640                 ind    = index[ci]+nra[ci]++;
641                 range_check_mesg(ind, 0, grid->nr, range_warn);
642                 a[ind] = i;
643             }
644         }
645     }
646 }
647
648 void fill_grid(gmx_domdec_zones_t *dd_zones,
649                t_grid *grid, int ncg_tot,
650                int cg0, int cg1, rvec cg_cm[])
651 {
652     int       *cell_index;
653     int        nry, nrz;
654     rvec       n_box, offset;
655     int        zone, ccg0, ccg1, cg, d, not_used;
656     ivec       shift0, useall, b0, b1, ind;
657     gmx_bool   bUse;
658
659     if (cg0 == -1)
660     {
661         /* We have already filled the grid up to grid->ncg,
662          * continue from there.
663          */
664         cg0 = grid->nr;
665     }
666
667     set_grid_ncg(grid, ncg_tot);
668
669     cell_index = grid->cell_index;
670
671     /* Initiate cell borders */
672     nry = grid->n[YY];
673     nrz = grid->n[ZZ];
674     for (d = 0; d < DIM; d++)
675     {
676         if (grid->cell_size[d] > 0)
677         {
678             n_box[d] = 1/grid->cell_size[d];
679         }
680         else
681         {
682             n_box[d] = 0;
683         }
684     }
685     copy_rvec(grid->cell_offset, offset);
686
687     if (debug)
688     {
689         fprintf(debug, "Filling grid from %d to %d\n", cg0, cg1);
690     }
691
692     if (dd_zones == nullptr)
693     {
694         for (cg = cg0; cg < cg1; cg++)
695         {
696             for (d = 0; d < DIM; d++)
697             {
698                 ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d])*n_box[d]);
699                 /* With pbc we should be done here.
700                  * Without pbc cg's outside the grid
701                  * should be assigned to the closest grid cell.
702                  */
703                 if (ind[d] < 0)
704                 {
705                     ind[d] = 0;
706                 }
707                 else if (ind[d] >= grid->n[d])
708                 {
709                     ind[d] = grid->n[d] - 1;
710                 }
711             }
712             cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
713         }
714     }
715     else
716     {
717         for (zone = 0; zone < dd_zones->n; zone++)
718         {
719             ccg0 = dd_zones->cg_range[zone];
720             ccg1 = dd_zones->cg_range[zone+1];
721             if (ccg1 <= cg0 || ccg0 >= cg1)
722             {
723                 continue;
724             }
725
726             /* Determine the ns grid cell limits for this DD zone */
727             for (d = 0; d < DIM; d++)
728             {
729                 shift0[d] = dd_zones->shift[zone][d];
730                 useall[d] = (shift0[d] == 0 || d >= grid->npbcdim);
731                 /* Check if we need to do normal or optimized grid assignments.
732                  * Normal is required for dims without DD or triclinic dims.
733                  * DD edge cell on dims without pbc will be automatically
734                  * be correct, since the shift=0 zones with have b0 and b1
735                  * set to the grid boundaries and there are no shift=1 zones.
736                  */
737                 if (grid->ncpddc[d] == 0)
738                 {
739                     b0[d] = 0;
740                     b1[d] = grid->n[d];
741                 }
742                 else
743                 {
744                     if (shift0[d] == 0)
745                     {
746                         b0[d] = 0;
747                         b1[d] = grid->ncpddc[d];
748                     }
749                     else
750                     {
751                         /* shift = 1 */
752                         b0[d] = grid->ncpddc[d];
753                         b1[d] = grid->n[d];
754                     }
755                 }
756             }
757
758             not_used = ci_not_used(grid->n);
759
760             /* Put all the charge groups of this DD zone on the grid */
761             for (cg = ccg0; cg < ccg1; cg++)
762             {
763                 if (cell_index[cg] == -1)
764                 {
765                     /* This cg has moved to another node */
766                     cell_index[cg] = NSGRID_SIGNAL_MOVED_FAC*grid->ncells;
767                     continue;
768                 }
769
770                 bUse = TRUE;
771                 for (d = 0; d < DIM; d++)
772                 {
773                     ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d])*n_box[d]);
774                     /* Here we have to correct for rounding problems,
775                      * as this cg_cm to cell index operation is not necessarily
776                      * binary identical to the operation for the DD zone assignment
777                      * and therefore a cg could end up in an unused grid cell.
778                      * For dimensions without pbc we need to check
779                      * for cells on the edge if charge groups are beyond
780                      * the grid and if so, store them in the closest cell.
781                      */
782                     if (ind[d] < b0[d])
783                     {
784                         ind[d] = b0[d];
785                     }
786                     else if (ind[d] >= b1[d])
787                     {
788                         if (useall[d])
789                         {
790                             ind[d] = b1[d] - 1;
791                         }
792                         else
793                         {
794                             /* Charge groups in this DD zone further away than the cut-off
795                              * in direction do not participate in non-bonded interactions.
796                              */
797                             bUse = FALSE;
798                         }
799                     }
800                 }
801                 if (cg > grid->nr_alloc)
802                 {
803                     fprintf(stderr, "WARNING: nra_alloc %d cg0 %d cg1 %d cg %d\n",
804                             grid->nr_alloc, cg0, cg1, cg);
805                 }
806                 if (bUse)
807                 {
808                     cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
809                 }
810                 else
811                 {
812                     cell_index[cg] = not_used;
813                 }
814             }
815         }
816     }
817
818 }
819
820 void check_grid(t_grid *grid)
821 {
822     int ix, iy, iz, ci, cci, nra;
823
824     if (grid->ncells <= 0)
825     {
826         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
827     }
828
829     ci  = 0;
830     cci = 0;
831     for (ix = 0; (ix < grid->n[XX]); ix++)
832     {
833         for (iy = 0; (iy < grid->n[YY]); iy++)
834         {
835             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
836             {
837                 if (ci > 0)
838                 {
839                     nra = grid->index[ci]-grid->index[cci];
840                     if (nra != grid->nra[cci])
841                     {
842                         gmx_fatal(FARGS, "nra=%d, grid->nra=%d, cci=%d",
843                                   nra, grid->nra[cci], cci);
844                     }
845                 }
846                 cci = xyz2ci(grid->n[YY], grid->n[ZZ], ix, iy, iz);
847                 range_check_mesg(cci, 0, grid->ncells, range_warn);
848
849                 if (cci != ci)
850                 {
851                     gmx_fatal(FARGS, "ci = %d, cci = %d", ci, cci);
852                 }
853             }
854         }
855     }
856 }
857
858 void print_grid(FILE *log, t_grid *grid)
859 {
860     int i, nra, index;
861     int ix, iy, iz, ci;
862
863     fprintf(log, "nr:        %d\n", grid->nr);
864     fprintf(log, "nrx:       %d\n", grid->n[XX]);
865     fprintf(log, "nry:       %d\n", grid->n[YY]);
866     fprintf(log, "nrz:       %d\n", grid->n[ZZ]);
867     fprintf(log, "ncg_ideal: %d\n", grid->ncg_ideal);
868     fprintf(log, "    i  cell_index\n");
869     for (i = 0; (i < grid->nr); i++)
870     {
871         fprintf(log, "%5d  %5d\n", i, grid->cell_index[i]);
872     }
873     fprintf(log, "cells\n");
874     fprintf(log, " ix iy iz   nr  index  cgs...\n");
875     ci = 0;
876     for (ix = 0; (ix < grid->n[XX]); ix++)
877     {
878         for (iy = 0; (iy < grid->n[YY]); iy++)
879         {
880             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
881             {
882                 index = grid->index[ci];
883                 nra   = grid->nra[ci];
884                 fprintf(log, "%3d%3d%3d%5d%5d", ix, iy, iz, nra, index);
885                 for (i = 0; (i < nra); i++)
886                 {
887                     fprintf(log, "%5d", grid->a[index+i]);
888                 }
889                 fprintf(log, "\n");
890             }
891         }
892     }
893     fflush(log);
894 }