db14315e70b945f2d25470d01f10efc57e7ada22
[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,2019, 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/dlb.h"
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 static 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, real* bound0, real* bound1, real* bdens0, real* bdens1)
101 {
102     /* Set the grid to 2 times the standard deviation of
103      * the charge group centers in both directions.
104      * For a uniform bounded distribution the width is sqrt(3)*stddev,
105      * so all charge groups fall within the width.
106      * For a sphere stddev is r/sqrt(5): 99.2% falls within the width.
107      * For a Gaussian distribution 98% fall within the width.
108      */
109     *bound0 = av - NSGRID_STDDEV_FAC * stddev;
110     *bound1 = av + NSGRID_STDDEV_FAC * stddev;
111
112     *bdens0 = av - GRID_STDDEV_FAC * stddev;
113     *bdens1 = av + GRID_STDDEV_FAC * stddev;
114 }
115
116 static void dd_box_bounds_to_ns_bounds(real box0, real box_size, real* gr0, real* gr1)
117 {
118     real av, stddev;
119
120     /* Redetermine av and stddev from the DD box boundaries */
121     av     = box0 + 0.5 * box_size;
122     stddev = 0.5 * box_size / GRID_STDDEV_FAC;
123
124     *gr0 = av - NSGRID_STDDEV_FAC * stddev;
125     *gr1 = av + NSGRID_STDDEV_FAC * stddev;
126 }
127
128 void get_nsgrid_boundaries(int           nboundeddim,
129                            matrix        box,
130                            gmx_domdec_t* dd,
131                            gmx_ddbox_t*  ddbox,
132                            rvec*         gr0,
133                            rvec*         gr1,
134                            int           ncg,
135                            rvec*         cgcm,
136                            rvec          grid_x0,
137                            rvec          grid_x1,
138                            real*         grid_density)
139 {
140     rvec av, stddev;
141     real vol, bdens0, bdens1;
142     int  d;
143
144     if (nboundeddim < DIM)
145     {
146         calc_x_av_stddev(ncg, cgcm, av, stddev);
147     }
148
149     vol = 1;
150     for (d = 0; d < DIM; d++)
151     {
152         if (d < nboundeddim)
153         {
154             grid_x0[d] = (gr0 != nullptr ? (*gr0)[d] : 0);
155             grid_x1[d] = (gr1 != nullptr ? (*gr1)[d] : box[d][d]);
156             vol *= (grid_x1[d] - grid_x0[d]);
157         }
158         else
159         {
160             if (ddbox == nullptr)
161             {
162                 get_nsgrid_boundaries_vac(av[d], stddev[d], &grid_x0[d], &grid_x1[d], &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], &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", d, grid_x0[d], grid_x1[d]);
193         }
194     }
195
196     *grid_density = ncg / vol;
197 }
198
199 static void set_grid_sizes(matrix              box,
200                            rvec                izones_x0,
201                            rvec                izones_x1,
202                            real                rlist,
203                            const gmx_domdec_t* dd,
204                            const gmx_ddbox_t*  ddbox,
205                            t_grid*             grid,
206                            real                grid_density)
207 {
208     int      i, j;
209     gmx_bool bDD, bDDRect;
210     rvec     izones_size;
211     real     inv_r_ideal, size, add_tric, radd;
212
213     for (i = 0; (i < DIM); i++)
214     {
215         if (debug)
216         {
217             fprintf(debug, "set_grid_sizes, i-zone bounds for dim %d: %6.3f %6.3f\n", i,
218                     izones_x0[i], izones_x1[i]);
219         }
220         izones_size[i] = izones_x1[i] - izones_x0[i];
221     }
222
223     /* Use the ideal number of cg's per cell to set the ideal cell size */
224     inv_r_ideal = std::cbrt(grid_density / grid->ncg_ideal);
225     if (rlist > 0 && inv_r_ideal * rlist < 1)
226     {
227         inv_r_ideal = 1 / rlist;
228     }
229     if (debug)
230     {
231         fprintf(debug, "CG density %f ideal ns cell size %f\n", 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 != nullptr) && (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] != 0) || (dd_dlb_is_on(dd) && i != dd->dim[0]));
252
253             radd = rlist;
254             if (i >= ddbox->npbcdim
255                 && (rlist == 0 || izones_x1[i] + radd > ddbox->box0[i] + ddbox->box_size[i]))
256             {
257                 radd = ddbox->box0[i] + ddbox->box_size[i] - izones_x1[i];
258                 if (radd < 0)
259                 {
260                     radd = 0;
261                 }
262             }
263
264             /* With DD we only need a grid of one DD cell size + rlist */
265             if (bDDRect)
266             {
267                 size += radd;
268             }
269             else
270             {
271                 size += radd / ddbox->skew_fac[i];
272             }
273
274             /* Check if the cell boundary in this direction is
275              * perpendicular to the Cartesian axis.
276              * Since grid->npbcdim isan integer that in principle can take
277              * any value, we help the compiler avoid warnings and potentially
278              * optimize by ensuring that j < DIM here.
279              */
280             for (j = i + 1; j < grid->npbcdim && j < DIM; j++)
281             {
282                 if (box[j][i] != 0)
283                 {
284                     /* Correct the offset for the home cell location */
285                     grid->cell_offset[i] += izones_x0[j] * box[j][i] / box[j][j];
286
287                     /* Correct the offset and size for the off-diagonal
288                      * displacement of opposing DD cell corners.
289                      */
290                     /* Without rouding we would need to add:
291                      * box[j][i]*rlist/(dd->skew_fac[i]*box[j][j])
292                      */
293                     /* Determine the shift for the corners of the triclinic box */
294                     add_tric = izones_size[j] * box[j][i] / box[j][j];
295                     if (dd->ndim == 1 && j == ZZ)
296                     {
297                         /* With 1D domain decomposition the cg's are not in
298                          * the triclinic box, but trilinic x-y and rectangular y-z.
299                          * Therefore we need to add the shift from the trilinic
300                          * corner to the corner at y=0.
301                          */
302                         add_tric += -box[YY][XX] * box[ZZ][YY] / box[YY][YY];
303                     }
304                     if (box[j][i] < 0)
305                     {
306                         grid->cell_offset[i] += add_tric;
307                         size -= add_tric;
308                     }
309                     else
310                     {
311                         size += add_tric;
312                     }
313                 }
314             }
315         }
316         if (!bDDRect)
317         {
318             /* No DD or the box is triclinic is this direction:
319              * we will use the normal grid ns that checks all cells
320              * that are within cut-off distance of the i-particle.
321              */
322             grid->n[i] = gmx::roundToInt(size * inv_r_ideal);
323             if (grid->n[i] < 2)
324             {
325                 grid->n[i] = 2;
326             }
327             grid->cell_size[i] = size / grid->n[i];
328             grid->ncpddc[i]    = 0;
329         }
330         else
331         {
332             /* We use grid->ncpddc[i] such that all particles
333              * in one ns cell belong to a single DD cell only.
334              * We can then beforehand exclude certain ns grid cells
335              * for non-home i-particles.
336              */
337             grid->ncpddc[i] = gmx::roundToInt(izones_size[i] * inv_r_ideal);
338             if (grid->ncpddc[i] < 2)
339             {
340                 grid->ncpddc[i] = 2;
341             }
342             grid->cell_size[i] = izones_size[i] / grid->ncpddc[i];
343             grid->n[i]         = grid->ncpddc[i] + static_cast<int>(radd / grid->cell_size[i]) + 1;
344         }
345         if (debug)
346         {
347             fprintf(debug, "grid dim %d size %d x %f: %f - %f\n", i, grid->n[i], grid->cell_size[i],
348                     grid->cell_offset[i], grid->cell_offset[i] + grid->n[i] * grid->cell_size[i]);
349         }
350     }
351
352     if (debug)
353     {
354         fprintf(debug, "CG ncg ideal %d, actual density %.1f\n", grid->ncg_ideal,
355                 grid_density * grid->cell_size[XX] * grid->cell_size[YY] * grid->cell_size[ZZ]);
356     }
357 }
358
359 t_grid* init_grid(FILE* fplog, t_forcerec* fr)
360 {
361     char*   ptr;
362     t_grid* grid;
363
364     snew(grid, 1);
365
366     grid->npbcdim = ePBC2npbcdim(fr->ePBC);
367
368     if (fr->ePBC == epbcXY && fr->nwall == 2)
369     {
370         grid->nboundeddim = 3;
371     }
372     else
373     {
374         grid->nboundeddim = grid->npbcdim;
375     }
376
377     if (debug)
378     {
379         fprintf(debug, "The coordinates are bounded in %d dimensions\n", grid->nboundeddim);
380     }
381
382     /* The ideal number of cg's per ns grid cell seems to be 10 */
383     grid->ncg_ideal = 10;
384     ptr             = getenv("GMX_NSCELL_NCG");
385     if (ptr)
386     {
387         sscanf(ptr, "%d", &grid->ncg_ideal);
388         if (fplog)
389         {
390             fprintf(fplog, "Set ncg_ideal to %d\n", grid->ncg_ideal);
391         }
392         if (grid->ncg_ideal <= 0)
393         {
394             gmx_fatal(FARGS, "The number of cg's per cell should be > 0");
395         }
396     }
397     if (debug)
398     {
399         fprintf(debug, "Set ncg_ideal to %d\n", grid->ncg_ideal);
400     }
401
402     return grid;
403 }
404
405 void done_grid(t_grid* grid)
406 {
407     if (grid == nullptr)
408     {
409         return;
410     }
411     grid->nr = 0;
412     clear_ivec(grid->n);
413     grid->ncells = 0;
414     sfree(grid->cell_index);
415     sfree(grid->a);
416     sfree(grid->index);
417     sfree(grid->nra);
418     grid->cells_nalloc = 0;
419     sfree(grid->dcx2);
420     sfree(grid->dcy2);
421     sfree(grid->dcz2);
422     grid->dc_nalloc = 0;
423
424     if (debug)
425     {
426         fprintf(debug, "Successfully freed memory for grid pointers.");
427     }
428     sfree(grid);
429 }
430
431 int xyz2ci_(int nry, int nrz, int x, int y, int z)
432 /* Return the cell index */
433 {
434     return (nry * nrz * x + nrz * y + z);
435 }
436
437 void ci2xyz(t_grid* grid, int i, int* x, int* y, int* z)
438 /* Return x,y and z from the cell index */
439 {
440     int ci;
441
442     range_check_mesg(i, 0, grid->nr, range_warn);
443
444     ci = grid->cell_index[i];
445     *x = ci / (grid->n[YY] * grid->n[ZZ]);
446     ci -= (*x) * grid->n[YY] * grid->n[ZZ];
447     *y = ci / grid->n[ZZ];
448     ci -= (*y) * grid->n[ZZ];
449     *z = ci;
450 }
451
452 static int ci_not_used(const ivec n)
453 {
454     /* Return an improbable value */
455     return xyz2ci(n[YY], n[ZZ], 3 * n[XX], 3 * n[YY], 3 * n[ZZ]);
456 }
457
458 static void set_grid_ncg(t_grid* grid, int ncg)
459 {
460     int nr_old, i;
461
462     grid->nr = ncg;
463     if (grid->nr + 1 > grid->nr_alloc)
464     {
465         nr_old         = grid->nr_alloc;
466         grid->nr_alloc = over_alloc_dd(grid->nr) + 1;
467         srenew(grid->cell_index, grid->nr_alloc);
468         for (i = nr_old; i < grid->nr_alloc; i++)
469         {
470             grid->cell_index[i] = 0;
471         }
472         srenew(grid->a, grid->nr_alloc);
473     }
474 }
475
476 void grid_first(FILE*              fplog,
477                 t_grid*            grid,
478                 gmx_domdec_t*      dd,
479                 const gmx_ddbox_t* ddbox,
480                 matrix             box,
481                 rvec               izones_x0,
482                 rvec               izones_x1,
483                 real               rlist,
484                 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", 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 void calc_elemnr(t_grid* grid, int cg0, int cg1, int ncg)
551 {
552     int  CG0[2], CG1[2];
553     int* cell_index = grid->cell_index;
554     int* nra        = grid->nra;
555     int  i, m, ncells;
556     int  ci, not_used;
557
558     ncells = grid->ncells;
559     if (ncells <= 0)
560     {
561         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
562     }
563
564     not_used = ci_not_used(grid->n);
565
566     calc_bor(cg0, cg1, ncg, CG0, CG1);
567     for (m = 0; (m < 2); m++)
568     {
569         for (i = CG0[m]; (i < CG1[m]); i++)
570         {
571             ci = cell_index[i];
572             if (ci != not_used)
573             {
574                 range_check_mesg(ci, 0, ncells, range_warn);
575                 nra[ci]++;
576             }
577         }
578     }
579 }
580
581 void calc_ptrs(t_grid* grid)
582 {
583     int* index = grid->index;
584     int* nra   = grid->nra;
585     int  ix, iy, iz, ci, nr;
586     int  nnra, ncells;
587
588     ncells = grid->ncells;
589     if (ncells <= 0)
590     {
591         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
592     }
593
594     ci = nr = 0;
595     for (ix = 0; (ix < grid->n[XX]); ix++)
596     {
597         for (iy = 0; (iy < grid->n[YY]); iy++)
598         {
599             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
600             {
601                 range_check_mesg(ci, 0, ncells, range_warn);
602                 index[ci] = nr;
603                 nnra      = nra[ci];
604                 nr += nnra;
605                 nra[ci] = 0;
606             }
607         }
608     }
609 }
610
611 void grid_last(t_grid* grid, int cg0, int cg1, int ncg)
612 {
613     int  CG0[2], CG1[2];
614     int  i, m;
615     int  ci, not_used, ind, ncells;
616     int* cell_index = grid->cell_index;
617     int* nra        = grid->nra;
618     int* index      = grid->index;
619     int* a          = grid->a;
620
621     ncells = grid->ncells;
622     if (ncells <= 0)
623     {
624         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
625     }
626
627     not_used = ci_not_used(grid->n);
628
629     calc_bor(cg0, cg1, ncg, CG0, CG1);
630     for (m = 0; (m < 2); m++)
631     {
632         for (i = CG0[m]; (i < CG1[m]); i++)
633         {
634             ci = cell_index[i];
635             if (ci != not_used)
636             {
637                 range_check_mesg(ci, 0, ncells, range_warn);
638                 ind = index[ci] + nra[ci]++;
639                 range_check_mesg(ind, 0, grid->nr, range_warn);
640                 a[ind] = i;
641             }
642         }
643     }
644 }
645
646 void fill_grid(gmx_domdec_zones_t* dd_zones, t_grid* grid, int ncg_tot, int cg0, int cg1, rvec cg_cm[])
647 {
648     int*     cell_index;
649     int      nry, nrz;
650     rvec     n_box, offset;
651     int      zone, ccg0, ccg1, cg, d, not_used;
652     ivec     shift0, useall, b0, b1, ind;
653     gmx_bool bUse;
654
655     if (cg0 == -1)
656     {
657         /* We have already filled the grid up to grid->ncg,
658          * continue from there.
659          */
660         cg0 = grid->nr;
661     }
662
663     set_grid_ncg(grid, ncg_tot);
664
665     cell_index = grid->cell_index;
666
667     /* Initiate cell borders */
668     nry = grid->n[YY];
669     nrz = grid->n[ZZ];
670     for (d = 0; d < DIM; d++)
671     {
672         if (grid->cell_size[d] > 0)
673         {
674             n_box[d] = 1 / grid->cell_size[d];
675         }
676         else
677         {
678             n_box[d] = 0;
679         }
680     }
681     copy_rvec(grid->cell_offset, offset);
682
683     if (debug)
684     {
685         fprintf(debug, "Filling grid from %d to %d\n", cg0, cg1);
686     }
687
688     if (dd_zones == nullptr)
689     {
690         for (cg = cg0; cg < cg1; cg++)
691         {
692             for (d = 0; d < DIM; d++)
693             {
694                 ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d]) * n_box[d]);
695                 /* With pbc we should be done here.
696                  * Without pbc cg's outside the grid
697                  * should be assigned to the closest grid cell.
698                  */
699                 if (ind[d] < 0)
700                 {
701                     ind[d] = 0;
702                 }
703                 else if (ind[d] >= grid->n[d])
704                 {
705                     ind[d] = grid->n[d] - 1;
706                 }
707             }
708             cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
709         }
710     }
711     else
712     {
713         for (zone = 0; zone < dd_zones->n; zone++)
714         {
715             ccg0 = dd_zones->cg_range[zone];
716             ccg1 = dd_zones->cg_range[zone + 1];
717             if (ccg1 <= cg0 || ccg0 >= cg1)
718             {
719                 continue;
720             }
721
722             /* Determine the ns grid cell limits for this DD zone */
723             for (d = 0; d < DIM; d++)
724             {
725                 shift0[d] = dd_zones->shift[zone][d];
726                 useall[d] = static_cast<int>(shift0[d] == 0 || d >= grid->npbcdim);
727                 /* Check if we need to do normal or optimized grid assignments.
728                  * Normal is required for dims without DD or triclinic dims.
729                  * DD edge cell on dims without pbc will be automatically
730                  * be correct, since the shift=0 zones with have b0 and b1
731                  * set to the grid boundaries and there are no shift=1 zones.
732                  */
733                 if (grid->ncpddc[d] == 0)
734                 {
735                     b0[d] = 0;
736                     b1[d] = grid->n[d];
737                 }
738                 else
739                 {
740                     if (shift0[d] == 0)
741                     {
742                         b0[d] = 0;
743                         b1[d] = grid->ncpddc[d];
744                     }
745                     else
746                     {
747                         /* shift = 1 */
748                         b0[d] = grid->ncpddc[d];
749                         b1[d] = grid->n[d];
750                     }
751                 }
752             }
753
754             not_used = ci_not_used(grid->n);
755
756             /* Put all the charge groups of this DD zone on the grid */
757             for (cg = ccg0; cg < ccg1; cg++)
758             {
759                 if (cell_index[cg] == -1)
760                 {
761                     /* This cg has moved to another node */
762                     cell_index[cg] = NSGRID_SIGNAL_MOVED_FAC * grid->ncells;
763                     continue;
764                 }
765
766                 bUse = TRUE;
767                 for (d = 0; d < DIM; d++)
768                 {
769                     ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d]) * n_box[d]);
770                     /* Here we have to correct for rounding problems,
771                      * as this cg_cm to cell index operation is not necessarily
772                      * binary identical to the operation for the DD zone assignment
773                      * and therefore a cg could end up in an unused grid cell.
774                      * For dimensions without pbc we need to check
775                      * for cells on the edge if charge groups are beyond
776                      * the grid and if so, store them in the closest cell.
777                      */
778                     if (ind[d] < b0[d])
779                     {
780                         ind[d] = b0[d];
781                     }
782                     else if (ind[d] >= b1[d])
783                     {
784                         if (useall[d])
785                         {
786                             ind[d] = b1[d] - 1;
787                         }
788                         else
789                         {
790                             /* Charge groups in this DD zone further away than the cut-off
791                              * in direction do not participate in non-bonded interactions.
792                              */
793                             bUse = FALSE;
794                         }
795                     }
796                 }
797                 if (cg > grid->nr_alloc)
798                 {
799                     fprintf(stderr, "WARNING: nra_alloc %d cg0 %d cg1 %d cg %d\n", grid->nr_alloc,
800                             cg0, cg1, cg);
801                 }
802                 if (bUse)
803                 {
804                     cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
805                 }
806                 else
807                 {
808                     cell_index[cg] = not_used;
809                 }
810             }
811         }
812     }
813 }
814
815 void check_grid(t_grid* grid)
816 {
817     int ix, iy, iz, ci, cci, nra;
818
819     if (grid->ncells <= 0)
820     {
821         gmx_fatal(FARGS, "Number of grid cells is zero. Probably the system and box collapsed.\n");
822     }
823
824     ci  = 0;
825     cci = 0;
826     for (ix = 0; (ix < grid->n[XX]); ix++)
827     {
828         for (iy = 0; (iy < grid->n[YY]); iy++)
829         {
830             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
831             {
832                 if (ci > 0)
833                 {
834                     nra = grid->index[ci] - grid->index[cci];
835                     if (nra != grid->nra[cci])
836                     {
837                         gmx_fatal(FARGS, "nra=%d, grid->nra=%d, cci=%d", nra, grid->nra[cci], cci);
838                     }
839                 }
840                 cci = xyz2ci(grid->n[YY], grid->n[ZZ], ix, iy, iz);
841                 range_check_mesg(cci, 0, grid->ncells, range_warn);
842
843                 if (cci != ci)
844                 {
845                     gmx_fatal(FARGS, "ci = %d, cci = %d", ci, cci);
846                 }
847             }
848         }
849     }
850 }
851
852 void print_grid(FILE* log, t_grid* grid)
853 {
854     int i, nra, index;
855     int ix, iy, iz, ci;
856
857     fprintf(log, "nr:        %d\n", grid->nr);
858     fprintf(log, "nrx:       %d\n", grid->n[XX]);
859     fprintf(log, "nry:       %d\n", grid->n[YY]);
860     fprintf(log, "nrz:       %d\n", grid->n[ZZ]);
861     fprintf(log, "ncg_ideal: %d\n", grid->ncg_ideal);
862     fprintf(log, "    i  cell_index\n");
863     for (i = 0; (i < grid->nr); i++)
864     {
865         fprintf(log, "%5d  %5d\n", i, grid->cell_index[i]);
866     }
867     fprintf(log, "cells\n");
868     fprintf(log, " ix iy iz   nr  index  cgs...\n");
869     ci = 0;
870     for (ix = 0; (ix < grid->n[XX]); ix++)
871     {
872         for (iy = 0; (iy < grid->n[YY]); iy++)
873         {
874             for (iz = 0; (iz < grid->n[ZZ]); iz++, ci++)
875             {
876                 index = grid->index[ci];
877                 nra   = grid->nra[ci];
878                 fprintf(log, "%3d%3d%3d%5d%5d", ix, iy, iz, nra, index);
879                 for (i = 0; (i < nra); i++)
880                 {
881                     fprintf(log, "%5d", grid->a[index + i]);
882                 }
883                 fprintf(log, "\n");
884             }
885         }
886     }
887     fflush(log);
888 }