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