Move more timing routines into timing/.
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_search.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  *
4  *                This source code is part of
5  *
6  *                 G   R   O   M   A   C   S
7  *
8  *          GROningen MAchine for Chemical Simulations
9  *
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2012, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  *
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <math.h>
38 #include <string.h>
39 #include "sysstuff.h"
40 #include "smalloc.h"
41 #include "macros.h"
42 #include "maths.h"
43 #include "vec.h"
44 #include "pbc.h"
45 #include "nbnxn_consts.h"
46 /* nbnxn_internal.h included gmx_simd_macros.h */
47 #include "nbnxn_internal.h"
48 #ifdef GMX_NBNXN_SIMD
49 #include "gmx_simd_vec.h"
50 #endif
51 #include "nbnxn_atomdata.h"
52 #include "nbnxn_search.h"
53 #include "gmx_omp_nthreads.h"
54 #include "nrnb.h"
55
56 #include "gromacs/fileio/gmxfio.h"
57
58 #ifdef NBNXN_SEARCH_BB_SIMD4
59 /* We use 4-wide SIMD for bounding box calculations */
60
61 #ifndef GMX_DOUBLE
62 /* Single precision BBs + coordinates, we can also load coordinates with SIMD */
63 #define NBNXN_SEARCH_SIMD4_FLOAT_X_BB
64 #endif
65
66 #if defined NBNXN_SEARCH_SIMD4_FLOAT_X_BB && (GPU_NSUBCELL == 4 || GPU_NSUBCELL == 8)
67 /* Store bounding boxes with x, y and z coordinates in packs of 4 */
68 #define NBNXN_PBB_SIMD4
69 #endif
70
71 /* The packed bounding box coordinate stride is always set to 4.
72  * With AVX we could use 8, but that turns out not to be faster.
73  */
74 #define STRIDE_PBB        4
75 #define STRIDE_PBB_2LOG   2
76
77 #endif /* NBNXN_SEARCH_BB_SIMD4 */
78
79 #ifdef GMX_NBNXN_SIMD
80
81 /* The functions below are macros as they are performance sensitive */
82
83 /* 4x4 list, pack=4: no complex conversion required */
84 /* i-cluster to j-cluster conversion */
85 #define CI_TO_CJ_J4(ci)   (ci)
86 /* cluster index to coordinate array index conversion */
87 #define X_IND_CI_J4(ci)  ((ci)*STRIDE_P4)
88 #define X_IND_CJ_J4(cj)  ((cj)*STRIDE_P4)
89
90 /* 4x2 list, pack=4: j-cluster size is half the packing width */
91 /* i-cluster to j-cluster conversion */
92 #define CI_TO_CJ_J2(ci)  ((ci)<<1)
93 /* cluster index to coordinate array index conversion */
94 #define X_IND_CI_J2(ci)  ((ci)*STRIDE_P4)
95 #define X_IND_CJ_J2(cj)  (((cj)>>1)*STRIDE_P4 + ((cj) & 1)*(PACK_X4>>1))
96
97 /* 4x8 list, pack=8: i-cluster size is half the packing width */
98 /* i-cluster to j-cluster conversion */
99 #define CI_TO_CJ_J8(ci)  ((ci)>>1)
100 /* cluster index to coordinate array index conversion */
101 #define X_IND_CI_J8(ci)  (((ci)>>1)*STRIDE_P8 + ((ci) & 1)*(PACK_X8>>1))
102 #define X_IND_CJ_J8(cj)  ((cj)*STRIDE_P8)
103
104 /* The j-cluster size is matched to the SIMD width */
105 #if GMX_SIMD_WIDTH_HERE == 2
106 #define CI_TO_CJ_SIMD_4XN(ci)  CI_TO_CJ_J2(ci)
107 #define X_IND_CI_SIMD_4XN(ci)  X_IND_CI_J2(ci)
108 #define X_IND_CJ_SIMD_4XN(cj)  X_IND_CJ_J2(cj)
109 #else
110 #if GMX_SIMD_WIDTH_HERE == 4
111 #define CI_TO_CJ_SIMD_4XN(ci)  CI_TO_CJ_J4(ci)
112 #define X_IND_CI_SIMD_4XN(ci)  X_IND_CI_J4(ci)
113 #define X_IND_CJ_SIMD_4XN(cj)  X_IND_CJ_J4(cj)
114 #else
115 #if GMX_SIMD_WIDTH_HERE == 8
116 #define CI_TO_CJ_SIMD_4XN(ci)  CI_TO_CJ_J8(ci)
117 #define X_IND_CI_SIMD_4XN(ci)  X_IND_CI_J8(ci)
118 #define X_IND_CJ_SIMD_4XN(cj)  X_IND_CJ_J8(cj)
119 /* Half SIMD with j-cluster size */
120 #define CI_TO_CJ_SIMD_2XNN(ci) CI_TO_CJ_J4(ci)
121 #define X_IND_CI_SIMD_2XNN(ci) X_IND_CI_J4(ci)
122 #define X_IND_CJ_SIMD_2XNN(cj) X_IND_CJ_J4(cj)
123 #else
124 #if GMX_SIMD_WIDTH_HERE == 16
125 #define CI_TO_CJ_SIMD_2XNN(ci) CI_TO_CJ_J8(ci)
126 #define X_IND_CI_SIMD_2XNN(ci) X_IND_CI_J8(ci)
127 #define X_IND_CJ_SIMD_2XNN(cj) X_IND_CJ_J8(cj)
128 #else
129 #error "unsupported GMX_NBNXN_SIMD_WIDTH"
130 #endif
131 #endif
132 #endif
133 #endif
134
135 #endif /* GMX_NBNXN_SIMD */
136
137
138 #ifdef NBNXN_SEARCH_BB_SIMD4
139 /* Store bounding boxes corners as quadruplets: xxxxyyyyzzzz */
140 #define NBNXN_BBXXXX
141 /* Size of bounding box corners quadruplet */
142 #define NNBSBB_XXXX      (NNBSBB_D*DIM*STRIDE_PBB)
143 #endif
144
145 /* We shift the i-particles backward for PBC.
146  * This leads to more conditionals than shifting forward.
147  * We do this to get more balanced pair lists.
148  */
149 #define NBNXN_SHIFT_BACKWARD
150
151
152 /* This define is a lazy way to avoid interdependence of the grid
153  * and searching data structures.
154  */
155 #define NBNXN_NA_SC_MAX (GPU_NSUBCELL*NBNXN_GPU_CLUSTER_SIZE)
156
157
158 static void nbs_cycle_clear(nbnxn_cycle_t *cc)
159 {
160     int i;
161
162     for (i = 0; i < enbsCCnr; i++)
163     {
164         cc[i].count = 0;
165         cc[i].c     = 0;
166     }
167 }
168
169 static double Mcyc_av(const nbnxn_cycle_t *cc)
170 {
171     return (double)cc->c*1e-6/cc->count;
172 }
173
174 static void nbs_cycle_print(FILE *fp, const nbnxn_search_t nbs)
175 {
176     int n;
177     int t;
178
179     fprintf(fp, "\n");
180     fprintf(fp, "ns %4d grid %4.1f search %4.1f red.f %5.3f",
181             nbs->cc[enbsCCgrid].count,
182             Mcyc_av(&nbs->cc[enbsCCgrid]),
183             Mcyc_av(&nbs->cc[enbsCCsearch]),
184             Mcyc_av(&nbs->cc[enbsCCreducef]));
185
186     if (nbs->nthread_max > 1)
187     {
188         if (nbs->cc[enbsCCcombine].count > 0)
189         {
190             fprintf(fp, " comb %5.2f",
191                     Mcyc_av(&nbs->cc[enbsCCcombine]));
192         }
193         fprintf(fp, " s. th");
194         for (t = 0; t < nbs->nthread_max; t++)
195         {
196             fprintf(fp, " %4.1f",
197                     Mcyc_av(&nbs->work[t].cc[enbsCCsearch]));
198         }
199     }
200     fprintf(fp, "\n");
201 }
202
203 static void nbnxn_grid_init(nbnxn_grid_t * grid)
204 {
205     grid->cxy_na      = NULL;
206     grid->cxy_ind     = NULL;
207     grid->cxy_nalloc  = 0;
208     grid->bb          = NULL;
209     grid->bbj         = NULL;
210     grid->nc_nalloc   = 0;
211 }
212
213 static int get_2log(int n)
214 {
215     int log2;
216
217     log2 = 0;
218     while ((1<<log2) < n)
219     {
220         log2++;
221     }
222     if ((1<<log2) != n)
223     {
224         gmx_fatal(FARGS, "nbnxn na_c (%d) is not a power of 2", n);
225     }
226
227     return log2;
228 }
229
230 static int nbnxn_kernel_to_ci_size(int nb_kernel_type)
231 {
232     switch (nb_kernel_type)
233     {
234         case nbnxnk4x4_PlainC:
235         case nbnxnk4xN_SIMD_4xN:
236         case nbnxnk4xN_SIMD_2xNN:
237             return NBNXN_CPU_CLUSTER_I_SIZE;
238         case nbnxnk8x8x8_CUDA:
239         case nbnxnk8x8x8_PlainC:
240             /* The cluster size for super/sub lists is only set here.
241              * Any value should work for the pair-search and atomdata code.
242              * The kernels, of course, might require a particular value.
243              */
244             return NBNXN_GPU_CLUSTER_SIZE;
245         default:
246             gmx_incons("unknown kernel type");
247     }
248
249     return 0;
250 }
251
252 int nbnxn_kernel_to_cj_size(int nb_kernel_type)
253 {
254     int nbnxn_simd_width = 0;
255     int cj_size          = 0;
256
257 #ifdef GMX_NBNXN_SIMD
258     nbnxn_simd_width = GMX_SIMD_WIDTH_HERE;
259 #endif
260
261     switch (nb_kernel_type)
262     {
263         case nbnxnk4x4_PlainC:
264             cj_size = NBNXN_CPU_CLUSTER_I_SIZE;
265             break;
266         case nbnxnk4xN_SIMD_4xN:
267             cj_size = nbnxn_simd_width;
268             break;
269         case nbnxnk4xN_SIMD_2xNN:
270             cj_size = nbnxn_simd_width/2;
271             break;
272         case nbnxnk8x8x8_CUDA:
273         case nbnxnk8x8x8_PlainC:
274             cj_size = nbnxn_kernel_to_ci_size(nb_kernel_type);
275             break;
276         default:
277             gmx_incons("unknown kernel type");
278     }
279
280     return cj_size;
281 }
282
283 static int ci_to_cj(int na_cj_2log, int ci)
284 {
285     switch (na_cj_2log)
286     {
287         case 2: return ci;     break;
288         case 1: return (ci<<1); break;
289         case 3: return (ci>>1); break;
290     }
291
292     return 0;
293 }
294
295 gmx_bool nbnxn_kernel_pairlist_simple(int nb_kernel_type)
296 {
297     if (nb_kernel_type == nbnxnkNotSet)
298     {
299         gmx_fatal(FARGS, "Non-bonded kernel type not set for Verlet-style pair-list.");
300     }
301
302     switch (nb_kernel_type)
303     {
304         case nbnxnk8x8x8_CUDA:
305         case nbnxnk8x8x8_PlainC:
306             return FALSE;
307
308         case nbnxnk4x4_PlainC:
309         case nbnxnk4xN_SIMD_4xN:
310         case nbnxnk4xN_SIMD_2xNN:
311             return TRUE;
312
313         default:
314             gmx_incons("Invalid nonbonded kernel type passed!");
315             return FALSE;
316     }
317 }
318
319 void nbnxn_init_search(nbnxn_search_t    * nbs_ptr,
320                        ivec               *n_dd_cells,
321                        gmx_domdec_zones_t *zones,
322                        int                 nthread_max)
323 {
324     nbnxn_search_t nbs;
325     int            d, g, t;
326
327     snew(nbs, 1);
328     *nbs_ptr = nbs;
329
330     nbs->DomDec = (n_dd_cells != NULL);
331
332     clear_ivec(nbs->dd_dim);
333     nbs->ngrid = 1;
334     if (nbs->DomDec)
335     {
336         nbs->zones = zones;
337
338         for (d = 0; d < DIM; d++)
339         {
340             if ((*n_dd_cells)[d] > 1)
341             {
342                 nbs->dd_dim[d] = 1;
343                 /* Each grid matches a DD zone */
344                 nbs->ngrid *= 2;
345             }
346         }
347     }
348
349     snew(nbs->grid, nbs->ngrid);
350     for (g = 0; g < nbs->ngrid; g++)
351     {
352         nbnxn_grid_init(&nbs->grid[g]);
353     }
354     nbs->cell        = NULL;
355     nbs->cell_nalloc = 0;
356     nbs->a           = NULL;
357     nbs->a_nalloc    = 0;
358
359     nbs->nthread_max = nthread_max;
360
361     /* Initialize the work data structures for each thread */
362     snew(nbs->work, nbs->nthread_max);
363     for (t = 0; t < nbs->nthread_max; t++)
364     {
365         nbs->work[t].cxy_na           = NULL;
366         nbs->work[t].cxy_na_nalloc    = 0;
367         nbs->work[t].sort_work        = NULL;
368         nbs->work[t].sort_work_nalloc = 0;
369     }
370
371     /* Initialize detailed nbsearch cycle counting */
372     nbs->print_cycles = (getenv("GMX_NBNXN_CYCLE") != 0);
373     nbs->search_count = 0;
374     nbs_cycle_clear(nbs->cc);
375     for (t = 0; t < nbs->nthread_max; t++)
376     {
377         nbs_cycle_clear(nbs->work[t].cc);
378     }
379 }
380
381 static real grid_atom_density(int n, rvec corner0, rvec corner1)
382 {
383     rvec size;
384
385     rvec_sub(corner1, corner0, size);
386
387     return n/(size[XX]*size[YY]*size[ZZ]);
388 }
389
390 static int set_grid_size_xy(const nbnxn_search_t nbs,
391                             nbnxn_grid_t *grid,
392                             int dd_zone,
393                             int n, rvec corner0, rvec corner1,
394                             real atom_density)
395 {
396     rvec size;
397     int  na_c;
398     real adens, tlen, tlen_x, tlen_y, nc_max;
399     int  t;
400
401     rvec_sub(corner1, corner0, size);
402
403     if (n > grid->na_sc)
404     {
405         /* target cell length */
406         if (grid->bSimple)
407         {
408             /* To minimize the zero interactions, we should make
409              * the largest of the i/j cell cubic.
410              */
411             na_c = max(grid->na_c, grid->na_cj);
412
413             /* Approximately cubic cells */
414             tlen   = pow(na_c/atom_density, 1.0/3.0);
415             tlen_x = tlen;
416             tlen_y = tlen;
417         }
418         else
419         {
420             /* Approximately cubic sub cells */
421             tlen   = pow(grid->na_c/atom_density, 1.0/3.0);
422             tlen_x = tlen*GPU_NSUBCELL_X;
423             tlen_y = tlen*GPU_NSUBCELL_Y;
424         }
425         /* We round ncx and ncy down, because we get less cell pairs
426          * in the nbsist when the fixed cell dimensions (x,y) are
427          * larger than the variable one (z) than the other way around.
428          */
429         grid->ncx = max(1, (int)(size[XX]/tlen_x));
430         grid->ncy = max(1, (int)(size[YY]/tlen_y));
431     }
432     else
433     {
434         grid->ncx = 1;
435         grid->ncy = 1;
436     }
437
438     grid->sx     = size[XX]/grid->ncx;
439     grid->sy     = size[YY]/grid->ncy;
440     grid->inv_sx = 1/grid->sx;
441     grid->inv_sy = 1/grid->sy;
442
443     if (dd_zone > 0)
444     {
445         /* This is a non-home zone, add an extra row of cells
446          * for particles communicated for bonded interactions.
447          * These can be beyond the cut-off. It doesn't matter where
448          * they end up on the grid, but for performance it's better
449          * if they don't end up in cells that can be within cut-off range.
450          */
451         grid->ncx++;
452         grid->ncy++;
453     }
454
455     /* We need one additional cell entry for particles moved by DD */
456     if (grid->ncx*grid->ncy+1 > grid->cxy_nalloc)
457     {
458         grid->cxy_nalloc = over_alloc_large(grid->ncx*grid->ncy+1);
459         srenew(grid->cxy_na, grid->cxy_nalloc);
460         srenew(grid->cxy_ind, grid->cxy_nalloc+1);
461     }
462     for (t = 0; t < nbs->nthread_max; t++)
463     {
464         if (grid->ncx*grid->ncy+1 > nbs->work[t].cxy_na_nalloc)
465         {
466             nbs->work[t].cxy_na_nalloc = over_alloc_large(grid->ncx*grid->ncy+1);
467             srenew(nbs->work[t].cxy_na, nbs->work[t].cxy_na_nalloc);
468         }
469     }
470
471     /* Worst case scenario of 1 atom in each last cell */
472     if (grid->na_cj <= grid->na_c)
473     {
474         nc_max = n/grid->na_sc + grid->ncx*grid->ncy;
475     }
476     else
477     {
478         nc_max = n/grid->na_sc + grid->ncx*grid->ncy*grid->na_cj/grid->na_c;
479     }
480
481     if (nc_max > grid->nc_nalloc)
482     {
483         grid->nc_nalloc = over_alloc_large(nc_max);
484         srenew(grid->nsubc, grid->nc_nalloc);
485         srenew(grid->bbcz, grid->nc_nalloc*NNBSBB_D);
486
487         sfree_aligned(grid->bb);
488         /* This snew also zeros the contents, this avoid possible
489          * floating exceptions in SIMD with the unused bb elements.
490          */
491         if (grid->bSimple)
492         {
493             snew_aligned(grid->bb, grid->nc_nalloc, 16);
494         }
495         else
496         {
497 #ifdef NBNXN_BBXXXX
498             int pbb_nalloc;
499
500             pbb_nalloc = grid->nc_nalloc*GPU_NSUBCELL/STRIDE_PBB*NNBSBB_XXXX;
501             snew_aligned(grid->pbb, pbb_nalloc, 16);
502 #else
503             snew_aligned(grid->bb, grid->nc_nalloc*GPU_NSUBCELL, 16);
504 #endif
505         }
506
507         if (grid->bSimple)
508         {
509             if (grid->na_cj == grid->na_c)
510             {
511                 grid->bbj = grid->bb;
512             }
513             else
514             {
515                 sfree_aligned(grid->bbj);
516                 snew_aligned(grid->bbj, grid->nc_nalloc*grid->na_c/grid->na_cj, 16);
517             }
518         }
519
520         srenew(grid->flags, grid->nc_nalloc);
521     }
522
523     copy_rvec(corner0, grid->c0);
524     copy_rvec(corner1, grid->c1);
525
526     return nc_max;
527 }
528
529 /* We need to sort paricles in grid columns on z-coordinate.
530  * As particle are very often distributed homogeneously, we a sorting
531  * algorithm similar to pigeonhole sort. We multiply the z-coordinate
532  * by a factor, cast to an int and try to store in that hole. If the hole
533  * is full, we move this or another particle. A second pass is needed to make
534  * contiguous elements. SORT_GRID_OVERSIZE is the ratio of holes to particles.
535  * 4 is the optimal value for homogeneous particle distribution and allows
536  * for an O(#particles) sort up till distributions were all particles are
537  * concentrated in 1/4 of the space. No NlogN fallback is implemented,
538  * as it can be expensive to detect imhomogeneous particle distributions.
539  * SGSF is the maximum ratio of holes used, in the worst case all particles
540  * end up in the last hole and we need #particles extra holes at the end.
541  */
542 #define SORT_GRID_OVERSIZE 4
543 #define SGSF (SORT_GRID_OVERSIZE + 1)
544
545 /* Sort particle index a on coordinates x along dim.
546  * Backwards tells if we want decreasing iso increasing coordinates.
547  * h0 is the minimum of the coordinate range.
548  * invh is the 1/length of the sorting range.
549  * n_per_h (>=n) is the expected average number of particles per 1/invh
550  * sort is the sorting work array.
551  * sort should have a size of at least n_per_h*SORT_GRID_OVERSIZE + n,
552  * or easier, allocate at least n*SGSF elements.
553  */
554 static void sort_atoms(int dim, gmx_bool Backwards,
555                        int *a, int n, rvec *x,
556                        real h0, real invh, int n_per_h,
557                        int *sort)
558 {
559     int nsort, i, c;
560     int zi, zim, zi_min, zi_max;
561     int cp, tmp;
562
563     if (n <= 1)
564     {
565         /* Nothing to do */
566         return;
567     }
568
569 #ifndef NDEBUG
570     if (n > n_per_h)
571     {
572         gmx_incons("n > n_per_h");
573     }
574 #endif
575
576     /* Transform the inverse range height into the inverse hole height */
577     invh *= n_per_h*SORT_GRID_OVERSIZE;
578
579     /* Set nsort to the maximum possible number of holes used.
580      * In worst case all n elements end up in the last bin.
581      */
582     nsort = n_per_h*SORT_GRID_OVERSIZE + n;
583
584     /* Determine the index range used, so we can limit it for the second pass */
585     zi_min = INT_MAX;
586     zi_max = -1;
587
588     /* Sort the particles using a simple index sort */
589     for (i = 0; i < n; i++)
590     {
591         /* The cast takes care of float-point rounding effects below zero.
592          * This code assumes particles are less than 1/SORT_GRID_OVERSIZE
593          * times the box height out of the box.
594          */
595         zi = (int)((x[a[i]][dim] - h0)*invh);
596
597 #ifndef NDEBUG
598         /* As we can have rounding effect, we use > iso >= here */
599         if (zi < 0 || zi > n_per_h*SORT_GRID_OVERSIZE)
600         {
601             gmx_fatal(FARGS, "(int)((x[%d][%c]=%f - %f)*%f) = %d, not in 0 - %d*%d\n",
602                       a[i], 'x'+dim, x[a[i]][dim], h0, invh, zi,
603                       n_per_h, SORT_GRID_OVERSIZE);
604         }
605 #endif
606
607         /* Ideally this particle should go in sort cell zi,
608          * but that might already be in use,
609          * in that case find the first empty cell higher up
610          */
611         if (sort[zi] < 0)
612         {
613             sort[zi] = a[i];
614             zi_min   = min(zi_min, zi);
615             zi_max   = max(zi_max, zi);
616         }
617         else
618         {
619             /* We have multiple atoms in the same sorting slot.
620              * Sort on real z for minimal bounding box size.
621              * There is an extra check for identical z to ensure
622              * well-defined output order, independent of input order
623              * to ensure binary reproducibility after restarts.
624              */
625             while (sort[zi] >= 0 && ( x[a[i]][dim] >  x[sort[zi]][dim] ||
626                                       (x[a[i]][dim] == x[sort[zi]][dim] &&
627                                        a[i] > sort[zi])))
628             {
629                 zi++;
630             }
631
632             if (sort[zi] >= 0)
633             {
634                 /* Shift all elements by one slot until we find an empty slot */
635                 cp  = sort[zi];
636                 zim = zi + 1;
637                 while (sort[zim] >= 0)
638                 {
639                     tmp       = sort[zim];
640                     sort[zim] = cp;
641                     cp        = tmp;
642                     zim++;
643                 }
644                 sort[zim] = cp;
645                 zi_max    = max(zi_max, zim);
646             }
647             sort[zi] = a[i];
648             zi_max   = max(zi_max, zi);
649         }
650     }
651
652     c = 0;
653     if (!Backwards)
654     {
655         for (zi = 0; zi < nsort; zi++)
656         {
657             if (sort[zi] >= 0)
658             {
659                 a[c++]   = sort[zi];
660                 sort[zi] = -1;
661             }
662         }
663     }
664     else
665     {
666         for (zi = zi_max; zi >= zi_min; zi--)
667         {
668             if (sort[zi] >= 0)
669             {
670                 a[c++]   = sort[zi];
671                 sort[zi] = -1;
672             }
673         }
674     }
675     if (c < n)
676     {
677         gmx_incons("Lost particles while sorting");
678     }
679 }
680
681 #ifdef GMX_DOUBLE
682 #define R2F_D(x) ((float)((x) >= 0 ? ((1-GMX_FLOAT_EPS)*(x)) : ((1+GMX_FLOAT_EPS)*(x))))
683 #define R2F_U(x) ((float)((x) >= 0 ? ((1+GMX_FLOAT_EPS)*(x)) : ((1-GMX_FLOAT_EPS)*(x))))
684 #else
685 #define R2F_D(x) (x)
686 #define R2F_U(x) (x)
687 #endif
688
689 /* Coordinate order x,y,z, bb order xyz0 */
690 static void calc_bounding_box(int na, int stride, const real *x, nbnxn_bb_t *bb)
691 {
692     int  i, j;
693     real xl, xh, yl, yh, zl, zh;
694
695     i  = 0;
696     xl = x[i+XX];
697     xh = x[i+XX];
698     yl = x[i+YY];
699     yh = x[i+YY];
700     zl = x[i+ZZ];
701     zh = x[i+ZZ];
702     i += stride;
703     for (j = 1; j < na; j++)
704     {
705         xl = min(xl, x[i+XX]);
706         xh = max(xh, x[i+XX]);
707         yl = min(yl, x[i+YY]);
708         yh = max(yh, x[i+YY]);
709         zl = min(zl, x[i+ZZ]);
710         zh = max(zh, x[i+ZZ]);
711         i += stride;
712     }
713     /* Note: possible double to float conversion here */
714     bb->lower[BB_X] = R2F_D(xl);
715     bb->lower[BB_Y] = R2F_D(yl);
716     bb->lower[BB_Z] = R2F_D(zl);
717     bb->upper[BB_X] = R2F_U(xh);
718     bb->upper[BB_Y] = R2F_U(yh);
719     bb->upper[BB_Z] = R2F_U(zh);
720 }
721
722 /* Packed coordinates, bb order xyz0 */
723 static void calc_bounding_box_x_x4(int na, const real *x, nbnxn_bb_t *bb)
724 {
725     int  j;
726     real xl, xh, yl, yh, zl, zh;
727
728     xl = x[XX*PACK_X4];
729     xh = x[XX*PACK_X4];
730     yl = x[YY*PACK_X4];
731     yh = x[YY*PACK_X4];
732     zl = x[ZZ*PACK_X4];
733     zh = x[ZZ*PACK_X4];
734     for (j = 1; j < na; j++)
735     {
736         xl = min(xl, x[j+XX*PACK_X4]);
737         xh = max(xh, x[j+XX*PACK_X4]);
738         yl = min(yl, x[j+YY*PACK_X4]);
739         yh = max(yh, x[j+YY*PACK_X4]);
740         zl = min(zl, x[j+ZZ*PACK_X4]);
741         zh = max(zh, x[j+ZZ*PACK_X4]);
742     }
743     /* Note: possible double to float conversion here */
744     bb->lower[BB_X] = R2F_D(xl);
745     bb->lower[BB_Y] = R2F_D(yl);
746     bb->lower[BB_Z] = R2F_D(zl);
747     bb->upper[BB_X] = R2F_U(xh);
748     bb->upper[BB_Y] = R2F_U(yh);
749     bb->upper[BB_Z] = R2F_U(zh);
750 }
751
752 /* Packed coordinates, bb order xyz0 */
753 static void calc_bounding_box_x_x8(int na, const real *x, nbnxn_bb_t *bb)
754 {
755     int  j;
756     real xl, xh, yl, yh, zl, zh;
757
758     xl = x[XX*PACK_X8];
759     xh = x[XX*PACK_X8];
760     yl = x[YY*PACK_X8];
761     yh = x[YY*PACK_X8];
762     zl = x[ZZ*PACK_X8];
763     zh = x[ZZ*PACK_X8];
764     for (j = 1; j < na; j++)
765     {
766         xl = min(xl, x[j+XX*PACK_X8]);
767         xh = max(xh, x[j+XX*PACK_X8]);
768         yl = min(yl, x[j+YY*PACK_X8]);
769         yh = max(yh, x[j+YY*PACK_X8]);
770         zl = min(zl, x[j+ZZ*PACK_X8]);
771         zh = max(zh, x[j+ZZ*PACK_X8]);
772     }
773     /* Note: possible double to float conversion here */
774     bb->lower[BB_X] = R2F_D(xl);
775     bb->lower[BB_Y] = R2F_D(yl);
776     bb->lower[BB_Z] = R2F_D(zl);
777     bb->upper[BB_X] = R2F_U(xh);
778     bb->upper[BB_Y] = R2F_U(yh);
779     bb->upper[BB_Z] = R2F_U(zh);
780 }
781
782 /* Packed coordinates, bb order xyz0 */
783 static void calc_bounding_box_x_x4_halves(int na, const real *x,
784                                           nbnxn_bb_t *bb, nbnxn_bb_t *bbj)
785 {
786     calc_bounding_box_x_x4(min(na, 2), x, bbj);
787
788     if (na > 2)
789     {
790         calc_bounding_box_x_x4(min(na-2, 2), x+(PACK_X4>>1), bbj+1);
791     }
792     else
793     {
794         /* Set the "empty" bounding box to the same as the first one,
795          * so we don't need to treat special cases in the rest of the code.
796          */
797 #ifdef NBNXN_SEARCH_BB_SIMD4
798         gmx_simd4_store_pr(&bbj[1].lower[0], gmx_simd4_load_bb_pr(&bbj[0].lower[0]));
799         gmx_simd4_store_pr(&bbj[1].upper[0], gmx_simd4_load_bb_pr(&bbj[0].upper[0]));
800 #else
801         bbj[1] = bbj[0];
802 #endif
803     }
804
805 #ifdef NBNXN_SEARCH_BB_SIMD4
806     gmx_simd4_store_pr(&bb->lower[0],
807                        gmx_simd4_min_pr(gmx_simd4_load_bb_pr(&bbj[0].lower[0]),
808                                         gmx_simd4_load_bb_pr(&bbj[1].lower[0])));
809     gmx_simd4_store_pr(&bb->upper[0],
810                        gmx_simd4_max_pr(gmx_simd4_load_bb_pr(&bbj[0].upper[0]),
811                                         gmx_simd4_load_bb_pr(&bbj[1].upper[0])));
812 #else
813     {
814         int i;
815
816         for (i = 0; i < NNBSBB_C; i++)
817         {
818             bb->lower[i] = min(bbj[0].lower[i], bbj[1].lower[i]);
819             bb->upper[i] = max(bbj[0].upper[i], bbj[1].upper[i]);
820         }
821     }
822 #endif
823 }
824
825 #ifdef NBNXN_SEARCH_BB_SIMD4
826
827 /* Coordinate order xyz, bb order xxxxyyyyzzzz */
828 static void calc_bounding_box_xxxx(int na, int stride, const real *x, float *bb)
829 {
830     int  i, j;
831     real xl, xh, yl, yh, zl, zh;
832
833     i  = 0;
834     xl = x[i+XX];
835     xh = x[i+XX];
836     yl = x[i+YY];
837     yh = x[i+YY];
838     zl = x[i+ZZ];
839     zh = x[i+ZZ];
840     i += stride;
841     for (j = 1; j < na; j++)
842     {
843         xl = min(xl, x[i+XX]);
844         xh = max(xh, x[i+XX]);
845         yl = min(yl, x[i+YY]);
846         yh = max(yh, x[i+YY]);
847         zl = min(zl, x[i+ZZ]);
848         zh = max(zh, x[i+ZZ]);
849         i += stride;
850     }
851     /* Note: possible double to float conversion here */
852     bb[0*STRIDE_PBB] = R2F_D(xl);
853     bb[1*STRIDE_PBB] = R2F_D(yl);
854     bb[2*STRIDE_PBB] = R2F_D(zl);
855     bb[3*STRIDE_PBB] = R2F_U(xh);
856     bb[4*STRIDE_PBB] = R2F_U(yh);
857     bb[5*STRIDE_PBB] = R2F_U(zh);
858 }
859
860 #endif /* NBNXN_SEARCH_BB_SIMD4 */
861
862 #ifdef NBNXN_SEARCH_SIMD4_FLOAT_X_BB
863
864 /* Coordinate order xyz?, bb order xyz0 */
865 static void calc_bounding_box_simd4(int na, const float *x, nbnxn_bb_t *bb)
866 {
867     gmx_simd4_pr bb_0_S, bb_1_S;
868     gmx_simd4_pr x_S;
869
870     int    i;
871
872     bb_0_S = gmx_simd4_load_bb_pr(x);
873     bb_1_S = bb_0_S;
874
875     for (i = 1; i < na; i++)
876     {
877         x_S    = gmx_simd4_load_bb_pr(x+i*NNBSBB_C);
878         bb_0_S = gmx_simd4_min_pr(bb_0_S, x_S);
879         bb_1_S = gmx_simd4_max_pr(bb_1_S, x_S);
880     }
881
882     gmx_simd4_store_pr(&bb->lower[0], bb_0_S);
883     gmx_simd4_store_pr(&bb->upper[0], bb_1_S);
884 }
885
886 /* Coordinate order xyz?, bb order xxxxyyyyzzzz */
887 static void calc_bounding_box_xxxx_simd4(int na, const float *x,
888                                          nbnxn_bb_t *bb_work_aligned,
889                                          real *bb)
890 {
891     calc_bounding_box_simd4(na, x, bb_work_aligned);
892
893     bb[0*STRIDE_PBB] = bb_work_aligned->lower[BB_X];
894     bb[1*STRIDE_PBB] = bb_work_aligned->lower[BB_Y];
895     bb[2*STRIDE_PBB] = bb_work_aligned->lower[BB_Z];
896     bb[3*STRIDE_PBB] = bb_work_aligned->upper[BB_X];
897     bb[4*STRIDE_PBB] = bb_work_aligned->upper[BB_Y];
898     bb[5*STRIDE_PBB] = bb_work_aligned->upper[BB_Z];
899 }
900
901 #endif /* NBNXN_SEARCH_SIMD4_FLOAT_X_BB */
902
903
904 /* Combines pairs of consecutive bounding boxes */
905 static void combine_bounding_box_pairs(nbnxn_grid_t *grid, const nbnxn_bb_t *bb)
906 {
907     int    i, j, sc2, nc2, c2;
908
909     for (i = 0; i < grid->ncx*grid->ncy; i++)
910     {
911         /* Starting bb in a column is expected to be 2-aligned */
912         sc2 = grid->cxy_ind[i]>>1;
913         /* For odd numbers skip the last bb here */
914         nc2 = (grid->cxy_na[i]+3)>>(2+1);
915         for (c2 = sc2; c2 < sc2+nc2; c2++)
916         {
917 #ifdef NBNXN_SEARCH_BB_SIMD4
918             gmx_simd4_pr min_S, max_S;
919
920             min_S = gmx_simd4_min_pr(gmx_simd4_load_bb_pr(&bb[c2*2+0].lower[0]),
921                                      gmx_simd4_load_bb_pr(&bb[c2*2+1].lower[0]));
922             max_S = gmx_simd4_max_pr(gmx_simd4_load_bb_pr(&bb[c2*2+0].upper[0]),
923                                      gmx_simd4_load_bb_pr(&bb[c2*2+1].upper[0]));
924             gmx_simd4_store_pr(&grid->bbj[c2].lower[0], min_S);
925             gmx_simd4_store_pr(&grid->bbj[c2].upper[0], max_S);
926 #else
927             for (j = 0; j < NNBSBB_C; j++)
928             {
929                 grid->bbj[c2].lower[j] = min(bb[c2*2+0].lower[j],
930                                              bb[c2*2+1].lower[j]);
931                 grid->bbj[c2].upper[j] = max(bb[c2*2+0].upper[j],
932                                              bb[c2*2+1].upper[j]);
933             }
934 #endif
935         }
936         if (((grid->cxy_na[i]+3)>>2) & 1)
937         {
938             /* The bb count in this column is odd: duplicate the last bb */
939             for (j = 0; j < NNBSBB_C; j++)
940             {
941                 grid->bbj[c2].lower[j] = bb[c2*2].lower[j];
942                 grid->bbj[c2].upper[j] = bb[c2*2].upper[j];
943             }
944         }
945     }
946 }
947
948
949 /* Prints the average bb size, used for debug output */
950 static void print_bbsizes_simple(FILE                *fp,
951                                  const nbnxn_search_t nbs,
952                                  const nbnxn_grid_t  *grid)
953 {
954     int  c, d;
955     dvec ba;
956
957     clear_dvec(ba);
958     for (c = 0; c < grid->nc; c++)
959     {
960         for (d = 0; d < DIM; d++)
961         {
962             ba[d] += grid->bb[c].upper[d] - grid->bb[c].lower[d];
963         }
964     }
965     dsvmul(1.0/grid->nc, ba, ba);
966
967     fprintf(fp, "ns bb: %4.2f %4.2f %4.2f  %4.2f %4.2f %4.2f rel %4.2f %4.2f %4.2f\n",
968             nbs->box[XX][XX]/grid->ncx,
969             nbs->box[YY][YY]/grid->ncy,
970             nbs->box[ZZ][ZZ]*grid->ncx*grid->ncy/grid->nc,
971             ba[XX], ba[YY], ba[ZZ],
972             ba[XX]*grid->ncx/nbs->box[XX][XX],
973             ba[YY]*grid->ncy/nbs->box[YY][YY],
974             ba[ZZ]*grid->nc/(grid->ncx*grid->ncy*nbs->box[ZZ][ZZ]));
975 }
976
977 /* Prints the average bb size, used for debug output */
978 static void print_bbsizes_supersub(FILE                *fp,
979                                    const nbnxn_search_t nbs,
980                                    const nbnxn_grid_t  *grid)
981 {
982     int  ns, c, s;
983     dvec ba;
984
985     clear_dvec(ba);
986     ns = 0;
987     for (c = 0; c < grid->nc; c++)
988     {
989 #ifdef NBNXN_BBXXXX
990         for (s = 0; s < grid->nsubc[c]; s += STRIDE_PBB)
991         {
992             int cs_w, i, d;
993
994             cs_w = (c*GPU_NSUBCELL + s)/STRIDE_PBB;
995             for (i = 0; i < STRIDE_PBB; i++)
996             {
997                 for (d = 0; d < DIM; d++)
998                 {
999                     ba[d] +=
1000                         grid->pbb[cs_w*NNBSBB_XXXX+(DIM+d)*STRIDE_PBB+i] -
1001                         grid->pbb[cs_w*NNBSBB_XXXX+     d *STRIDE_PBB+i];
1002                 }
1003             }
1004         }
1005 #else
1006         for (s = 0; s < grid->nsubc[c]; s++)
1007         {
1008             int cs, d;
1009
1010             cs = c*GPU_NSUBCELL + s;
1011             for (d = 0; d < DIM; d++)
1012             {
1013                 ba[d] += grid->bb[cs].upper[d] - grid->bb[cs].lower[d];
1014             }
1015         }
1016 #endif
1017         ns += grid->nsubc[c];
1018     }
1019     dsvmul(1.0/ns, ba, ba);
1020
1021     fprintf(fp, "ns bb: %4.2f %4.2f %4.2f  %4.2f %4.2f %4.2f rel %4.2f %4.2f %4.2f\n",
1022             nbs->box[XX][XX]/(grid->ncx*GPU_NSUBCELL_X),
1023             nbs->box[YY][YY]/(grid->ncy*GPU_NSUBCELL_Y),
1024             nbs->box[ZZ][ZZ]*grid->ncx*grid->ncy/(grid->nc*GPU_NSUBCELL_Z),
1025             ba[XX], ba[YY], ba[ZZ],
1026             ba[XX]*grid->ncx*GPU_NSUBCELL_X/nbs->box[XX][XX],
1027             ba[YY]*grid->ncy*GPU_NSUBCELL_Y/nbs->box[YY][YY],
1028             ba[ZZ]*grid->nc*GPU_NSUBCELL_Z/(grid->ncx*grid->ncy*nbs->box[ZZ][ZZ]));
1029 }
1030
1031 /* Potentially sorts atoms on LJ coefficients !=0 and ==0.
1032  * Also sets interaction flags.
1033  */
1034 void sort_on_lj(int na_c,
1035                 int a0, int a1, const int *atinfo,
1036                 int *order,
1037                 int *flags)
1038 {
1039     int      subc, s, a, n1, n2, a_lj_max, i, j;
1040     int      sort1[NBNXN_NA_SC_MAX/GPU_NSUBCELL];
1041     int      sort2[NBNXN_NA_SC_MAX/GPU_NSUBCELL];
1042     gmx_bool haveQ;
1043
1044     *flags = 0;
1045
1046     subc = 0;
1047     for (s = a0; s < a1; s += na_c)
1048     {
1049         /* Make lists for this (sub-)cell on atoms with and without LJ */
1050         n1       = 0;
1051         n2       = 0;
1052         haveQ    = FALSE;
1053         a_lj_max = -1;
1054         for (a = s; a < min(s+na_c, a1); a++)
1055         {
1056             haveQ = haveQ || GET_CGINFO_HAS_Q(atinfo[order[a]]);
1057
1058             if (GET_CGINFO_HAS_VDW(atinfo[order[a]]))
1059             {
1060                 sort1[n1++] = order[a];
1061                 a_lj_max    = a;
1062             }
1063             else
1064             {
1065                 sort2[n2++] = order[a];
1066             }
1067         }
1068
1069         /* If we don't have atom with LJ, there's nothing to sort */
1070         if (n1 > 0)
1071         {
1072             *flags |= NBNXN_CI_DO_LJ(subc);
1073
1074             if (2*n1 <= na_c)
1075             {
1076                 /* Only sort when strictly necessary. Ordering particles
1077                  * Ordering particles can lead to less accurate summation
1078                  * due to rounding, both for LJ and Coulomb interactions.
1079                  */
1080                 if (2*(a_lj_max - s) >= na_c)
1081                 {
1082                     for (i = 0; i < n1; i++)
1083                     {
1084                         order[a0+i] = sort1[i];
1085                     }
1086                     for (j = 0; j < n2; j++)
1087                     {
1088                         order[a0+n1+j] = sort2[j];
1089                     }
1090                 }
1091
1092                 *flags |= NBNXN_CI_HALF_LJ(subc);
1093             }
1094         }
1095         if (haveQ)
1096         {
1097             *flags |= NBNXN_CI_DO_COUL(subc);
1098         }
1099         subc++;
1100     }
1101 }
1102
1103 /* Fill a pair search cell with atoms.
1104  * Potentially sorts atoms and sets the interaction flags.
1105  */
1106 void fill_cell(const nbnxn_search_t nbs,
1107                nbnxn_grid_t *grid,
1108                nbnxn_atomdata_t *nbat,
1109                int a0, int a1,
1110                const int *atinfo,
1111                rvec *x,
1112                int sx, int sy, int sz,
1113                nbnxn_bb_t gmx_unused *bb_work_aligned)
1114 {
1115     int         na, a;
1116     size_t      offset;
1117     nbnxn_bb_t *bb_ptr;
1118 #ifdef NBNXN_BBXXXX
1119     float      *pbb_ptr;
1120 #endif
1121
1122     na = a1 - a0;
1123
1124     if (grid->bSimple)
1125     {
1126         sort_on_lj(grid->na_c, a0, a1, atinfo, nbs->a,
1127                    grid->flags+(a0>>grid->na_c_2log)-grid->cell0);
1128     }
1129
1130     /* Now we have sorted the atoms, set the cell indices */
1131     for (a = a0; a < a1; a++)
1132     {
1133         nbs->cell[nbs->a[a]] = a;
1134     }
1135
1136     copy_rvec_to_nbat_real(nbs->a+a0, a1-a0, grid->na_c, x,
1137                            nbat->XFormat, nbat->x, a0,
1138                            sx, sy, sz);
1139
1140     if (nbat->XFormat == nbatX4)
1141     {
1142         /* Store the bounding boxes as xyz.xyz. */
1143         offset = (a0 - grid->cell0*grid->na_sc) >> grid->na_c_2log;
1144         bb_ptr = grid->bb + offset;
1145
1146 #if defined GMX_NBNXN_SIMD && GMX_SIMD_WIDTH_HERE == 2
1147         if (2*grid->na_cj == grid->na_c)
1148         {
1149             calc_bounding_box_x_x4_halves(na, nbat->x+X4_IND_A(a0), bb_ptr,
1150                                           grid->bbj+offset*2);
1151         }
1152         else
1153 #endif
1154         {
1155             calc_bounding_box_x_x4(na, nbat->x+X4_IND_A(a0), bb_ptr);
1156         }
1157     }
1158     else if (nbat->XFormat == nbatX8)
1159     {
1160         /* Store the bounding boxes as xyz.xyz. */
1161         offset = (a0 - grid->cell0*grid->na_sc) >> grid->na_c_2log;
1162         bb_ptr = grid->bb + offset;
1163
1164         calc_bounding_box_x_x8(na, nbat->x+X8_IND_A(a0), bb_ptr);
1165     }
1166 #ifdef NBNXN_BBXXXX
1167     else if (!grid->bSimple)
1168     {
1169         /* Store the bounding boxes in a format convenient
1170          * for SIMD4 calculations: xxxxyyyyzzzz...
1171          */
1172         pbb_ptr =
1173             grid->pbb +
1174             ((a0-grid->cell0*grid->na_sc)>>(grid->na_c_2log+STRIDE_PBB_2LOG))*NNBSBB_XXXX +
1175             (((a0-grid->cell0*grid->na_sc)>>grid->na_c_2log) & (STRIDE_PBB-1));
1176
1177 #ifdef NBNXN_SEARCH_SIMD4_FLOAT_X_BB
1178         if (nbat->XFormat == nbatXYZQ)
1179         {
1180             calc_bounding_box_xxxx_simd4(na, nbat->x+a0*nbat->xstride,
1181                                          bb_work_aligned, pbb_ptr);
1182         }
1183         else
1184 #endif
1185         {
1186             calc_bounding_box_xxxx(na, nbat->xstride, nbat->x+a0*nbat->xstride,
1187                                    pbb_ptr);
1188         }
1189         if (gmx_debug_at)
1190         {
1191             fprintf(debug, "%2d %2d %2d bb %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f\n",
1192                     sx, sy, sz,
1193                     pbb_ptr[0*STRIDE_PBB], pbb_ptr[3*STRIDE_PBB],
1194                     pbb_ptr[1*STRIDE_PBB], pbb_ptr[4*STRIDE_PBB],
1195                     pbb_ptr[2*STRIDE_PBB], pbb_ptr[5*STRIDE_PBB]);
1196         }
1197     }
1198 #endif
1199     else
1200     {
1201         /* Store the bounding boxes as xyz.xyz. */
1202         bb_ptr = grid->bb+((a0-grid->cell0*grid->na_sc)>>grid->na_c_2log);
1203
1204         calc_bounding_box(na, nbat->xstride, nbat->x+a0*nbat->xstride,
1205                           bb_ptr);
1206
1207         if (gmx_debug_at)
1208         {
1209             int bbo;
1210             bbo = (a0 - grid->cell0*grid->na_sc)/grid->na_c;
1211             fprintf(debug, "%2d %2d %2d bb %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f\n",
1212                     sx, sy, sz,
1213                     grid->bb[bbo].lower[BB_X],
1214                     grid->bb[bbo].lower[BB_Y],
1215                     grid->bb[bbo].lower[BB_Z],
1216                     grid->bb[bbo].upper[BB_X],
1217                     grid->bb[bbo].upper[BB_Y],
1218                     grid->bb[bbo].upper[BB_Z]);
1219         }
1220     }
1221 }
1222
1223 /* Spatially sort the atoms within one grid column */
1224 static void sort_columns_simple(const nbnxn_search_t nbs,
1225                                 int dd_zone,
1226                                 nbnxn_grid_t *grid,
1227                                 int a0, int a1,
1228                                 const int *atinfo,
1229                                 rvec *x,
1230                                 nbnxn_atomdata_t *nbat,
1231                                 int cxy_start, int cxy_end,
1232                                 int *sort_work)
1233 {
1234     int  cxy;
1235     int  cx, cy, cz, ncz, cfilled, c;
1236     int  na, ash, ind, a;
1237     int  na_c, ash_c;
1238
1239     if (debug)
1240     {
1241         fprintf(debug, "cell0 %d sorting columns %d - %d, atoms %d - %d\n",
1242                 grid->cell0, cxy_start, cxy_end, a0, a1);
1243     }
1244
1245     /* Sort the atoms within each x,y column in 3 dimensions */
1246     for (cxy = cxy_start; cxy < cxy_end; cxy++)
1247     {
1248         cx = cxy/grid->ncy;
1249         cy = cxy - cx*grid->ncy;
1250
1251         na  = grid->cxy_na[cxy];
1252         ncz = grid->cxy_ind[cxy+1] - grid->cxy_ind[cxy];
1253         ash = (grid->cell0 + grid->cxy_ind[cxy])*grid->na_sc;
1254
1255         /* Sort the atoms within each x,y column on z coordinate */
1256         sort_atoms(ZZ, FALSE,
1257                    nbs->a+ash, na, x,
1258                    grid->c0[ZZ],
1259                    1.0/nbs->box[ZZ][ZZ], ncz*grid->na_sc,
1260                    sort_work);
1261
1262         /* Fill the ncz cells in this column */
1263         cfilled = grid->cxy_ind[cxy];
1264         for (cz = 0; cz < ncz; cz++)
1265         {
1266             c  = grid->cxy_ind[cxy] + cz;
1267
1268             ash_c = ash + cz*grid->na_sc;
1269             na_c  = min(grid->na_sc, na-(ash_c-ash));
1270
1271             fill_cell(nbs, grid, nbat,
1272                       ash_c, ash_c+na_c, atinfo, x,
1273                       grid->na_sc*cx + (dd_zone >> 2),
1274                       grid->na_sc*cy + (dd_zone & 3),
1275                       grid->na_sc*cz,
1276                       NULL);
1277
1278             /* This copy to bbcz is not really necessary.
1279              * But it allows to use the same grid search code
1280              * for the simple and supersub cell setups.
1281              */
1282             if (na_c > 0)
1283             {
1284                 cfilled = c;
1285             }
1286             grid->bbcz[c*NNBSBB_D  ] = grid->bb[cfilled].lower[BB_Z];
1287             grid->bbcz[c*NNBSBB_D+1] = grid->bb[cfilled].upper[BB_Z];
1288         }
1289
1290         /* Set the unused atom indices to -1 */
1291         for (ind = na; ind < ncz*grid->na_sc; ind++)
1292         {
1293             nbs->a[ash+ind] = -1;
1294         }
1295     }
1296 }
1297
1298 /* Spatially sort the atoms within one grid column */
1299 static void sort_columns_supersub(const nbnxn_search_t nbs,
1300                                   int dd_zone,
1301                                   nbnxn_grid_t *grid,
1302                                   int a0, int a1,
1303                                   const int *atinfo,
1304                                   rvec *x,
1305                                   nbnxn_atomdata_t *nbat,
1306                                   int cxy_start, int cxy_end,
1307                                   int *sort_work)
1308 {
1309     int  cxy;
1310     int  cx, cy, cz = -1, c = -1, ncz;
1311     int  na, ash, na_c, ind, a;
1312     int  subdiv_z, sub_z, na_z, ash_z;
1313     int  subdiv_y, sub_y, na_y, ash_y;
1314     int  subdiv_x, sub_x, na_x, ash_x;
1315
1316     /* cppcheck-suppress unassignedVariable */
1317     nbnxn_bb_t bb_work_array[2], *bb_work_aligned;
1318
1319     bb_work_aligned = (nbnxn_bb_t *)(((size_t)(bb_work_array+1)) & (~((size_t)15)));
1320
1321     if (debug)
1322     {
1323         fprintf(debug, "cell0 %d sorting columns %d - %d, atoms %d - %d\n",
1324                 grid->cell0, cxy_start, cxy_end, a0, a1);
1325     }
1326
1327     subdiv_x = grid->na_c;
1328     subdiv_y = GPU_NSUBCELL_X*subdiv_x;
1329     subdiv_z = GPU_NSUBCELL_Y*subdiv_y;
1330
1331     /* Sort the atoms within each x,y column in 3 dimensions */
1332     for (cxy = cxy_start; cxy < cxy_end; cxy++)
1333     {
1334         cx = cxy/grid->ncy;
1335         cy = cxy - cx*grid->ncy;
1336
1337         na  = grid->cxy_na[cxy];
1338         ncz = grid->cxy_ind[cxy+1] - grid->cxy_ind[cxy];
1339         ash = (grid->cell0 + grid->cxy_ind[cxy])*grid->na_sc;
1340
1341         /* Sort the atoms within each x,y column on z coordinate */
1342         sort_atoms(ZZ, FALSE,
1343                    nbs->a+ash, na, x,
1344                    grid->c0[ZZ],
1345                    1.0/nbs->box[ZZ][ZZ], ncz*grid->na_sc,
1346                    sort_work);
1347
1348         /* This loop goes over the supercells and subcells along z at once */
1349         for (sub_z = 0; sub_z < ncz*GPU_NSUBCELL_Z; sub_z++)
1350         {
1351             ash_z = ash + sub_z*subdiv_z;
1352             na_z  = min(subdiv_z, na-(ash_z-ash));
1353
1354             /* We have already sorted on z */
1355
1356             if (sub_z % GPU_NSUBCELL_Z == 0)
1357             {
1358                 cz = sub_z/GPU_NSUBCELL_Z;
1359                 c  = grid->cxy_ind[cxy] + cz;
1360
1361                 /* The number of atoms in this supercell */
1362                 na_c = min(grid->na_sc, na-(ash_z-ash));
1363
1364                 grid->nsubc[c] = min(GPU_NSUBCELL, (na_c+grid->na_c-1)/grid->na_c);
1365
1366                 /* Store the z-boundaries of the super cell */
1367                 grid->bbcz[c*NNBSBB_D  ] = x[nbs->a[ash_z]][ZZ];
1368                 grid->bbcz[c*NNBSBB_D+1] = x[nbs->a[ash_z+na_c-1]][ZZ];
1369             }
1370
1371 #if GPU_NSUBCELL_Y > 1
1372             /* Sort the atoms along y */
1373             sort_atoms(YY, (sub_z & 1),
1374                        nbs->a+ash_z, na_z, x,
1375                        grid->c0[YY]+cy*grid->sy,
1376                        grid->inv_sy, subdiv_z,
1377                        sort_work);
1378 #endif
1379
1380             for (sub_y = 0; sub_y < GPU_NSUBCELL_Y; sub_y++)
1381             {
1382                 ash_y = ash_z + sub_y*subdiv_y;
1383                 na_y  = min(subdiv_y, na-(ash_y-ash));
1384
1385 #if GPU_NSUBCELL_X > 1
1386                 /* Sort the atoms along x */
1387                 sort_atoms(XX, ((cz*GPU_NSUBCELL_Y + sub_y) & 1),
1388                            nbs->a+ash_y, na_y, x,
1389                            grid->c0[XX]+cx*grid->sx,
1390                            grid->inv_sx, subdiv_y,
1391                            sort_work);
1392 #endif
1393
1394                 for (sub_x = 0; sub_x < GPU_NSUBCELL_X; sub_x++)
1395                 {
1396                     ash_x = ash_y + sub_x*subdiv_x;
1397                     na_x  = min(subdiv_x, na-(ash_x-ash));
1398
1399                     fill_cell(nbs, grid, nbat,
1400                               ash_x, ash_x+na_x, atinfo, x,
1401                               grid->na_c*(cx*GPU_NSUBCELL_X+sub_x) + (dd_zone >> 2),
1402                               grid->na_c*(cy*GPU_NSUBCELL_Y+sub_y) + (dd_zone & 3),
1403                               grid->na_c*sub_z,
1404                               bb_work_aligned);
1405                 }
1406             }
1407         }
1408
1409         /* Set the unused atom indices to -1 */
1410         for (ind = na; ind < ncz*grid->na_sc; ind++)
1411         {
1412             nbs->a[ash+ind] = -1;
1413         }
1414     }
1415 }
1416
1417 /* Determine in which grid column atoms should go */
1418 static void calc_column_indices(nbnxn_grid_t *grid,
1419                                 int a0, int a1,
1420                                 rvec *x,
1421                                 int dd_zone, const int *move,
1422                                 int thread, int nthread,
1423                                 int *cell,
1424                                 int *cxy_na)
1425 {
1426     int  n0, n1, i;
1427     int  cx, cy;
1428
1429     /* We add one extra cell for particles which moved during DD */
1430     for (i = 0; i < grid->ncx*grid->ncy+1; i++)
1431     {
1432         cxy_na[i] = 0;
1433     }
1434
1435     n0 = a0 + (int)((thread+0)*(a1 - a0))/nthread;
1436     n1 = a0 + (int)((thread+1)*(a1 - a0))/nthread;
1437     if (dd_zone == 0)
1438     {
1439         /* Home zone */
1440         for (i = n0; i < n1; i++)
1441         {
1442             if (move == NULL || move[i] >= 0)
1443             {
1444                 /* We need to be careful with rounding,
1445                  * particles might be a few bits outside the local zone.
1446                  * The int cast takes care of the lower bound,
1447                  * we will explicitly take care of the upper bound.
1448                  */
1449                 cx = (int)((x[i][XX] - grid->c0[XX])*grid->inv_sx);
1450                 cy = (int)((x[i][YY] - grid->c0[YY])*grid->inv_sy);
1451
1452 #ifndef NDEBUG
1453                 if (cx < 0 || cx > grid->ncx ||
1454                     cy < 0 || cy > grid->ncy)
1455                 {
1456                     gmx_fatal(FARGS,
1457                               "grid cell cx %d cy %d out of range (max %d %d)\n"
1458                               "atom %f %f %f, grid->c0 %f %f",
1459                               cx, cy, grid->ncx, grid->ncy,
1460                               x[i][XX], x[i][YY], x[i][ZZ], grid->c0[XX], grid->c0[YY]);
1461                 }
1462 #endif
1463                 /* Take care of potential rouding issues */
1464                 cx = min(cx, grid->ncx - 1);
1465                 cy = min(cy, grid->ncy - 1);
1466
1467                 /* For the moment cell will contain only the, grid local,
1468                  * x and y indices, not z.
1469                  */
1470                 cell[i] = cx*grid->ncy + cy;
1471             }
1472             else
1473             {
1474                 /* Put this moved particle after the end of the grid,
1475                  * so we can process it later without using conditionals.
1476                  */
1477                 cell[i] = grid->ncx*grid->ncy;
1478             }
1479
1480             cxy_na[cell[i]]++;
1481         }
1482     }
1483     else
1484     {
1485         /* Non-home zone */
1486         for (i = n0; i < n1; i++)
1487         {
1488             cx = (int)((x[i][XX] - grid->c0[XX])*grid->inv_sx);
1489             cy = (int)((x[i][YY] - grid->c0[YY])*grid->inv_sy);
1490
1491             /* For non-home zones there could be particles outside
1492              * the non-bonded cut-off range, which have been communicated
1493              * for bonded interactions only. For the result it doesn't
1494              * matter where these end up on the grid. For performance
1495              * we put them in an extra row at the border.
1496              */
1497             cx = max(cx, 0);
1498             cx = min(cx, grid->ncx - 1);
1499             cy = max(cy, 0);
1500             cy = min(cy, grid->ncy - 1);
1501
1502             /* For the moment cell will contain only the, grid local,
1503              * x and y indices, not z.
1504              */
1505             cell[i] = cx*grid->ncy + cy;
1506
1507             cxy_na[cell[i]]++;
1508         }
1509     }
1510 }
1511
1512 /* Determine in which grid cells the atoms should go */
1513 static void calc_cell_indices(const nbnxn_search_t nbs,
1514                               int dd_zone,
1515                               nbnxn_grid_t *grid,
1516                               int a0, int a1,
1517                               const int *atinfo,
1518                               rvec *x,
1519                               const int *move,
1520                               nbnxn_atomdata_t *nbat)
1521 {
1522     int   n0, n1, i;
1523     int   cx, cy, cxy, ncz_max, ncz;
1524     int   nthread, thread;
1525     int  *cxy_na, cxy_na_i;
1526
1527     nthread = gmx_omp_nthreads_get(emntPairsearch);
1528
1529 #pragma omp parallel for num_threads(nthread) schedule(static)
1530     for (thread = 0; thread < nthread; thread++)
1531     {
1532         calc_column_indices(grid, a0, a1, x, dd_zone, move, thread, nthread,
1533                             nbs->cell, nbs->work[thread].cxy_na);
1534     }
1535
1536     /* Make the cell index as a function of x and y */
1537     ncz_max          = 0;
1538     ncz              = 0;
1539     grid->cxy_ind[0] = 0;
1540     for (i = 0; i < grid->ncx*grid->ncy+1; i++)
1541     {
1542         /* We set ncz_max at the beginning of the loop iso at the end
1543          * to skip i=grid->ncx*grid->ncy which are moved particles
1544          * that do not need to be ordered on the grid.
1545          */
1546         if (ncz > ncz_max)
1547         {
1548             ncz_max = ncz;
1549         }
1550         cxy_na_i = nbs->work[0].cxy_na[i];
1551         for (thread = 1; thread < nthread; thread++)
1552         {
1553             cxy_na_i += nbs->work[thread].cxy_na[i];
1554         }
1555         ncz = (cxy_na_i + grid->na_sc - 1)/grid->na_sc;
1556         if (nbat->XFormat == nbatX8)
1557         {
1558             /* Make the number of cell a multiple of 2 */
1559             ncz = (ncz + 1) & ~1;
1560         }
1561         grid->cxy_ind[i+1] = grid->cxy_ind[i] + ncz;
1562         /* Clear cxy_na, so we can reuse the array below */
1563         grid->cxy_na[i] = 0;
1564     }
1565     grid->nc = grid->cxy_ind[grid->ncx*grid->ncy] - grid->cxy_ind[0];
1566
1567     nbat->natoms = (grid->cell0 + grid->nc)*grid->na_sc;
1568
1569     if (debug)
1570     {
1571         fprintf(debug, "ns na_sc %d na_c %d super-cells: %d x %d y %d z %.1f maxz %d\n",
1572                 grid->na_sc, grid->na_c, grid->nc,
1573                 grid->ncx, grid->ncy, grid->nc/((double)(grid->ncx*grid->ncy)),
1574                 ncz_max);
1575         if (gmx_debug_at)
1576         {
1577             i = 0;
1578             for (cy = 0; cy < grid->ncy; cy++)
1579             {
1580                 for (cx = 0; cx < grid->ncx; cx++)
1581                 {
1582                     fprintf(debug, " %2d", grid->cxy_ind[i+1]-grid->cxy_ind[i]);
1583                     i++;
1584                 }
1585                 fprintf(debug, "\n");
1586             }
1587         }
1588     }
1589
1590     /* Make sure the work array for sorting is large enough */
1591     if (ncz_max*grid->na_sc*SGSF > nbs->work[0].sort_work_nalloc)
1592     {
1593         for (thread = 0; thread < nbs->nthread_max; thread++)
1594         {
1595             nbs->work[thread].sort_work_nalloc =
1596                 over_alloc_large(ncz_max*grid->na_sc*SGSF);
1597             srenew(nbs->work[thread].sort_work,
1598                    nbs->work[thread].sort_work_nalloc);
1599             /* When not in use, all elements should be -1 */
1600             for (i = 0; i < nbs->work[thread].sort_work_nalloc; i++)
1601             {
1602                 nbs->work[thread].sort_work[i] = -1;
1603             }
1604         }
1605     }
1606
1607     /* Now we know the dimensions we can fill the grid.
1608      * This is the first, unsorted fill. We sort the columns after this.
1609      */
1610     for (i = a0; i < a1; i++)
1611     {
1612         /* At this point nbs->cell contains the local grid x,y indices */
1613         cxy = nbs->cell[i];
1614         nbs->a[(grid->cell0 + grid->cxy_ind[cxy])*grid->na_sc + grid->cxy_na[cxy]++] = i;
1615     }
1616
1617     if (dd_zone == 0)
1618     {
1619         /* Set the cell indices for the moved particles */
1620         n0 = grid->nc*grid->na_sc;
1621         n1 = grid->nc*grid->na_sc+grid->cxy_na[grid->ncx*grid->ncy];
1622         if (dd_zone == 0)
1623         {
1624             for (i = n0; i < n1; i++)
1625             {
1626                 nbs->cell[nbs->a[i]] = i;
1627             }
1628         }
1629     }
1630
1631     /* Sort the super-cell columns along z into the sub-cells. */
1632 #pragma omp parallel for num_threads(nbs->nthread_max) schedule(static)
1633     for (thread = 0; thread < nbs->nthread_max; thread++)
1634     {
1635         if (grid->bSimple)
1636         {
1637             sort_columns_simple(nbs, dd_zone, grid, a0, a1, atinfo, x, nbat,
1638                                 ((thread+0)*grid->ncx*grid->ncy)/nthread,
1639                                 ((thread+1)*grid->ncx*grid->ncy)/nthread,
1640                                 nbs->work[thread].sort_work);
1641         }
1642         else
1643         {
1644             sort_columns_supersub(nbs, dd_zone, grid, a0, a1, atinfo, x, nbat,
1645                                   ((thread+0)*grid->ncx*grid->ncy)/nthread,
1646                                   ((thread+1)*grid->ncx*grid->ncy)/nthread,
1647                                   nbs->work[thread].sort_work);
1648         }
1649     }
1650
1651     if (grid->bSimple && nbat->XFormat == nbatX8)
1652     {
1653         combine_bounding_box_pairs(grid, grid->bb);
1654     }
1655
1656     if (!grid->bSimple)
1657     {
1658         grid->nsubc_tot = 0;
1659         for (i = 0; i < grid->nc; i++)
1660         {
1661             grid->nsubc_tot += grid->nsubc[i];
1662         }
1663     }
1664
1665     if (debug)
1666     {
1667         if (grid->bSimple)
1668         {
1669             print_bbsizes_simple(debug, nbs, grid);
1670         }
1671         else
1672         {
1673             fprintf(debug, "ns non-zero sub-cells: %d average atoms %.2f\n",
1674                     grid->nsubc_tot, (a1-a0)/(double)grid->nsubc_tot);
1675
1676             print_bbsizes_supersub(debug, nbs, grid);
1677         }
1678     }
1679 }
1680
1681 static void init_buffer_flags(nbnxn_buffer_flags_t *flags,
1682                               int                   natoms)
1683 {
1684     int b;
1685
1686     flags->nflag = (natoms + NBNXN_BUFFERFLAG_SIZE - 1)/NBNXN_BUFFERFLAG_SIZE;
1687     if (flags->nflag > flags->flag_nalloc)
1688     {
1689         flags->flag_nalloc = over_alloc_large(flags->nflag);
1690         srenew(flags->flag, flags->flag_nalloc);
1691     }
1692     for (b = 0; b < flags->nflag; b++)
1693     {
1694         flags->flag[b] = 0;
1695     }
1696 }
1697
1698 /* Sets up a grid and puts the atoms on the grid.
1699  * This function only operates on one domain of the domain decompostion.
1700  * Note that without domain decomposition there is only one domain.
1701  */
1702 void nbnxn_put_on_grid(nbnxn_search_t nbs,
1703                        int ePBC, matrix box,
1704                        int dd_zone,
1705                        rvec corner0, rvec corner1,
1706                        int a0, int a1,
1707                        real atom_density,
1708                        const int *atinfo,
1709                        rvec *x,
1710                        int nmoved, int *move,
1711                        int nb_kernel_type,
1712                        nbnxn_atomdata_t *nbat)
1713 {
1714     nbnxn_grid_t *grid;
1715     int           n;
1716     int           nc_max_grid, nc_max;
1717
1718     grid = &nbs->grid[dd_zone];
1719
1720     nbs_cycle_start(&nbs->cc[enbsCCgrid]);
1721
1722     grid->bSimple = nbnxn_kernel_pairlist_simple(nb_kernel_type);
1723
1724     grid->na_c      = nbnxn_kernel_to_ci_size(nb_kernel_type);
1725     grid->na_cj     = nbnxn_kernel_to_cj_size(nb_kernel_type);
1726     grid->na_sc     = (grid->bSimple ? 1 : GPU_NSUBCELL)*grid->na_c;
1727     grid->na_c_2log = get_2log(grid->na_c);
1728
1729     nbat->na_c = grid->na_c;
1730
1731     if (dd_zone == 0)
1732     {
1733         grid->cell0 = 0;
1734     }
1735     else
1736     {
1737         grid->cell0 =
1738             (nbs->grid[dd_zone-1].cell0 + nbs->grid[dd_zone-1].nc)*
1739             nbs->grid[dd_zone-1].na_sc/grid->na_sc;
1740     }
1741
1742     n = a1 - a0;
1743
1744     if (dd_zone == 0)
1745     {
1746         nbs->ePBC = ePBC;
1747         copy_mat(box, nbs->box);
1748
1749         if (atom_density >= 0)
1750         {
1751             grid->atom_density = atom_density;
1752         }
1753         else
1754         {
1755             grid->atom_density = grid_atom_density(n-nmoved, corner0, corner1);
1756         }
1757
1758         grid->cell0 = 0;
1759
1760         nbs->natoms_local    = a1 - nmoved;
1761         /* We assume that nbnxn_put_on_grid is called first
1762          * for the local atoms (dd_zone=0).
1763          */
1764         nbs->natoms_nonlocal = a1 - nmoved;
1765     }
1766     else
1767     {
1768         nbs->natoms_nonlocal = max(nbs->natoms_nonlocal, a1);
1769     }
1770
1771     nc_max_grid = set_grid_size_xy(nbs, grid,
1772                                    dd_zone, n-nmoved, corner0, corner1,
1773                                    nbs->grid[0].atom_density);
1774
1775     nc_max = grid->cell0 + nc_max_grid;
1776
1777     if (a1 > nbs->cell_nalloc)
1778     {
1779         nbs->cell_nalloc = over_alloc_large(a1);
1780         srenew(nbs->cell, nbs->cell_nalloc);
1781     }
1782
1783     /* To avoid conditionals we store the moved particles at the end of a,
1784      * make sure we have enough space.
1785      */
1786     if (nc_max*grid->na_sc + nmoved > nbs->a_nalloc)
1787     {
1788         nbs->a_nalloc = over_alloc_large(nc_max*grid->na_sc + nmoved);
1789         srenew(nbs->a, nbs->a_nalloc);
1790     }
1791
1792     /* We need padding up to a multiple of the buffer flag size: simply add */
1793     if (nc_max*grid->na_sc + NBNXN_BUFFERFLAG_SIZE > nbat->nalloc)
1794     {
1795         nbnxn_atomdata_realloc(nbat, nc_max*grid->na_sc+NBNXN_BUFFERFLAG_SIZE);
1796     }
1797
1798     calc_cell_indices(nbs, dd_zone, grid, a0, a1, atinfo, x, move, nbat);
1799
1800     if (dd_zone == 0)
1801     {
1802         nbat->natoms_local = nbat->natoms;
1803     }
1804
1805     nbs_cycle_stop(&nbs->cc[enbsCCgrid]);
1806 }
1807
1808 /* Calls nbnxn_put_on_grid for all non-local domains */
1809 void nbnxn_put_on_grid_nonlocal(nbnxn_search_t            nbs,
1810                                 const gmx_domdec_zones_t *zones,
1811                                 const int                *atinfo,
1812                                 rvec                     *x,
1813                                 int                       nb_kernel_type,
1814                                 nbnxn_atomdata_t         *nbat)
1815 {
1816     int  zone, d;
1817     rvec c0, c1;
1818
1819     for (zone = 1; zone < zones->n; zone++)
1820     {
1821         for (d = 0; d < DIM; d++)
1822         {
1823             c0[d] = zones->size[zone].bb_x0[d];
1824             c1[d] = zones->size[zone].bb_x1[d];
1825         }
1826
1827         nbnxn_put_on_grid(nbs, nbs->ePBC, NULL,
1828                           zone, c0, c1,
1829                           zones->cg_range[zone],
1830                           zones->cg_range[zone+1],
1831                           -1,
1832                           atinfo,
1833                           x,
1834                           0, NULL,
1835                           nb_kernel_type,
1836                           nbat);
1837     }
1838 }
1839
1840 /* Add simple grid type information to the local super/sub grid */
1841 void nbnxn_grid_add_simple(nbnxn_search_t    nbs,
1842                            nbnxn_atomdata_t *nbat)
1843 {
1844     nbnxn_grid_t *grid;
1845     float        *bbcz;
1846     nbnxn_bb_t   *bb;
1847     int           ncd, sc;
1848
1849     grid = &nbs->grid[0];
1850
1851     if (grid->bSimple)
1852     {
1853         gmx_incons("nbnxn_grid_simple called with a simple grid");
1854     }
1855
1856     ncd = grid->na_sc/NBNXN_CPU_CLUSTER_I_SIZE;
1857
1858     if (grid->nc*ncd > grid->nc_nalloc_simple)
1859     {
1860         grid->nc_nalloc_simple = over_alloc_large(grid->nc*ncd);
1861         srenew(grid->bbcz_simple, grid->nc_nalloc_simple*NNBSBB_D);
1862         srenew(grid->bb_simple, grid->nc_nalloc_simple);
1863         srenew(grid->flags_simple, grid->nc_nalloc_simple);
1864         if (nbat->XFormat)
1865         {
1866             sfree_aligned(grid->bbj);
1867             snew_aligned(grid->bbj, grid->nc_nalloc_simple/2, 16);
1868         }
1869     }
1870
1871     bbcz = grid->bbcz_simple;
1872     bb   = grid->bb_simple;
1873
1874 #pragma omp parallel for num_threads(gmx_omp_nthreads_get(emntPairsearch)) schedule(static)
1875     for (sc = 0; sc < grid->nc; sc++)
1876     {
1877         int c, tx, na;
1878
1879         for (c = 0; c < ncd; c++)
1880         {
1881             tx = sc*ncd + c;
1882
1883             na = NBNXN_CPU_CLUSTER_I_SIZE;
1884             while (na > 0 &&
1885                    nbat->type[tx*NBNXN_CPU_CLUSTER_I_SIZE+na-1] == nbat->ntype-1)
1886             {
1887                 na--;
1888             }
1889
1890             if (na > 0)
1891             {
1892                 switch (nbat->XFormat)
1893                 {
1894                     case nbatX4:
1895                         /* PACK_X4==NBNXN_CPU_CLUSTER_I_SIZE, so this is simple */
1896                         calc_bounding_box_x_x4(na, nbat->x+tx*STRIDE_P4,
1897                                                bb+tx);
1898                         break;
1899                     case nbatX8:
1900                         /* PACK_X8>NBNXN_CPU_CLUSTER_I_SIZE, more complicated */
1901                         calc_bounding_box_x_x8(na, nbat->x+X8_IND_A(tx*NBNXN_CPU_CLUSTER_I_SIZE),
1902                                                bb+tx);
1903                         break;
1904                     default:
1905                         calc_bounding_box(na, nbat->xstride,
1906                                           nbat->x+tx*NBNXN_CPU_CLUSTER_I_SIZE*nbat->xstride,
1907                                           bb+tx);
1908                         break;
1909                 }
1910                 bbcz[tx*NNBSBB_D+0] = bb[tx].lower[BB_Z];
1911                 bbcz[tx*NNBSBB_D+1] = bb[tx].upper[BB_Z];
1912
1913                 /* No interaction optimization yet here */
1914                 grid->flags_simple[tx] = NBNXN_CI_DO_LJ(0) | NBNXN_CI_DO_COUL(0);
1915             }
1916             else
1917             {
1918                 grid->flags_simple[tx] = 0;
1919             }
1920         }
1921     }
1922
1923     if (grid->bSimple && nbat->XFormat == nbatX8)
1924     {
1925         combine_bounding_box_pairs(grid, grid->bb_simple);
1926     }
1927 }
1928
1929 void nbnxn_get_ncells(nbnxn_search_t nbs, int *ncx, int *ncy)
1930 {
1931     *ncx = nbs->grid[0].ncx;
1932     *ncy = nbs->grid[0].ncy;
1933 }
1934
1935 void nbnxn_get_atomorder(nbnxn_search_t nbs, int **a, int *n)
1936 {
1937     const nbnxn_grid_t *grid;
1938
1939     grid = &nbs->grid[0];
1940
1941     /* Return the atom order for the home cell (index 0) */
1942     *a  = nbs->a;
1943
1944     *n = grid->cxy_ind[grid->ncx*grid->ncy]*grid->na_sc;
1945 }
1946
1947 void nbnxn_set_atomorder(nbnxn_search_t nbs)
1948 {
1949     nbnxn_grid_t *grid;
1950     int           ao, cx, cy, cxy, cz, j;
1951
1952     /* Set the atom order for the home cell (index 0) */
1953     grid = &nbs->grid[0];
1954
1955     ao = 0;
1956     for (cx = 0; cx < grid->ncx; cx++)
1957     {
1958         for (cy = 0; cy < grid->ncy; cy++)
1959         {
1960             cxy = cx*grid->ncy + cy;
1961             j   = grid->cxy_ind[cxy]*grid->na_sc;
1962             for (cz = 0; cz < grid->cxy_na[cxy]; cz++)
1963             {
1964                 nbs->a[j]     = ao;
1965                 nbs->cell[ao] = j;
1966                 ao++;
1967                 j++;
1968             }
1969         }
1970     }
1971 }
1972
1973 /* Determines the cell range along one dimension that
1974  * the bounding box b0 - b1 sees.
1975  */
1976 static void get_cell_range(real b0, real b1,
1977                            int nc, real c0, real s, real invs,
1978                            real d2, real r2, int *cf, int *cl)
1979 {
1980     *cf = max((int)((b0 - c0)*invs), 0);
1981
1982     while (*cf > 0 && d2 + sqr((b0 - c0) - (*cf-1+1)*s) < r2)
1983     {
1984         (*cf)--;
1985     }
1986
1987     *cl = min((int)((b1 - c0)*invs), nc-1);
1988     while (*cl < nc-1 && d2 + sqr((*cl+1)*s - (b1 - c0)) < r2)
1989     {
1990         (*cl)++;
1991     }
1992 }
1993
1994 /* Reference code calculating the distance^2 between two bounding boxes */
1995 static float box_dist2(float bx0, float bx1, float by0,
1996                        float by1, float bz0, float bz1,
1997                        const nbnxn_bb_t *bb)
1998 {
1999     float d2;
2000     float dl, dh, dm, dm0;
2001
2002     d2 = 0;
2003
2004     dl  = bx0 - bb->upper[BB_X];
2005     dh  = bb->lower[BB_X] - bx1;
2006     dm  = max(dl, dh);
2007     dm0 = max(dm, 0);
2008     d2 += dm0*dm0;
2009
2010     dl  = by0 - bb->upper[BB_Y];
2011     dh  = bb->lower[BB_Y] - by1;
2012     dm  = max(dl, dh);
2013     dm0 = max(dm, 0);
2014     d2 += dm0*dm0;
2015
2016     dl  = bz0 - bb->upper[BB_Z];
2017     dh  = bb->lower[BB_Z] - bz1;
2018     dm  = max(dl, dh);
2019     dm0 = max(dm, 0);
2020     d2 += dm0*dm0;
2021
2022     return d2;
2023 }
2024
2025 /* Plain C code calculating the distance^2 between two bounding boxes */
2026 static float subc_bb_dist2(int si, const nbnxn_bb_t *bb_i_ci,
2027                            int csj, const nbnxn_bb_t *bb_j_all)
2028 {
2029     const nbnxn_bb_t *bb_i, *bb_j;
2030     float             d2;
2031     float             dl, dh, dm, dm0;
2032
2033     bb_i = bb_i_ci  +  si;
2034     bb_j = bb_j_all + csj;
2035
2036     d2 = 0;
2037
2038     dl  = bb_i->lower[BB_X] - bb_j->upper[BB_X];
2039     dh  = bb_j->lower[BB_X] - bb_i->upper[BB_X];
2040     dm  = max(dl, dh);
2041     dm0 = max(dm, 0);
2042     d2 += dm0*dm0;
2043
2044     dl  = bb_i->lower[BB_Y] - bb_j->upper[BB_Y];
2045     dh  = bb_j->lower[BB_Y] - bb_i->upper[BB_Y];
2046     dm  = max(dl, dh);
2047     dm0 = max(dm, 0);
2048     d2 += dm0*dm0;
2049
2050     dl  = bb_i->lower[BB_Z] - bb_j->upper[BB_Z];
2051     dh  = bb_j->lower[BB_Z] - bb_i->upper[BB_Z];
2052     dm  = max(dl, dh);
2053     dm0 = max(dm, 0);
2054     d2 += dm0*dm0;
2055
2056     return d2;
2057 }
2058
2059 #ifdef NBNXN_SEARCH_BB_SIMD4
2060
2061 /* 4-wide SIMD code for bb distance for bb format xyz0 */
2062 static float subc_bb_dist2_simd4(int si, const nbnxn_bb_t *bb_i_ci,
2063                                  int csj, const nbnxn_bb_t *bb_j_all)
2064 {
2065     gmx_simd4_pr bb_i_S0, bb_i_S1;
2066     gmx_simd4_pr bb_j_S0, bb_j_S1;
2067     gmx_simd4_pr dl_S;
2068     gmx_simd4_pr dh_S;
2069     gmx_simd4_pr dm_S;
2070     gmx_simd4_pr dm0_S;
2071
2072     bb_i_S0 = gmx_simd4_load_bb_pr(&bb_i_ci[si].lower[0]);
2073     bb_i_S1 = gmx_simd4_load_bb_pr(&bb_i_ci[si].upper[0]);
2074     bb_j_S0 = gmx_simd4_load_bb_pr(&bb_j_all[csj].lower[0]);
2075     bb_j_S1 = gmx_simd4_load_bb_pr(&bb_j_all[csj].upper[0]);
2076
2077     dl_S    = gmx_simd4_sub_pr(bb_i_S0, bb_j_S1);
2078     dh_S    = gmx_simd4_sub_pr(bb_j_S0, bb_i_S1);
2079
2080     dm_S    = gmx_simd4_max_pr(dl_S, dh_S);
2081     dm0_S   = gmx_simd4_max_pr(dm_S, gmx_simd4_setzero_pr());
2082
2083     return gmx_simd4_dotproduct3(dm0_S, dm0_S);
2084 }
2085
2086 /* Calculate bb bounding distances of bb_i[si,...,si+3] and store them in d2 */
2087 #define SUBC_BB_DIST2_SIMD4_XXXX_INNER(si, bb_i, d2) \
2088     {                                                \
2089         int    shi;                                  \
2090                                                  \
2091         gmx_simd4_pr dx_0, dy_0, dz_0;                       \
2092         gmx_simd4_pr dx_1, dy_1, dz_1;                       \
2093                                                  \
2094         gmx_simd4_pr mx, my, mz;                             \
2095         gmx_simd4_pr m0x, m0y, m0z;                          \
2096                                                  \
2097         gmx_simd4_pr d2x, d2y, d2z;                          \
2098         gmx_simd4_pr d2s, d2t;                              \
2099                                                  \
2100         shi = si*NNBSBB_D*DIM;                       \
2101                                                  \
2102         xi_l = gmx_simd4_load_bb_pr(bb_i+shi+0*STRIDE_PBB);   \
2103         yi_l = gmx_simd4_load_bb_pr(bb_i+shi+1*STRIDE_PBB);   \
2104         zi_l = gmx_simd4_load_bb_pr(bb_i+shi+2*STRIDE_PBB);   \
2105         xi_h = gmx_simd4_load_bb_pr(bb_i+shi+3*STRIDE_PBB);   \
2106         yi_h = gmx_simd4_load_bb_pr(bb_i+shi+4*STRIDE_PBB);   \
2107         zi_h = gmx_simd4_load_bb_pr(bb_i+shi+5*STRIDE_PBB);   \
2108                                                  \
2109         dx_0 = gmx_simd4_sub_pr(xi_l, xj_h);                \
2110         dy_0 = gmx_simd4_sub_pr(yi_l, yj_h);                \
2111         dz_0 = gmx_simd4_sub_pr(zi_l, zj_h);                \
2112                                                  \
2113         dx_1 = gmx_simd4_sub_pr(xj_l, xi_h);                \
2114         dy_1 = gmx_simd4_sub_pr(yj_l, yi_h);                \
2115         dz_1 = gmx_simd4_sub_pr(zj_l, zi_h);                \
2116                                                  \
2117         mx   = gmx_simd4_max_pr(dx_0, dx_1);                \
2118         my   = gmx_simd4_max_pr(dy_0, dy_1);                \
2119         mz   = gmx_simd4_max_pr(dz_0, dz_1);                \
2120                                                  \
2121         m0x  = gmx_simd4_max_pr(mx, zero);                  \
2122         m0y  = gmx_simd4_max_pr(my, zero);                  \
2123         m0z  = gmx_simd4_max_pr(mz, zero);                  \
2124                                                  \
2125         d2x  = gmx_simd4_mul_pr(m0x, m0x);                  \
2126         d2y  = gmx_simd4_mul_pr(m0y, m0y);                  \
2127         d2z  = gmx_simd4_mul_pr(m0z, m0z);                  \
2128                                                  \
2129         d2s  = gmx_simd4_add_pr(d2x, d2y);                  \
2130         d2t  = gmx_simd4_add_pr(d2s, d2z);                  \
2131                                                  \
2132         gmx_simd4_store_pr(d2+si, d2t);                     \
2133     }
2134
2135 /* 4-wide SIMD code for nsi bb distances for bb format xxxxyyyyzzzz */
2136 static void subc_bb_dist2_simd4_xxxx(const float *bb_j,
2137                                      int nsi, const float *bb_i,
2138                                      float *d2)
2139 {
2140     gmx_simd4_pr xj_l, yj_l, zj_l;
2141     gmx_simd4_pr xj_h, yj_h, zj_h;
2142     gmx_simd4_pr xi_l, yi_l, zi_l;
2143     gmx_simd4_pr xi_h, yi_h, zi_h;
2144
2145     gmx_simd4_pr zero;
2146
2147     zero = gmx_simd4_setzero_pr();
2148
2149     xj_l = gmx_simd4_set1_pr(bb_j[0*STRIDE_PBB]);
2150     yj_l = gmx_simd4_set1_pr(bb_j[1*STRIDE_PBB]);
2151     zj_l = gmx_simd4_set1_pr(bb_j[2*STRIDE_PBB]);
2152     xj_h = gmx_simd4_set1_pr(bb_j[3*STRIDE_PBB]);
2153     yj_h = gmx_simd4_set1_pr(bb_j[4*STRIDE_PBB]);
2154     zj_h = gmx_simd4_set1_pr(bb_j[5*STRIDE_PBB]);
2155
2156     /* Here we "loop" over si (0,STRIDE_PBB) from 0 to nsi with step STRIDE_PBB.
2157      * But as we know the number of iterations is 1 or 2, we unroll manually.
2158      */
2159     SUBC_BB_DIST2_SIMD4_XXXX_INNER(0, bb_i, d2);
2160     if (STRIDE_PBB < nsi)
2161     {
2162         SUBC_BB_DIST2_SIMD4_XXXX_INNER(STRIDE_PBB, bb_i, d2);
2163     }
2164 }
2165
2166 #endif /* NBNXN_SEARCH_BB_SIMD4 */
2167
2168 /* Plain C function which determines if any atom pair between two cells
2169  * is within distance sqrt(rl2).
2170  */
2171 static gmx_bool subc_in_range_x(int na_c,
2172                                 int si, const real *x_i,
2173                                 int csj, int stride, const real *x_j,
2174                                 real rl2)
2175 {
2176     int  i, j, i0, j0;
2177     real d2;
2178
2179     for (i = 0; i < na_c; i++)
2180     {
2181         i0 = (si*na_c + i)*DIM;
2182         for (j = 0; j < na_c; j++)
2183         {
2184             j0 = (csj*na_c + j)*stride;
2185
2186             d2 = sqr(x_i[i0  ] - x_j[j0  ]) +
2187                 sqr(x_i[i0+1] - x_j[j0+1]) +
2188                 sqr(x_i[i0+2] - x_j[j0+2]);
2189
2190             if (d2 < rl2)
2191             {
2192                 return TRUE;
2193             }
2194         }
2195     }
2196
2197     return FALSE;
2198 }
2199
2200 #ifdef NBNXN_SEARCH_SIMD4_FLOAT_X_BB
2201 /* When we make seperate single/double precision SIMD vector operation
2202  * include files, this function should be moved there (also using FMA).
2203  */
2204 static inline gmx_simd4_pr
2205 gmx_simd4_calc_rsq_pr(gmx_simd4_pr x, gmx_simd4_pr y, gmx_simd4_pr z)
2206 {
2207     return gmx_simd4_add_pr( gmx_simd4_add_pr( gmx_simd4_mul_pr(x, x), gmx_simd4_mul_pr(y, y) ), gmx_simd4_mul_pr(z, z) );
2208 }
2209
2210 /* 4-wide SIMD function which determines if any atom pair between two cells,
2211  * both with 8 atoms, is within distance sqrt(rl2).
2212  * Using 8-wide AVX is not faster on Intel Sandy Bridge.
2213  */
2214 static gmx_bool subc_in_range_simd4(int na_c,
2215                                     int si, const real *x_i,
2216                                     int csj, int stride, const real *x_j,
2217                                     real rl2)
2218 {
2219     gmx_simd4_pr ix_S0, iy_S0, iz_S0;
2220     gmx_simd4_pr ix_S1, iy_S1, iz_S1;
2221
2222     gmx_simd4_pr rc2_S;
2223
2224     int    dim_stride;
2225     int    j0, j1;
2226
2227     rc2_S   = gmx_simd4_set1_pr(rl2);
2228
2229     dim_stride = NBNXN_GPU_CLUSTER_SIZE/STRIDE_PBB*DIM;
2230     ix_S0      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+0)*STRIDE_PBB);
2231     iy_S0      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+1)*STRIDE_PBB);
2232     iz_S0      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+2)*STRIDE_PBB);
2233     ix_S1      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+3)*STRIDE_PBB);
2234     iy_S1      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+4)*STRIDE_PBB);
2235     iz_S1      = gmx_simd4_load_bb_pr(x_i+(si*dim_stride+5)*STRIDE_PBB);
2236
2237     /* We loop from the outer to the inner particles to maximize
2238      * the chance that we find a pair in range quickly and return.
2239      */
2240     j0 = csj*na_c;
2241     j1 = j0 + na_c - 1;
2242     while (j0 < j1)
2243     {
2244         gmx_simd4_pr jx0_S, jy0_S, jz0_S;
2245         gmx_simd4_pr jx1_S, jy1_S, jz1_S;
2246
2247         gmx_simd4_pr dx_S0, dy_S0, dz_S0;
2248         gmx_simd4_pr dx_S1, dy_S1, dz_S1;
2249         gmx_simd4_pr dx_S2, dy_S2, dz_S2;
2250         gmx_simd4_pr dx_S3, dy_S3, dz_S3;
2251
2252         gmx_simd4_pr rsq_S0;
2253         gmx_simd4_pr rsq_S1;
2254         gmx_simd4_pr rsq_S2;
2255         gmx_simd4_pr rsq_S3;
2256
2257         gmx_simd4_pb wco_S0;
2258         gmx_simd4_pb wco_S1;
2259         gmx_simd4_pb wco_S2;
2260         gmx_simd4_pb wco_S3;
2261         gmx_simd4_pb wco_any_S01, wco_any_S23, wco_any_S;
2262
2263         jx0_S = gmx_simd4_set1_pr(x_j[j0*stride+0]);
2264         jy0_S = gmx_simd4_set1_pr(x_j[j0*stride+1]);
2265         jz0_S = gmx_simd4_set1_pr(x_j[j0*stride+2]);
2266
2267         jx1_S = gmx_simd4_set1_pr(x_j[j1*stride+0]);
2268         jy1_S = gmx_simd4_set1_pr(x_j[j1*stride+1]);
2269         jz1_S = gmx_simd4_set1_pr(x_j[j1*stride+2]);
2270
2271         /* Calculate distance */
2272         dx_S0            = gmx_simd4_sub_pr(ix_S0, jx0_S);
2273         dy_S0            = gmx_simd4_sub_pr(iy_S0, jy0_S);
2274         dz_S0            = gmx_simd4_sub_pr(iz_S0, jz0_S);
2275         dx_S1            = gmx_simd4_sub_pr(ix_S1, jx0_S);
2276         dy_S1            = gmx_simd4_sub_pr(iy_S1, jy0_S);
2277         dz_S1            = gmx_simd4_sub_pr(iz_S1, jz0_S);
2278         dx_S2            = gmx_simd4_sub_pr(ix_S0, jx1_S);
2279         dy_S2            = gmx_simd4_sub_pr(iy_S0, jy1_S);
2280         dz_S2            = gmx_simd4_sub_pr(iz_S0, jz1_S);
2281         dx_S3            = gmx_simd4_sub_pr(ix_S1, jx1_S);
2282         dy_S3            = gmx_simd4_sub_pr(iy_S1, jy1_S);
2283         dz_S3            = gmx_simd4_sub_pr(iz_S1, jz1_S);
2284
2285         /* rsq = dx*dx+dy*dy+dz*dz */
2286         rsq_S0           = gmx_simd4_calc_rsq_pr(dx_S0, dy_S0, dz_S0);
2287         rsq_S1           = gmx_simd4_calc_rsq_pr(dx_S1, dy_S1, dz_S1);
2288         rsq_S2           = gmx_simd4_calc_rsq_pr(dx_S2, dy_S2, dz_S2);
2289         rsq_S3           = gmx_simd4_calc_rsq_pr(dx_S3, dy_S3, dz_S3);
2290
2291         wco_S0           = gmx_simd4_cmplt_pr(rsq_S0, rc2_S);
2292         wco_S1           = gmx_simd4_cmplt_pr(rsq_S1, rc2_S);
2293         wco_S2           = gmx_simd4_cmplt_pr(rsq_S2, rc2_S);
2294         wco_S3           = gmx_simd4_cmplt_pr(rsq_S3, rc2_S);
2295
2296         wco_any_S01      = gmx_simd4_or_pb(wco_S0, wco_S1);
2297         wco_any_S23      = gmx_simd4_or_pb(wco_S2, wco_S3);
2298         wco_any_S        = gmx_simd4_or_pb(wco_any_S01, wco_any_S23);
2299
2300         if (gmx_simd4_anytrue_pb(wco_any_S))
2301         {
2302             return TRUE;
2303         }
2304
2305         j0++;
2306         j1--;
2307     }
2308     return FALSE;
2309
2310 }
2311 #endif
2312
2313
2314 /* Returns the j sub-cell for index cj_ind */
2315 static int nbl_cj(const nbnxn_pairlist_t *nbl, int cj_ind)
2316 {
2317     return nbl->cj4[cj_ind >> NBNXN_GPU_JGROUP_SIZE_2LOG].cj[cj_ind & (NBNXN_GPU_JGROUP_SIZE - 1)];
2318 }
2319
2320 /* Returns the i-interaction mask of the j sub-cell for index cj_ind */
2321 static unsigned nbl_imask0(const nbnxn_pairlist_t *nbl, int cj_ind)
2322 {
2323     return nbl->cj4[cj_ind >> NBNXN_GPU_JGROUP_SIZE_2LOG].imei[0].imask;
2324 }
2325
2326 /* Ensures there is enough space for extra extra exclusion masks */
2327 static void check_excl_space(nbnxn_pairlist_t *nbl, int extra)
2328 {
2329     if (nbl->nexcl+extra > nbl->excl_nalloc)
2330     {
2331         nbl->excl_nalloc = over_alloc_small(nbl->nexcl+extra);
2332         nbnxn_realloc_void((void **)&nbl->excl,
2333                            nbl->nexcl*sizeof(*nbl->excl),
2334                            nbl->excl_nalloc*sizeof(*nbl->excl),
2335                            nbl->alloc, nbl->free);
2336     }
2337 }
2338
2339 /* Ensures there is enough space for ncell extra j-cells in the list */
2340 static void check_subcell_list_space_simple(nbnxn_pairlist_t *nbl,
2341                                             int               ncell)
2342 {
2343     int cj_max;
2344
2345     cj_max = nbl->ncj + ncell;
2346
2347     if (cj_max > nbl->cj_nalloc)
2348     {
2349         nbl->cj_nalloc = over_alloc_small(cj_max);
2350         nbnxn_realloc_void((void **)&nbl->cj,
2351                            nbl->ncj*sizeof(*nbl->cj),
2352                            nbl->cj_nalloc*sizeof(*nbl->cj),
2353                            nbl->alloc, nbl->free);
2354     }
2355 }
2356
2357 /* Ensures there is enough space for ncell extra j-subcells in the list */
2358 static void check_subcell_list_space_supersub(nbnxn_pairlist_t *nbl,
2359                                               int               nsupercell)
2360 {
2361     int ncj4_max, j4, j, w, t;
2362
2363 #define NWARP       2
2364 #define WARP_SIZE  32
2365
2366     /* We can have maximally nsupercell*GPU_NSUBCELL sj lists */
2367     /* We can store 4 j-subcell - i-supercell pairs in one struct.
2368      * since we round down, we need one extra entry.
2369      */
2370     ncj4_max = ((nbl->work->cj_ind + nsupercell*GPU_NSUBCELL + NBNXN_GPU_JGROUP_SIZE - 1) >> NBNXN_GPU_JGROUP_SIZE_2LOG);
2371
2372     if (ncj4_max > nbl->cj4_nalloc)
2373     {
2374         nbl->cj4_nalloc = over_alloc_small(ncj4_max);
2375         nbnxn_realloc_void((void **)&nbl->cj4,
2376                            nbl->work->cj4_init*sizeof(*nbl->cj4),
2377                            nbl->cj4_nalloc*sizeof(*nbl->cj4),
2378                            nbl->alloc, nbl->free);
2379     }
2380
2381     if (ncj4_max > nbl->work->cj4_init)
2382     {
2383         for (j4 = nbl->work->cj4_init; j4 < ncj4_max; j4++)
2384         {
2385             /* No i-subcells and no excl's in the list initially */
2386             for (w = 0; w < NWARP; w++)
2387             {
2388                 nbl->cj4[j4].imei[w].imask    = 0U;
2389                 nbl->cj4[j4].imei[w].excl_ind = 0;
2390
2391             }
2392         }
2393         nbl->work->cj4_init = ncj4_max;
2394     }
2395 }
2396
2397 /* Set all excl masks for one GPU warp no exclusions */
2398 static void set_no_excls(nbnxn_excl_t *excl)
2399 {
2400     int t;
2401
2402     for (t = 0; t < WARP_SIZE; t++)
2403     {
2404         /* Turn all interaction bits on */
2405         excl->pair[t] = NBNXN_INTERACTION_MASK_ALL;
2406     }
2407 }
2408
2409 /* Initializes a single nbnxn_pairlist_t data structure */
2410 static void nbnxn_init_pairlist(nbnxn_pairlist_t *nbl,
2411                                 gmx_bool          bSimple,
2412                                 nbnxn_alloc_t    *alloc,
2413                                 nbnxn_free_t     *free)
2414 {
2415     if (alloc == NULL)
2416     {
2417         nbl->alloc = nbnxn_alloc_aligned;
2418     }
2419     else
2420     {
2421         nbl->alloc = alloc;
2422     }
2423     if (free == NULL)
2424     {
2425         nbl->free = nbnxn_free_aligned;
2426     }
2427     else
2428     {
2429         nbl->free = free;
2430     }
2431
2432     nbl->bSimple     = bSimple;
2433     nbl->na_sc       = 0;
2434     nbl->na_ci       = 0;
2435     nbl->na_cj       = 0;
2436     nbl->nci         = 0;
2437     nbl->ci          = NULL;
2438     nbl->ci_nalloc   = 0;
2439     nbl->ncj         = 0;
2440     nbl->cj          = NULL;
2441     nbl->cj_nalloc   = 0;
2442     nbl->ncj4        = 0;
2443     /* We need one element extra in sj, so alloc initially with 1 */
2444     nbl->cj4_nalloc  = 0;
2445     nbl->cj4         = NULL;
2446     nbl->nci_tot     = 0;
2447
2448     if (!nbl->bSimple)
2449     {
2450         nbl->excl        = NULL;
2451         nbl->excl_nalloc = 0;
2452         nbl->nexcl       = 0;
2453         check_excl_space(nbl, 1);
2454         nbl->nexcl       = 1;
2455         set_no_excls(&nbl->excl[0]);
2456     }
2457
2458     snew(nbl->work, 1);
2459     if (nbl->bSimple)
2460     {
2461         snew_aligned(nbl->work->bb_ci, 1, NBNXN_SEARCH_BB_MEM_ALIGN);
2462     }
2463     else
2464     {
2465 #ifdef NBNXN_BBXXXX
2466         snew_aligned(nbl->work->pbb_ci, GPU_NSUBCELL/STRIDE_PBB*NNBSBB_XXXX, NBNXN_SEARCH_BB_MEM_ALIGN);
2467 #else
2468         snew_aligned(nbl->work->bb_ci, GPU_NSUBCELL, NBNXN_SEARCH_BB_MEM_ALIGN);
2469 #endif
2470     }
2471     snew_aligned(nbl->work->x_ci, NBNXN_NA_SC_MAX*DIM, NBNXN_SEARCH_BB_MEM_ALIGN);
2472 #ifdef GMX_NBNXN_SIMD
2473     snew_aligned(nbl->work->x_ci_simd_4xn, 1, NBNXN_MEM_ALIGN);
2474     snew_aligned(nbl->work->x_ci_simd_2xnn, 1, NBNXN_MEM_ALIGN);
2475 #endif
2476     snew_aligned(nbl->work->d2, GPU_NSUBCELL, NBNXN_SEARCH_BB_MEM_ALIGN);
2477
2478     nbl->work->sort            = NULL;
2479     nbl->work->sort_nalloc     = 0;
2480     nbl->work->sci_sort        = NULL;
2481     nbl->work->sci_sort_nalloc = 0;
2482 }
2483
2484 void nbnxn_init_pairlist_set(nbnxn_pairlist_set_t *nbl_list,
2485                              gmx_bool bSimple, gmx_bool bCombined,
2486                              nbnxn_alloc_t *alloc,
2487                              nbnxn_free_t  *free)
2488 {
2489     int i;
2490
2491     nbl_list->bSimple   = bSimple;
2492     nbl_list->bCombined = bCombined;
2493
2494     nbl_list->nnbl = gmx_omp_nthreads_get(emntNonbonded);
2495
2496     if (!nbl_list->bCombined &&
2497         nbl_list->nnbl > NBNXN_BUFFERFLAG_MAX_THREADS)
2498     {
2499         gmx_fatal(FARGS, "%d OpenMP threads were requested. Since the non-bonded force buffer reduction is prohibitively slow with more than %d threads, we do not allow this. Use %d or less OpenMP threads.",
2500                   nbl_list->nnbl, NBNXN_BUFFERFLAG_MAX_THREADS, NBNXN_BUFFERFLAG_MAX_THREADS);
2501     }
2502
2503     snew(nbl_list->nbl, nbl_list->nnbl);
2504     /* Execute in order to avoid memory interleaving between threads */
2505 #pragma omp parallel for num_threads(nbl_list->nnbl) schedule(static)
2506     for (i = 0; i < nbl_list->nnbl; i++)
2507     {
2508         /* Allocate the nblist data structure locally on each thread
2509          * to optimize memory access for NUMA architectures.
2510          */
2511         snew(nbl_list->nbl[i], 1);
2512
2513         /* Only list 0 is used on the GPU, use normal allocation for i>0 */
2514         if (i == 0)
2515         {
2516             nbnxn_init_pairlist(nbl_list->nbl[i], nbl_list->bSimple, alloc, free);
2517         }
2518         else
2519         {
2520             nbnxn_init_pairlist(nbl_list->nbl[i], nbl_list->bSimple, NULL, NULL);
2521         }
2522     }
2523 }
2524
2525 /* Print statistics of a pair list, used for debug output */
2526 static void print_nblist_statistics_simple(FILE *fp, const nbnxn_pairlist_t *nbl,
2527                                            const nbnxn_search_t nbs, real rl)
2528 {
2529     const nbnxn_grid_t *grid;
2530     int                 cs[SHIFTS];
2531     int                 s, i, j;
2532     int                 npexcl;
2533
2534     /* This code only produces correct statistics with domain decomposition */
2535     grid = &nbs->grid[0];
2536
2537     fprintf(fp, "nbl nci %d ncj %d\n",
2538             nbl->nci, nbl->ncj);
2539     fprintf(fp, "nbl na_sc %d rl %g ncp %d per cell %.1f atoms %.1f ratio %.2f\n",
2540             nbl->na_sc, rl, nbl->ncj, nbl->ncj/(double)grid->nc,
2541             nbl->ncj/(double)grid->nc*grid->na_sc,
2542             nbl->ncj/(double)grid->nc*grid->na_sc/(0.5*4.0/3.0*M_PI*rl*rl*rl*grid->nc*grid->na_sc/det(nbs->box)));
2543
2544     fprintf(fp, "nbl average j cell list length %.1f\n",
2545             0.25*nbl->ncj/(double)nbl->nci);
2546
2547     for (s = 0; s < SHIFTS; s++)
2548     {
2549         cs[s] = 0;
2550     }
2551     npexcl = 0;
2552     for (i = 0; i < nbl->nci; i++)
2553     {
2554         cs[nbl->ci[i].shift & NBNXN_CI_SHIFT] +=
2555             nbl->ci[i].cj_ind_end - nbl->ci[i].cj_ind_start;
2556
2557         j = nbl->ci[i].cj_ind_start;
2558         while (j < nbl->ci[i].cj_ind_end &&
2559                nbl->cj[j].excl != NBNXN_INTERACTION_MASK_ALL)
2560         {
2561             npexcl++;
2562             j++;
2563         }
2564     }
2565     fprintf(fp, "nbl cell pairs, total: %d excl: %d %.1f%%\n",
2566             nbl->ncj, npexcl, 100*npexcl/(double)nbl->ncj);
2567     for (s = 0; s < SHIFTS; s++)
2568     {
2569         if (cs[s] > 0)
2570         {
2571             fprintf(fp, "nbl shift %2d ncj %3d\n", s, cs[s]);
2572         }
2573     }
2574 }
2575
2576 /* Print statistics of a pair lists, used for debug output */
2577 static void print_nblist_statistics_supersub(FILE *fp, const nbnxn_pairlist_t *nbl,
2578                                              const nbnxn_search_t nbs, real rl)
2579 {
2580     const nbnxn_grid_t *grid;
2581     int                 i, j4, j, si, b;
2582     int                 c[GPU_NSUBCELL+1];
2583
2584     /* This code only produces correct statistics with domain decomposition */
2585     grid = &nbs->grid[0];
2586
2587     fprintf(fp, "nbl nsci %d ncj4 %d nsi %d excl4 %d\n",
2588             nbl->nsci, nbl->ncj4, nbl->nci_tot, nbl->nexcl);
2589     fprintf(fp, "nbl na_c %d rl %g ncp %d per cell %.1f atoms %.1f ratio %.2f\n",
2590             nbl->na_ci, rl, nbl->nci_tot, nbl->nci_tot/(double)grid->nsubc_tot,
2591             nbl->nci_tot/(double)grid->nsubc_tot*grid->na_c,
2592             nbl->nci_tot/(double)grid->nsubc_tot*grid->na_c/(0.5*4.0/3.0*M_PI*rl*rl*rl*grid->nsubc_tot*grid->na_c/det(nbs->box)));
2593
2594     fprintf(fp, "nbl average j super cell list length %.1f\n",
2595             0.25*nbl->ncj4/(double)nbl->nsci);
2596     fprintf(fp, "nbl average i sub cell list length %.1f\n",
2597             nbl->nci_tot/((double)nbl->ncj4));
2598
2599     for (si = 0; si <= GPU_NSUBCELL; si++)
2600     {
2601         c[si] = 0;
2602     }
2603     for (i = 0; i < nbl->nsci; i++)
2604     {
2605         for (j4 = nbl->sci[i].cj4_ind_start; j4 < nbl->sci[i].cj4_ind_end; j4++)
2606         {
2607             for (j = 0; j < NBNXN_GPU_JGROUP_SIZE; j++)
2608             {
2609                 b = 0;
2610                 for (si = 0; si < GPU_NSUBCELL; si++)
2611                 {
2612                     if (nbl->cj4[j4].imei[0].imask & (1U << (j*GPU_NSUBCELL + si)))
2613                     {
2614                         b++;
2615                     }
2616                 }
2617                 c[b]++;
2618             }
2619         }
2620     }
2621     for (b = 0; b <= GPU_NSUBCELL; b++)
2622     {
2623         fprintf(fp, "nbl j-list #i-subcell %d %7d %4.1f\n",
2624                 b, c[b], 100.0*c[b]/(double)(nbl->ncj4*NBNXN_GPU_JGROUP_SIZE));
2625     }
2626 }
2627
2628 /* Returns a pointer to the exclusion mask for cj4-unit cj4, warp warp */
2629 static void low_get_nbl_exclusions(nbnxn_pairlist_t *nbl, int cj4,
2630                                    int warp, nbnxn_excl_t **excl)
2631 {
2632     if (nbl->cj4[cj4].imei[warp].excl_ind == 0)
2633     {
2634         /* No exclusions set, make a new list entry */
2635         nbl->cj4[cj4].imei[warp].excl_ind = nbl->nexcl;
2636         nbl->nexcl++;
2637         *excl = &nbl->excl[nbl->cj4[cj4].imei[warp].excl_ind];
2638         set_no_excls(*excl);
2639     }
2640     else
2641     {
2642         /* We already have some exclusions, new ones can be added to the list */
2643         *excl = &nbl->excl[nbl->cj4[cj4].imei[warp].excl_ind];
2644     }
2645 }
2646
2647 /* Returns a pointer to the exclusion mask for cj4-unit cj4, warp warp,
2648  * allocates extra memory, if necessary.
2649  */
2650 static void get_nbl_exclusions_1(nbnxn_pairlist_t *nbl, int cj4,
2651                                  int warp, nbnxn_excl_t **excl)
2652 {
2653     if (nbl->cj4[cj4].imei[warp].excl_ind == 0)
2654     {
2655         /* We need to make a new list entry, check if we have space */
2656         check_excl_space(nbl, 1);
2657     }
2658     low_get_nbl_exclusions(nbl, cj4, warp, excl);
2659 }
2660
2661 /* Returns pointers to the exclusion mask for cj4-unit cj4 for both warps,
2662  * allocates extra memory, if necessary.
2663  */
2664 static void get_nbl_exclusions_2(nbnxn_pairlist_t *nbl, int cj4,
2665                                  nbnxn_excl_t **excl_w0,
2666                                  nbnxn_excl_t **excl_w1)
2667 {
2668     /* Check for space we might need */
2669     check_excl_space(nbl, 2);
2670
2671     low_get_nbl_exclusions(nbl, cj4, 0, excl_w0);
2672     low_get_nbl_exclusions(nbl, cj4, 1, excl_w1);
2673 }
2674
2675 /* Sets the self exclusions i=j and pair exclusions i>j */
2676 static void set_self_and_newton_excls_supersub(nbnxn_pairlist_t *nbl,
2677                                                int cj4_ind, int sj_offset,
2678                                                int si)
2679 {
2680     nbnxn_excl_t *excl[2];
2681     int           ei, ej, w;
2682
2683     /* Here we only set the set self and double pair exclusions */
2684
2685     get_nbl_exclusions_2(nbl, cj4_ind, &excl[0], &excl[1]);
2686
2687     /* Only minor < major bits set */
2688     for (ej = 0; ej < nbl->na_ci; ej++)
2689     {
2690         w = (ej>>2);
2691         for (ei = ej; ei < nbl->na_ci; ei++)
2692         {
2693             excl[w]->pair[(ej & (NBNXN_GPU_JGROUP_SIZE-1))*nbl->na_ci + ei] &=
2694                 ~(1U << (sj_offset*GPU_NSUBCELL + si));
2695         }
2696     }
2697 }
2698
2699 /* Returns a diagonal or off-diagonal interaction mask for plain C lists */
2700 static unsigned int get_imask(gmx_bool rdiag, int ci, int cj)
2701 {
2702     return (rdiag && ci == cj ? NBNXN_INTERACTION_MASK_DIAG : NBNXN_INTERACTION_MASK_ALL);
2703 }
2704
2705 /* Returns a diagonal or off-diagonal interaction mask for cj-size=2 */
2706 static unsigned int get_imask_simd_j2(gmx_bool rdiag, int ci, int cj)
2707 {
2708     return (rdiag && ci*2 == cj ? NBNXN_INTERACTION_MASK_DIAG_J2_0 :
2709             (rdiag && ci*2+1 == cj ? NBNXN_INTERACTION_MASK_DIAG_J2_1 :
2710              NBNXN_INTERACTION_MASK_ALL));
2711 }
2712
2713 /* Returns a diagonal or off-diagonal interaction mask for cj-size=4 */
2714 static unsigned int get_imask_simd_j4(gmx_bool rdiag, int ci, int cj)
2715 {
2716     return (rdiag && ci == cj ? NBNXN_INTERACTION_MASK_DIAG : NBNXN_INTERACTION_MASK_ALL);
2717 }
2718
2719 /* Returns a diagonal or off-diagonal interaction mask for cj-size=8 */
2720 static unsigned int get_imask_simd_j8(gmx_bool rdiag, int ci, int cj)
2721 {
2722     return (rdiag && ci == cj*2 ? NBNXN_INTERACTION_MASK_DIAG_J8_0 :
2723             (rdiag && ci == cj*2+1 ? NBNXN_INTERACTION_MASK_DIAG_J8_1 :
2724              NBNXN_INTERACTION_MASK_ALL));
2725 }
2726
2727 #ifdef GMX_NBNXN_SIMD
2728 #if GMX_SIMD_WIDTH_HERE == 2
2729 #define get_imask_simd_4xn  get_imask_simd_j2
2730 #endif
2731 #if GMX_SIMD_WIDTH_HERE == 4
2732 #define get_imask_simd_4xn  get_imask_simd_j4
2733 #endif
2734 #if GMX_SIMD_WIDTH_HERE == 8
2735 #define get_imask_simd_4xn  get_imask_simd_j8
2736 #define get_imask_simd_2xnn get_imask_simd_j4
2737 #endif
2738 #if GMX_SIMD_WIDTH_HERE == 16
2739 #define get_imask_simd_2xnn get_imask_simd_j8
2740 #endif
2741 #endif
2742
2743 /* Plain C code for making a pair list of cell ci vs cell cjf-cjl.
2744  * Checks bounding box distances and possibly atom pair distances.
2745  */
2746 static void make_cluster_list_simple(const nbnxn_grid_t *gridj,
2747                                      nbnxn_pairlist_t *nbl,
2748                                      int ci, int cjf, int cjl,
2749                                      gmx_bool remove_sub_diag,
2750                                      const real *x_j,
2751                                      real rl2, float rbb2,
2752                                      int *ndistc)
2753 {
2754     const nbnxn_list_work_t *work;
2755
2756     const nbnxn_bb_t        *bb_ci;
2757     const real              *x_ci;
2758
2759     gmx_bool                 InRange;
2760     real                     d2;
2761     int                      cjf_gl, cjl_gl, cj;
2762
2763     work = nbl->work;
2764
2765     bb_ci = nbl->work->bb_ci;
2766     x_ci  = nbl->work->x_ci;
2767
2768     InRange = FALSE;
2769     while (!InRange && cjf <= cjl)
2770     {
2771         d2       = subc_bb_dist2(0, bb_ci, cjf, gridj->bb);
2772         *ndistc += 2;
2773
2774         /* Check if the distance is within the distance where
2775          * we use only the bounding box distance rbb,
2776          * or within the cut-off and there is at least one atom pair
2777          * within the cut-off.
2778          */
2779         if (d2 < rbb2)
2780         {
2781             InRange = TRUE;
2782         }
2783         else if (d2 < rl2)
2784         {
2785             int i, j;
2786
2787             cjf_gl = gridj->cell0 + cjf;
2788             for (i = 0; i < NBNXN_CPU_CLUSTER_I_SIZE && !InRange; i++)
2789             {
2790                 for (j = 0; j < NBNXN_CPU_CLUSTER_I_SIZE; j++)
2791                 {
2792                     InRange = InRange ||
2793                         (sqr(x_ci[i*STRIDE_XYZ+XX] - x_j[(cjf_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+XX]) +
2794                          sqr(x_ci[i*STRIDE_XYZ+YY] - x_j[(cjf_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+YY]) +
2795                          sqr(x_ci[i*STRIDE_XYZ+ZZ] - x_j[(cjf_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+ZZ]) < rl2);
2796                 }
2797             }
2798             *ndistc += NBNXN_CPU_CLUSTER_I_SIZE*NBNXN_CPU_CLUSTER_I_SIZE;
2799         }
2800         if (!InRange)
2801         {
2802             cjf++;
2803         }
2804     }
2805     if (!InRange)
2806     {
2807         return;
2808     }
2809
2810     InRange = FALSE;
2811     while (!InRange && cjl > cjf)
2812     {
2813         d2       = subc_bb_dist2(0, bb_ci, cjl, gridj->bb);
2814         *ndistc += 2;
2815
2816         /* Check if the distance is within the distance where
2817          * we use only the bounding box distance rbb,
2818          * or within the cut-off and there is at least one atom pair
2819          * within the cut-off.
2820          */
2821         if (d2 < rbb2)
2822         {
2823             InRange = TRUE;
2824         }
2825         else if (d2 < rl2)
2826         {
2827             int i, j;
2828
2829             cjl_gl = gridj->cell0 + cjl;
2830             for (i = 0; i < NBNXN_CPU_CLUSTER_I_SIZE && !InRange; i++)
2831             {
2832                 for (j = 0; j < NBNXN_CPU_CLUSTER_I_SIZE; j++)
2833                 {
2834                     InRange = InRange ||
2835                         (sqr(x_ci[i*STRIDE_XYZ+XX] - x_j[(cjl_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+XX]) +
2836                          sqr(x_ci[i*STRIDE_XYZ+YY] - x_j[(cjl_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+YY]) +
2837                          sqr(x_ci[i*STRIDE_XYZ+ZZ] - x_j[(cjl_gl*NBNXN_CPU_CLUSTER_I_SIZE+j)*STRIDE_XYZ+ZZ]) < rl2);
2838                 }
2839             }
2840             *ndistc += NBNXN_CPU_CLUSTER_I_SIZE*NBNXN_CPU_CLUSTER_I_SIZE;
2841         }
2842         if (!InRange)
2843         {
2844             cjl--;
2845         }
2846     }
2847
2848     if (cjf <= cjl)
2849     {
2850         for (cj = cjf; cj <= cjl; cj++)
2851         {
2852             /* Store cj and the interaction mask */
2853             nbl->cj[nbl->ncj].cj   = gridj->cell0 + cj;
2854             nbl->cj[nbl->ncj].excl = get_imask(remove_sub_diag, ci, cj);
2855             nbl->ncj++;
2856         }
2857         /* Increase the closing index in i super-cell list */
2858         nbl->ci[nbl->nci].cj_ind_end = nbl->ncj;
2859     }
2860 }
2861
2862 #ifdef GMX_NBNXN_SIMD_4XN
2863 #include "nbnxn_search_simd_4xn.h"
2864 #endif
2865 #ifdef GMX_NBNXN_SIMD_2XNN
2866 #include "nbnxn_search_simd_2xnn.h"
2867 #endif
2868
2869 /* Plain C or SIMD4 code for making a pair list of super-cell sci vs scj.
2870  * Checks bounding box distances and possibly atom pair distances.
2871  */
2872 static void make_cluster_list_supersub(const nbnxn_grid_t *gridi,
2873                                        const nbnxn_grid_t *gridj,
2874                                        nbnxn_pairlist_t *nbl,
2875                                        int sci, int scj,
2876                                        gmx_bool sci_equals_scj,
2877                                        int stride, const real *x,
2878                                        real rl2, float rbb2,
2879                                        int *ndistc)
2880 {
2881     int               na_c;
2882     int               npair;
2883     int               cjo, ci1, ci, cj, cj_gl;
2884     int               cj4_ind, cj_offset;
2885     unsigned          imask;
2886     nbnxn_cj4_t      *cj4;
2887 #ifdef NBNXN_BBXXXX
2888     const float      *pbb_ci;
2889 #else
2890     const nbnxn_bb_t *bb_ci;
2891 #endif
2892     const real       *x_ci;
2893     float            *d2l, d2;
2894     int               w;
2895 #define PRUNE_LIST_CPU_ONE
2896 #ifdef PRUNE_LIST_CPU_ONE
2897     int  ci_last = -1;
2898 #endif
2899
2900     d2l = nbl->work->d2;
2901
2902 #ifdef NBNXN_BBXXXX
2903     pbb_ci = nbl->work->pbb_ci;
2904 #else
2905     bb_ci  = nbl->work->bb_ci;
2906 #endif
2907     x_ci   = nbl->work->x_ci;
2908
2909     na_c = gridj->na_c;
2910
2911     for (cjo = 0; cjo < gridj->nsubc[scj]; cjo++)
2912     {
2913         cj4_ind   = (nbl->work->cj_ind >> NBNXN_GPU_JGROUP_SIZE_2LOG);
2914         cj_offset = nbl->work->cj_ind - cj4_ind*NBNXN_GPU_JGROUP_SIZE;
2915         cj4       = &nbl->cj4[cj4_ind];
2916
2917         cj = scj*GPU_NSUBCELL + cjo;
2918
2919         cj_gl = gridj->cell0*GPU_NSUBCELL + cj;
2920
2921         /* Initialize this j-subcell i-subcell list */
2922         cj4->cj[cj_offset] = cj_gl;
2923         imask              = 0;
2924
2925         if (sci_equals_scj)
2926         {
2927             ci1 = cjo + 1;
2928         }
2929         else
2930         {
2931             ci1 = gridi->nsubc[sci];
2932         }
2933
2934 #ifdef NBNXN_BBXXXX
2935         /* Determine all ci1 bb distances in one call with SIMD4 */
2936         subc_bb_dist2_simd4_xxxx(gridj->pbb+(cj>>STRIDE_PBB_2LOG)*NNBSBB_XXXX+(cj & (STRIDE_PBB-1)),
2937                                ci1, pbb_ci, d2l);
2938         *ndistc += na_c*2;
2939 #endif
2940
2941         npair = 0;
2942         /* We use a fixed upper-bound instead of ci1 to help optimization */
2943         for (ci = 0; ci < GPU_NSUBCELL; ci++)
2944         {
2945             if (ci == ci1)
2946             {
2947                 break;
2948             }
2949
2950 #ifndef NBNXN_BBXXXX
2951             /* Determine the bb distance between ci and cj */
2952             d2l[ci]  = subc_bb_dist2(ci, bb_ci, cj, gridj->bb);
2953             *ndistc += 2;
2954 #endif
2955             d2 = d2l[ci];
2956
2957 #ifdef PRUNE_LIST_CPU_ALL
2958             /* Check if the distance is within the distance where
2959              * we use only the bounding box distance rbb,
2960              * or within the cut-off and there is at least one atom pair
2961              * within the cut-off. This check is very costly.
2962              */
2963             *ndistc += na_c*na_c;
2964             if (d2 < rbb2 ||
2965                 (d2 < rl2 &&
2966 #ifdef NBNXN_PBB_SIMD4
2967                  subc_in_range_simd4
2968 #else
2969                  subc_in_range_x
2970 #endif
2971                      (na_c, ci, x_ci, cj_gl, stride, x, rl2)))
2972 #else
2973             /* Check if the distance between the two bounding boxes
2974              * in within the pair-list cut-off.
2975              */
2976             if (d2 < rl2)
2977 #endif
2978             {
2979                 /* Flag this i-subcell to be taken into account */
2980                 imask |= (1U << (cj_offset*GPU_NSUBCELL+ci));
2981
2982 #ifdef PRUNE_LIST_CPU_ONE
2983                 ci_last = ci;
2984 #endif
2985
2986                 npair++;
2987             }
2988         }
2989
2990 #ifdef PRUNE_LIST_CPU_ONE
2991         /* If we only found 1 pair, check if any atoms are actually
2992          * within the cut-off, so we could get rid of it.
2993          */
2994         if (npair == 1 && d2l[ci_last] >= rbb2)
2995         {
2996             /* Avoid using function pointers here, as it's slower */
2997             if (
2998 #ifdef NBNXN_PBB_SIMD4
2999                 !subc_in_range_simd4
3000 #else
3001                 !subc_in_range_x
3002 #endif
3003                     (na_c, ci_last, x_ci, cj_gl, stride, x, rl2))
3004             {
3005                 imask &= ~(1U << (cj_offset*GPU_NSUBCELL+ci_last));
3006                 npair--;
3007             }
3008         }
3009 #endif
3010
3011         if (npair > 0)
3012         {
3013             /* We have a useful sj entry, close it now */
3014
3015             /* Set the exclucions for the ci== sj entry.
3016              * Here we don't bother to check if this entry is actually flagged,
3017              * as it will nearly always be in the list.
3018              */
3019             if (sci_equals_scj)
3020             {
3021                 set_self_and_newton_excls_supersub(nbl, cj4_ind, cj_offset, cjo);
3022             }
3023
3024             /* Copy the cluster interaction mask to the list */
3025             for (w = 0; w < NWARP; w++)
3026             {
3027                 cj4->imei[w].imask |= imask;
3028             }
3029
3030             nbl->work->cj_ind++;
3031
3032             /* Keep the count */
3033             nbl->nci_tot += npair;
3034
3035             /* Increase the closing index in i super-cell list */
3036             nbl->sci[nbl->nsci].cj4_ind_end =
3037                 ((nbl->work->cj_ind+NBNXN_GPU_JGROUP_SIZE-1) >> NBNXN_GPU_JGROUP_SIZE_2LOG);
3038         }
3039     }
3040 }
3041
3042 /* Set all atom-pair exclusions from the topology stored in excl
3043  * as masks in the pair-list for simple list i-entry nbl_ci
3044  */
3045 static void set_ci_top_excls(const nbnxn_search_t nbs,
3046                              nbnxn_pairlist_t    *nbl,
3047                              gmx_bool             diagRemoved,
3048                              int                  na_ci_2log,
3049                              int                  na_cj_2log,
3050                              const nbnxn_ci_t    *nbl_ci,
3051                              const t_blocka      *excl)
3052 {
3053     const int    *cell;
3054     int           ci;
3055     int           cj_ind_first, cj_ind_last;
3056     int           cj_first, cj_last;
3057     int           ndirect;
3058     int           i, ai, aj, si, eind, ge, se;
3059     int           found, cj_ind_0, cj_ind_1, cj_ind_m;
3060     int           cj_m;
3061     gmx_bool      Found_si;
3062     int           si_ind;
3063     nbnxn_excl_t *nbl_excl;
3064     int           inner_i, inner_e;
3065
3066     cell = nbs->cell;
3067
3068     if (nbl_ci->cj_ind_end == nbl_ci->cj_ind_start)
3069     {
3070         /* Empty list */
3071         return;
3072     }
3073
3074     ci = nbl_ci->ci;
3075
3076     cj_ind_first = nbl_ci->cj_ind_start;
3077     cj_ind_last  = nbl->ncj - 1;
3078
3079     cj_first = nbl->cj[cj_ind_first].cj;
3080     cj_last  = nbl->cj[cj_ind_last].cj;
3081
3082     /* Determine how many contiguous j-cells we have starting
3083      * from the first i-cell. This number can be used to directly
3084      * calculate j-cell indices for excluded atoms.
3085      */
3086     ndirect = 0;
3087     if (na_ci_2log == na_cj_2log)
3088     {
3089         while (cj_ind_first + ndirect <= cj_ind_last &&
3090                nbl->cj[cj_ind_first+ndirect].cj == ci + ndirect)
3091         {
3092             ndirect++;
3093         }
3094     }
3095 #ifdef NBNXN_SEARCH_BB_SIMD4
3096     else
3097     {
3098         while (cj_ind_first + ndirect <= cj_ind_last &&
3099                nbl->cj[cj_ind_first+ndirect].cj == ci_to_cj(na_cj_2log, ci) + ndirect)
3100         {
3101             ndirect++;
3102         }
3103     }
3104 #endif
3105
3106     /* Loop over the atoms in the i super-cell */
3107     for (i = 0; i < nbl->na_sc; i++)
3108     {
3109         ai = nbs->a[ci*nbl->na_sc+i];
3110         if (ai >= 0)
3111         {
3112             si  = (i>>na_ci_2log);
3113
3114             /* Loop over the topology-based exclusions for this i-atom */
3115             for (eind = excl->index[ai]; eind < excl->index[ai+1]; eind++)
3116             {
3117                 aj = excl->a[eind];
3118
3119                 if (aj == ai)
3120                 {
3121                     /* The self exclusion are already set, save some time */
3122                     continue;
3123                 }
3124
3125                 ge = cell[aj];
3126
3127                 /* Without shifts we only calculate interactions j>i
3128                  * for one-way pair-lists.
3129                  */
3130                 if (diagRemoved && ge <= ci*nbl->na_sc + i)
3131                 {
3132                     continue;
3133                 }
3134
3135                 se = (ge >> na_cj_2log);
3136
3137                 /* Could the cluster se be in our list? */
3138                 if (se >= cj_first && se <= cj_last)
3139                 {
3140                     if (se < cj_first + ndirect)
3141                     {
3142                         /* We can calculate cj_ind directly from se */
3143                         found = cj_ind_first + se - cj_first;
3144                     }
3145                     else
3146                     {
3147                         /* Search for se using bisection */
3148                         found    = -1;
3149                         cj_ind_0 = cj_ind_first + ndirect;
3150                         cj_ind_1 = cj_ind_last + 1;
3151                         while (found == -1 && cj_ind_0 < cj_ind_1)
3152                         {
3153                             cj_ind_m = (cj_ind_0 + cj_ind_1)>>1;
3154
3155                             cj_m = nbl->cj[cj_ind_m].cj;
3156
3157                             if (se == cj_m)
3158                             {
3159                                 found = cj_ind_m;
3160                             }
3161                             else if (se < cj_m)
3162                             {
3163                                 cj_ind_1 = cj_ind_m;
3164                             }
3165                             else
3166                             {
3167                                 cj_ind_0 = cj_ind_m + 1;
3168                             }
3169                         }
3170                     }
3171
3172                     if (found >= 0)
3173                     {
3174                         inner_i = i  - (si << na_ci_2log);
3175                         inner_e = ge - (se << na_cj_2log);
3176
3177                         nbl->cj[found].excl &= ~(1U<<((inner_i<<na_cj_2log) + inner_e));
3178 /* The next code line is usually not needed. We do not want to version
3179  * away the above line, because there is logic that relies on being
3180  * able to detect easily whether any exclusions exist. */
3181 #if (defined GMX_CPU_ACCELERATION_IBM_QPX)
3182                         nbl->cj[found].interaction_mask_indices[inner_i] &= ~(1U << inner_e);
3183 #endif
3184                     }
3185                 }
3186             }
3187         }
3188     }
3189 }
3190
3191 /* Set all atom-pair exclusions from the topology stored in excl
3192  * as masks in the pair-list for i-super-cell entry nbl_sci
3193  */
3194 static void set_sci_top_excls(const nbnxn_search_t nbs,
3195                               nbnxn_pairlist_t    *nbl,
3196                               gmx_bool             diagRemoved,
3197                               int                  na_c_2log,
3198                               const nbnxn_sci_t   *nbl_sci,
3199                               const t_blocka      *excl)
3200 {
3201     const int    *cell;
3202     int           na_c;
3203     int           sci;
3204     int           cj_ind_first, cj_ind_last;
3205     int           cj_first, cj_last;
3206     int           ndirect;
3207     int           i, ai, aj, si, eind, ge, se;
3208     int           found, cj_ind_0, cj_ind_1, cj_ind_m;
3209     int           cj_m;
3210     gmx_bool      Found_si;
3211     int           si_ind;
3212     nbnxn_excl_t *nbl_excl;
3213     int           inner_i, inner_e, w;
3214
3215     cell = nbs->cell;
3216
3217     na_c = nbl->na_ci;
3218
3219     if (nbl_sci->cj4_ind_end == nbl_sci->cj4_ind_start)
3220     {
3221         /* Empty list */
3222         return;
3223     }
3224
3225     sci = nbl_sci->sci;
3226
3227     cj_ind_first = nbl_sci->cj4_ind_start*NBNXN_GPU_JGROUP_SIZE;
3228     cj_ind_last  = nbl->work->cj_ind - 1;
3229
3230     cj_first = nbl->cj4[nbl_sci->cj4_ind_start].cj[0];
3231     cj_last  = nbl_cj(nbl, cj_ind_last);
3232
3233     /* Determine how many contiguous j-clusters we have starting
3234      * from the first i-cluster. This number can be used to directly
3235      * calculate j-cluster indices for excluded atoms.
3236      */
3237     ndirect = 0;
3238     while (cj_ind_first + ndirect <= cj_ind_last &&
3239            nbl_cj(nbl, cj_ind_first+ndirect) == sci*GPU_NSUBCELL + ndirect)
3240     {
3241         ndirect++;
3242     }
3243
3244     /* Loop over the atoms in the i super-cell */
3245     for (i = 0; i < nbl->na_sc; i++)
3246     {
3247         ai = nbs->a[sci*nbl->na_sc+i];
3248         if (ai >= 0)
3249         {
3250             si  = (i>>na_c_2log);
3251
3252             /* Loop over the topology-based exclusions for this i-atom */
3253             for (eind = excl->index[ai]; eind < excl->index[ai+1]; eind++)
3254             {
3255                 aj = excl->a[eind];
3256
3257                 if (aj == ai)
3258                 {
3259                     /* The self exclusion are already set, save some time */
3260                     continue;
3261                 }
3262
3263                 ge = cell[aj];
3264
3265                 /* Without shifts we only calculate interactions j>i
3266                  * for one-way pair-lists.
3267                  */
3268                 if (diagRemoved && ge <= sci*nbl->na_sc + i)
3269                 {
3270                     continue;
3271                 }
3272
3273                 se = ge>>na_c_2log;
3274                 /* Could the cluster se be in our list? */
3275                 if (se >= cj_first && se <= cj_last)
3276                 {
3277                     if (se < cj_first + ndirect)
3278                     {
3279                         /* We can calculate cj_ind directly from se */
3280                         found = cj_ind_first + se - cj_first;
3281                     }
3282                     else
3283                     {
3284                         /* Search for se using bisection */
3285                         found    = -1;
3286                         cj_ind_0 = cj_ind_first + ndirect;
3287                         cj_ind_1 = cj_ind_last + 1;
3288                         while (found == -1 && cj_ind_0 < cj_ind_1)
3289                         {
3290                             cj_ind_m = (cj_ind_0 + cj_ind_1)>>1;
3291
3292                             cj_m = nbl_cj(nbl, cj_ind_m);
3293
3294                             if (se == cj_m)
3295                             {
3296                                 found = cj_ind_m;
3297                             }
3298                             else if (se < cj_m)
3299                             {
3300                                 cj_ind_1 = cj_ind_m;
3301                             }
3302                             else
3303                             {
3304                                 cj_ind_0 = cj_ind_m + 1;
3305                             }
3306                         }
3307                     }
3308
3309                     if (found >= 0)
3310                     {
3311                         inner_i = i  - si*na_c;
3312                         inner_e = ge - se*na_c;
3313
3314 /* Macro for getting the index of atom a within a cluster */
3315 #define AMODCJ4(a)  ((a) & (NBNXN_GPU_JGROUP_SIZE - 1))
3316 /* Macro for converting an atom number to a cluster number */
3317 #define A2CJ4(a)    ((a) >> NBNXN_GPU_JGROUP_SIZE_2LOG)
3318 /* Macro for getting the index of an i-atom within a warp */
3319 #define AMODWI(a)   ((a) & (NBNXN_GPU_CLUSTER_SIZE/2 - 1))
3320
3321                         if (nbl_imask0(nbl, found) & (1U << (AMODCJ4(found)*GPU_NSUBCELL + si)))
3322                         {
3323                             w       = (inner_e >> 2);
3324
3325                             get_nbl_exclusions_1(nbl, A2CJ4(found), w, &nbl_excl);
3326
3327                             nbl_excl->pair[AMODWI(inner_e)*nbl->na_ci+inner_i] &=
3328                                 ~(1U << (AMODCJ4(found)*GPU_NSUBCELL + si));
3329                         }
3330
3331 #undef AMODCJ4
3332 #undef A2CJ4
3333 #undef AMODWI
3334                     }
3335                 }
3336             }
3337         }
3338     }
3339 }
3340
3341 /* Reallocate the simple ci list for at least n entries */
3342 static void nb_realloc_ci(nbnxn_pairlist_t *nbl, int n)
3343 {
3344     nbl->ci_nalloc = over_alloc_small(n);
3345     nbnxn_realloc_void((void **)&nbl->ci,
3346                        nbl->nci*sizeof(*nbl->ci),
3347                        nbl->ci_nalloc*sizeof(*nbl->ci),
3348                        nbl->alloc, nbl->free);
3349 }
3350
3351 /* Reallocate the super-cell sci list for at least n entries */
3352 static void nb_realloc_sci(nbnxn_pairlist_t *nbl, int n)
3353 {
3354     nbl->sci_nalloc = over_alloc_small(n);
3355     nbnxn_realloc_void((void **)&nbl->sci,
3356                        nbl->nsci*sizeof(*nbl->sci),
3357                        nbl->sci_nalloc*sizeof(*nbl->sci),
3358                        nbl->alloc, nbl->free);
3359 }
3360
3361 /* Make a new ci entry at index nbl->nci */
3362 static void new_ci_entry(nbnxn_pairlist_t *nbl, int ci, int shift, int flags)
3363 {
3364     if (nbl->nci + 1 > nbl->ci_nalloc)
3365     {
3366         nb_realloc_ci(nbl, nbl->nci+1);
3367     }
3368     nbl->ci[nbl->nci].ci            = ci;
3369     nbl->ci[nbl->nci].shift         = shift;
3370     /* Store the interaction flags along with the shift */
3371     nbl->ci[nbl->nci].shift        |= flags;
3372     nbl->ci[nbl->nci].cj_ind_start  = nbl->ncj;
3373     nbl->ci[nbl->nci].cj_ind_end    = nbl->ncj;
3374 }
3375
3376 /* Make a new sci entry at index nbl->nsci */
3377 static void new_sci_entry(nbnxn_pairlist_t *nbl, int sci, int shift)
3378 {
3379     if (nbl->nsci + 1 > nbl->sci_nalloc)
3380     {
3381         nb_realloc_sci(nbl, nbl->nsci+1);
3382     }
3383     nbl->sci[nbl->nsci].sci           = sci;
3384     nbl->sci[nbl->nsci].shift         = shift;
3385     nbl->sci[nbl->nsci].cj4_ind_start = nbl->ncj4;
3386     nbl->sci[nbl->nsci].cj4_ind_end   = nbl->ncj4;
3387 }
3388
3389 /* Sort the simple j-list cj on exclusions.
3390  * Entries with exclusions will all be sorted to the beginning of the list.
3391  */
3392 static void sort_cj_excl(nbnxn_cj_t *cj, int ncj,
3393                          nbnxn_list_work_t *work)
3394 {
3395     int jnew, j;
3396
3397     if (ncj > work->cj_nalloc)
3398     {
3399         work->cj_nalloc = over_alloc_large(ncj);
3400         srenew(work->cj, work->cj_nalloc);
3401     }
3402
3403     /* Make a list of the j-cells involving exclusions */
3404     jnew = 0;
3405     for (j = 0; j < ncj; j++)
3406     {
3407         if (cj[j].excl != NBNXN_INTERACTION_MASK_ALL)
3408         {
3409             work->cj[jnew++] = cj[j];
3410         }
3411     }
3412     /* Check if there are exclusions at all or not just the first entry */
3413     if (!((jnew == 0) ||
3414           (jnew == 1 && cj[0].excl != NBNXN_INTERACTION_MASK_ALL)))
3415     {
3416         for (j = 0; j < ncj; j++)
3417         {
3418             if (cj[j].excl == NBNXN_INTERACTION_MASK_ALL)
3419             {
3420                 work->cj[jnew++] = cj[j];
3421             }
3422         }
3423         for (j = 0; j < ncj; j++)
3424         {
3425             cj[j] = work->cj[j];
3426         }
3427     }
3428 }
3429
3430 /* Close this simple list i entry */
3431 static void close_ci_entry_simple(nbnxn_pairlist_t *nbl)
3432 {
3433     int jlen;
3434
3435     /* All content of the new ci entry have already been filled correctly,
3436      * we only need to increase the count here (for non empty lists).
3437      */
3438     jlen = nbl->ci[nbl->nci].cj_ind_end - nbl->ci[nbl->nci].cj_ind_start;
3439     if (jlen > 0)
3440     {
3441         sort_cj_excl(nbl->cj+nbl->ci[nbl->nci].cj_ind_start, jlen, nbl->work);
3442
3443         /* The counts below are used for non-bonded pair/flop counts
3444          * and should therefore match the available kernel setups.
3445          */
3446         if (!(nbl->ci[nbl->nci].shift & NBNXN_CI_DO_COUL(0)))
3447         {
3448             nbl->work->ncj_noq += jlen;
3449         }
3450         else if ((nbl->ci[nbl->nci].shift & NBNXN_CI_HALF_LJ(0)) ||
3451                  !(nbl->ci[nbl->nci].shift & NBNXN_CI_DO_LJ(0)))
3452         {
3453             nbl->work->ncj_hlj += jlen;
3454         }
3455
3456         nbl->nci++;
3457     }
3458 }
3459
3460 /* Split sci entry for load balancing on the GPU.
3461  * Splitting ensures we have enough lists to fully utilize the whole GPU.
3462  * With progBal we generate progressively smaller lists, which improves
3463  * load balancing. As we only know the current count on our own thread,
3464  * we will need to estimate the current total amount of i-entries.
3465  * As the lists get concatenated later, this estimate depends
3466  * both on nthread and our own thread index.
3467  */
3468 static void split_sci_entry(nbnxn_pairlist_t *nbl,
3469                             int nsp_max_av, gmx_bool progBal, int nc_bal,
3470                             int thread, int nthread)
3471 {
3472     int nsci_est;
3473     int nsp_max;
3474     int cj4_start, cj4_end, j4len, cj4;
3475     int sci;
3476     int nsp, nsp_sci, nsp_cj4, nsp_cj4_e, nsp_cj4_p;
3477     int p;
3478
3479     if (progBal)
3480     {
3481         /* Estimate the total numbers of ci's of the nblist combined
3482          * over all threads using the target number of ci's.
3483          */
3484         nsci_est = nc_bal*thread/nthread + nbl->nsci;
3485
3486         /* The first ci blocks should be larger, to avoid overhead.
3487          * The last ci blocks should be smaller, to improve load balancing.
3488          */
3489         nsp_max = max(1,
3490                       nsp_max_av*nc_bal*3/(2*(nsci_est - 1 + nc_bal)));
3491     }
3492     else
3493     {
3494         nsp_max = nsp_max_av;
3495     }
3496
3497     cj4_start = nbl->sci[nbl->nsci-1].cj4_ind_start;
3498     cj4_end   = nbl->sci[nbl->nsci-1].cj4_ind_end;
3499     j4len     = cj4_end - cj4_start;
3500
3501     if (j4len > 1 && j4len*GPU_NSUBCELL*NBNXN_GPU_JGROUP_SIZE > nsp_max)
3502     {
3503         /* Remove the last ci entry and process the cj4's again */
3504         nbl->nsci -= 1;
3505
3506         sci        = nbl->nsci;
3507         nsp        = 0;
3508         nsp_sci    = 0;
3509         nsp_cj4_e  = 0;
3510         nsp_cj4    = 0;
3511         for (cj4 = cj4_start; cj4 < cj4_end; cj4++)
3512         {
3513             nsp_cj4_p = nsp_cj4;
3514             /* Count the number of cluster pairs in this cj4 group */
3515             nsp_cj4   = 0;
3516             for (p = 0; p < GPU_NSUBCELL*NBNXN_GPU_JGROUP_SIZE; p++)
3517             {
3518                 nsp_cj4 += (nbl->cj4[cj4].imei[0].imask >> p) & 1;
3519             }
3520
3521             if (nsp_cj4 > 0 && nsp + nsp_cj4 > nsp_max)
3522             {
3523                 /* Split the list at cj4 */
3524                 nbl->sci[sci].cj4_ind_end = cj4;
3525                 /* Create a new sci entry */
3526                 sci++;
3527                 nbl->nsci++;
3528                 if (nbl->nsci+1 > nbl->sci_nalloc)
3529                 {
3530                     nb_realloc_sci(nbl, nbl->nsci+1);
3531                 }
3532                 nbl->sci[sci].sci           = nbl->sci[nbl->nsci-1].sci;
3533                 nbl->sci[sci].shift         = nbl->sci[nbl->nsci-1].shift;
3534                 nbl->sci[sci].cj4_ind_start = cj4;
3535                 nsp_sci                     = nsp;
3536                 nsp_cj4_e                   = nsp_cj4_p;
3537                 nsp                         = 0;
3538             }
3539             nsp += nsp_cj4;
3540         }
3541
3542         /* Put the remaining cj4's in the last sci entry */
3543         nbl->sci[sci].cj4_ind_end = cj4_end;
3544
3545         /* Possibly balance out the last two sci's
3546          * by moving the last cj4 of the second last sci.
3547          */
3548         if (nsp_sci - nsp_cj4_e >= nsp + nsp_cj4_e)
3549         {
3550             nbl->sci[sci-1].cj4_ind_end--;
3551             nbl->sci[sci].cj4_ind_start--;
3552         }
3553
3554         nbl->nsci++;
3555     }
3556 }
3557
3558 /* Clost this super/sub list i entry */
3559 static void close_ci_entry_supersub(nbnxn_pairlist_t *nbl,
3560                                     int nsp_max_av,
3561                                     gmx_bool progBal, int nc_bal,
3562                                     int thread, int nthread)
3563 {
3564     int j4len, tlen;
3565     int nb, b;
3566
3567     /* All content of the new ci entry have already been filled correctly,
3568      * we only need to increase the count here (for non empty lists).
3569      */
3570     j4len = nbl->sci[nbl->nsci].cj4_ind_end - nbl->sci[nbl->nsci].cj4_ind_start;
3571     if (j4len > 0)
3572     {
3573         /* We can only have complete blocks of 4 j-entries in a list,
3574          * so round the count up before closing.
3575          */
3576         nbl->ncj4         = ((nbl->work->cj_ind + NBNXN_GPU_JGROUP_SIZE - 1) >> NBNXN_GPU_JGROUP_SIZE_2LOG);
3577         nbl->work->cj_ind = nbl->ncj4*NBNXN_GPU_JGROUP_SIZE;
3578
3579         nbl->nsci++;
3580
3581         if (nsp_max_av > 0)
3582         {
3583             /* Measure the size of the new entry and potentially split it */
3584             split_sci_entry(nbl, nsp_max_av, progBal, nc_bal, thread, nthread);
3585         }
3586     }
3587 }
3588
3589 /* Syncs the working array before adding another grid pair to the list */
3590 static void sync_work(nbnxn_pairlist_t *nbl)
3591 {
3592     if (!nbl->bSimple)
3593     {
3594         nbl->work->cj_ind   = nbl->ncj4*NBNXN_GPU_JGROUP_SIZE;
3595         nbl->work->cj4_init = nbl->ncj4;
3596     }
3597 }
3598
3599 /* Clears an nbnxn_pairlist_t data structure */
3600 static void clear_pairlist(nbnxn_pairlist_t *nbl)
3601 {
3602     nbl->nci           = 0;
3603     nbl->nsci          = 0;
3604     nbl->ncj           = 0;
3605     nbl->ncj4          = 0;
3606     nbl->nci_tot       = 0;
3607     nbl->nexcl         = 1;
3608
3609     nbl->work->ncj_noq = 0;
3610     nbl->work->ncj_hlj = 0;
3611 }
3612
3613 /* Sets a simple list i-cell bounding box, including PBC shift */
3614 static gmx_inline void set_icell_bb_simple(const nbnxn_bb_t *bb, int ci,
3615                                            real shx, real shy, real shz,
3616                                            nbnxn_bb_t *bb_ci)
3617 {
3618     bb_ci->lower[BB_X] = bb[ci].lower[BB_X] + shx;
3619     bb_ci->lower[BB_Y] = bb[ci].lower[BB_Y] + shy;
3620     bb_ci->lower[BB_Z] = bb[ci].lower[BB_Z] + shz;
3621     bb_ci->upper[BB_X] = bb[ci].upper[BB_X] + shx;
3622     bb_ci->upper[BB_Y] = bb[ci].upper[BB_Y] + shy;
3623     bb_ci->upper[BB_Z] = bb[ci].upper[BB_Z] + shz;
3624 }
3625
3626 #ifdef NBNXN_BBXXXX
3627 /* Sets a super-cell and sub cell bounding boxes, including PBC shift */
3628 static void set_icell_bbxxxx_supersub(const float *bb, int ci,
3629                                       real shx, real shy, real shz,
3630                                       float *bb_ci)
3631 {
3632     int ia, m, i;
3633
3634     ia = ci*(GPU_NSUBCELL>>STRIDE_PBB_2LOG)*NNBSBB_XXXX;
3635     for (m = 0; m < (GPU_NSUBCELL>>STRIDE_PBB_2LOG)*NNBSBB_XXXX; m += NNBSBB_XXXX)
3636     {
3637         for (i = 0; i < STRIDE_PBB; i++)
3638         {
3639             bb_ci[m+0*STRIDE_PBB+i] = bb[ia+m+0*STRIDE_PBB+i] + shx;
3640             bb_ci[m+1*STRIDE_PBB+i] = bb[ia+m+1*STRIDE_PBB+i] + shy;
3641             bb_ci[m+2*STRIDE_PBB+i] = bb[ia+m+2*STRIDE_PBB+i] + shz;
3642             bb_ci[m+3*STRIDE_PBB+i] = bb[ia+m+3*STRIDE_PBB+i] + shx;
3643             bb_ci[m+4*STRIDE_PBB+i] = bb[ia+m+4*STRIDE_PBB+i] + shy;
3644             bb_ci[m+5*STRIDE_PBB+i] = bb[ia+m+5*STRIDE_PBB+i] + shz;
3645         }
3646     }
3647 }
3648 #endif
3649
3650 /* Sets a super-cell and sub cell bounding boxes, including PBC shift */
3651 static void set_icell_bb_supersub(const nbnxn_bb_t *bb, int ci,
3652                                   real shx, real shy, real shz,
3653                                   nbnxn_bb_t *bb_ci)
3654 {
3655     int i;
3656
3657     for (i = 0; i < GPU_NSUBCELL; i++)
3658     {
3659         set_icell_bb_simple(bb, ci*GPU_NSUBCELL+i,
3660                             shx, shy, shz,
3661                             &bb_ci[i]);
3662     }
3663 }
3664
3665 /* Copies PBC shifted i-cell atom coordinates x,y,z to working array */
3666 static void icell_set_x_simple(int ci,
3667                                real shx, real shy, real shz,
3668                                int gmx_unused na_c,
3669                                int stride, const real *x,
3670                                nbnxn_list_work_t *work)
3671 {
3672     int  ia, i;
3673
3674     ia = ci*NBNXN_CPU_CLUSTER_I_SIZE;
3675
3676     for (i = 0; i < NBNXN_CPU_CLUSTER_I_SIZE; i++)
3677     {
3678         work->x_ci[i*STRIDE_XYZ+XX] = x[(ia+i)*stride+XX] + shx;
3679         work->x_ci[i*STRIDE_XYZ+YY] = x[(ia+i)*stride+YY] + shy;
3680         work->x_ci[i*STRIDE_XYZ+ZZ] = x[(ia+i)*stride+ZZ] + shz;
3681     }
3682 }
3683
3684 /* Copies PBC shifted super-cell atom coordinates x,y,z to working array */
3685 static void icell_set_x_supersub(int ci,
3686                                  real shx, real shy, real shz,
3687                                  int na_c,
3688                                  int stride, const real *x,
3689                                  nbnxn_list_work_t *work)
3690 {
3691     int  ia, i;
3692     real *x_ci;
3693
3694     x_ci = work->x_ci;
3695
3696     ia = ci*GPU_NSUBCELL*na_c;
3697     for (i = 0; i < GPU_NSUBCELL*na_c; i++)
3698     {
3699         x_ci[i*DIM + XX] = x[(ia+i)*stride + XX] + shx;
3700         x_ci[i*DIM + YY] = x[(ia+i)*stride + YY] + shy;
3701         x_ci[i*DIM + ZZ] = x[(ia+i)*stride + ZZ] + shz;
3702     }
3703 }
3704
3705 #ifdef NBNXN_SEARCH_BB_SIMD4
3706 /* Copies PBC shifted super-cell packed atom coordinates to working array */
3707 static void icell_set_x_supersub_simd4(int ci,
3708                                        real shx, real shy, real shz,
3709                                        int na_c,
3710                                        int stride, const real *x,
3711                                        nbnxn_list_work_t *work)
3712 {
3713     int  si, io, ia, i, j;
3714     real *x_ci;
3715
3716     x_ci = work->x_ci;
3717
3718     for (si = 0; si < GPU_NSUBCELL; si++)
3719     {
3720         for (i = 0; i < na_c; i += STRIDE_PBB)
3721         {
3722             io = si*na_c + i;
3723             ia = ci*GPU_NSUBCELL*na_c + io;
3724             for (j = 0; j < STRIDE_PBB; j++)
3725             {
3726                 x_ci[io*DIM + j + XX*STRIDE_PBB] = x[(ia+j)*stride+XX] + shx;
3727                 x_ci[io*DIM + j + YY*STRIDE_PBB] = x[(ia+j)*stride+YY] + shy;
3728                 x_ci[io*DIM + j + ZZ*STRIDE_PBB] = x[(ia+j)*stride+ZZ] + shz;
3729             }
3730         }
3731     }
3732 }
3733 #endif
3734
3735 static real nbnxn_rlist_inc_nonloc_fac = 0.6;
3736
3737 /* Due to the cluster size the effective pair-list is longer than
3738  * that of a simple atom pair-list. This function gives the extra distance.
3739  */
3740 real nbnxn_get_rlist_effective_inc(int cluster_size, real atom_density)
3741 {
3742     return ((0.5 + nbnxn_rlist_inc_nonloc_fac)*sqr(((cluster_size) - 1.0)/(cluster_size))*pow((cluster_size)/(atom_density), 1.0/3.0));
3743 }
3744
3745 /* Estimates the interaction volume^2 for non-local interactions */
3746 static real nonlocal_vol2(const gmx_domdec_zones_t *zones, rvec ls, real r)
3747 {
3748     int  z, d;
3749     real cl, ca, za;
3750     real vold_est;
3751     real vol2_est_tot;
3752
3753     vol2_est_tot = 0;
3754
3755     /* Here we simply add up the volumes of 1, 2 or 3 1D decomposition
3756      * not home interaction volume^2. As these volumes are not additive,
3757      * this is an overestimate, but it would only be significant in the limit
3758      * of small cells, where we anyhow need to split the lists into
3759      * as small parts as possible.
3760      */
3761
3762     for (z = 0; z < zones->n; z++)
3763     {
3764         if (zones->shift[z][XX] + zones->shift[z][YY] + zones->shift[z][ZZ] == 1)
3765         {
3766             cl = 0;
3767             ca = 1;
3768             za = 1;
3769             for (d = 0; d < DIM; d++)
3770             {
3771                 if (zones->shift[z][d] == 0)
3772                 {
3773                     cl += 0.5*ls[d];
3774                     ca *= ls[d];
3775                     za *= zones->size[z].x1[d] - zones->size[z].x0[d];
3776                 }
3777             }
3778
3779             /* 4 octants of a sphere */
3780             vold_est  = 0.25*M_PI*r*r*r*r;
3781             /* 4 quarter pie slices on the edges */
3782             vold_est += 4*cl*M_PI/6.0*r*r*r;
3783             /* One rectangular volume on a face */
3784             vold_est += ca*0.5*r*r;
3785
3786             vol2_est_tot += vold_est*za;
3787         }
3788     }
3789
3790     return vol2_est_tot;
3791 }
3792
3793 /* Estimates the average size of a full j-list for super/sub setup */
3794 static int get_nsubpair_max(const nbnxn_search_t nbs,
3795                             int                  iloc,
3796                             real                 rlist,
3797                             int                  min_ci_balanced)
3798 {
3799     const nbnxn_grid_t *grid;
3800     rvec ls;
3801     real xy_diag2, r_eff_sup, vol_est, nsp_est, nsp_est_nl;
3802     int  nsubpair_max;
3803
3804     grid = &nbs->grid[0];
3805
3806     ls[XX] = (grid->c1[XX] - grid->c0[XX])/(grid->ncx*GPU_NSUBCELL_X);
3807     ls[YY] = (grid->c1[YY] - grid->c0[YY])/(grid->ncy*GPU_NSUBCELL_Y);
3808     ls[ZZ] = (grid->c1[ZZ] - grid->c0[ZZ])*grid->ncx*grid->ncy/(grid->nc*GPU_NSUBCELL_Z);
3809
3810     /* The average squared length of the diagonal of a sub cell */
3811     xy_diag2 = ls[XX]*ls[XX] + ls[YY]*ls[YY] + ls[ZZ]*ls[ZZ];
3812
3813     /* The formulas below are a heuristic estimate of the average nsj per si*/
3814     r_eff_sup = rlist + nbnxn_rlist_inc_nonloc_fac*sqr((grid->na_c - 1.0)/grid->na_c)*sqrt(xy_diag2/3);
3815
3816     if (!nbs->DomDec || nbs->zones->n == 1)
3817     {
3818         nsp_est_nl = 0;
3819     }
3820     else
3821     {
3822         nsp_est_nl =
3823             sqr(grid->atom_density/grid->na_c)*
3824             nonlocal_vol2(nbs->zones, ls, r_eff_sup);
3825     }
3826
3827     if (LOCAL_I(iloc))
3828     {
3829         /* Sub-cell interacts with itself */
3830         vol_est  = ls[XX]*ls[YY]*ls[ZZ];
3831         /* 6/2 rectangular volume on the faces */
3832         vol_est += (ls[XX]*ls[YY] + ls[XX]*ls[ZZ] + ls[YY]*ls[ZZ])*r_eff_sup;
3833         /* 12/2 quarter pie slices on the edges */
3834         vol_est += 2*(ls[XX] + ls[YY] + ls[ZZ])*0.25*M_PI*sqr(r_eff_sup);
3835         /* 4 octants of a sphere */
3836         vol_est += 0.5*4.0/3.0*M_PI*pow(r_eff_sup, 3);
3837
3838         nsp_est = grid->nsubc_tot*vol_est*grid->atom_density/grid->na_c;
3839
3840         /* Subtract the non-local pair count */
3841         nsp_est -= nsp_est_nl;
3842
3843         if (debug)
3844         {
3845             fprintf(debug, "nsp_est local %5.1f non-local %5.1f\n",
3846                     nsp_est, nsp_est_nl);
3847         }
3848     }
3849     else
3850     {
3851         nsp_est = nsp_est_nl;
3852     }
3853
3854     if (min_ci_balanced <= 0 || grid->nc >= min_ci_balanced || grid->nc == 0)
3855     {
3856         /* We don't need to worry */
3857         nsubpair_max = -1;
3858     }
3859     else
3860     {
3861         /* Thus the (average) maximum j-list size should be as follows */
3862         nsubpair_max = max(1, (int)(nsp_est/min_ci_balanced+0.5));
3863
3864         /* Since the target value is a maximum (this avoids high outliers,
3865          * which lead to load imbalance), not average, we add half the
3866          * number of pairs in a cj4 block to get the average about right.
3867          */
3868         nsubpair_max += GPU_NSUBCELL*NBNXN_GPU_JGROUP_SIZE/2;
3869     }
3870
3871     if (debug)
3872     {
3873         fprintf(debug, "nbl nsp estimate %.1f, nsubpair_max %d\n",
3874                 nsp_est, nsubpair_max);
3875     }
3876
3877     return nsubpair_max;
3878 }
3879
3880 /* Debug list print function */
3881 static void print_nblist_ci_cj(FILE *fp, const nbnxn_pairlist_t *nbl)
3882 {
3883     int i, j;
3884
3885     for (i = 0; i < nbl->nci; i++)
3886     {
3887         fprintf(fp, "ci %4d  shift %2d  ncj %3d\n",
3888                 nbl->ci[i].ci, nbl->ci[i].shift,
3889                 nbl->ci[i].cj_ind_end - nbl->ci[i].cj_ind_start);
3890
3891         for (j = nbl->ci[i].cj_ind_start; j < nbl->ci[i].cj_ind_end; j++)
3892         {
3893             fprintf(fp, "  cj %5d  imask %x\n",
3894                     nbl->cj[j].cj,
3895                     nbl->cj[j].excl);
3896         }
3897     }
3898 }
3899
3900 /* Debug list print function */
3901 static void print_nblist_sci_cj(FILE *fp, const nbnxn_pairlist_t *nbl)
3902 {
3903     int i, j4, j, ncp, si;
3904
3905     for (i = 0; i < nbl->nsci; i++)
3906     {
3907         fprintf(fp, "ci %4d  shift %2d  ncj4 %2d\n",
3908                 nbl->sci[i].sci, nbl->sci[i].shift,
3909                 nbl->sci[i].cj4_ind_end - nbl->sci[i].cj4_ind_start);
3910
3911         ncp = 0;
3912         for (j4 = nbl->sci[i].cj4_ind_start; j4 < nbl->sci[i].cj4_ind_end; j4++)
3913         {
3914             for (j = 0; j < NBNXN_GPU_JGROUP_SIZE; j++)
3915             {
3916                 fprintf(fp, "  sj %5d  imask %x\n",
3917                         nbl->cj4[j4].cj[j],
3918                         nbl->cj4[j4].imei[0].imask);
3919                 for (si = 0; si < GPU_NSUBCELL; si++)
3920                 {
3921                     if (nbl->cj4[j4].imei[0].imask & (1U << (j*GPU_NSUBCELL + si)))
3922                     {
3923                         ncp++;
3924                     }
3925                 }
3926             }
3927         }
3928         fprintf(fp, "ci %4d  shift %2d  ncj4 %2d ncp %3d\n",
3929                 nbl->sci[i].sci, nbl->sci[i].shift,
3930                 nbl->sci[i].cj4_ind_end - nbl->sci[i].cj4_ind_start,
3931                 ncp);
3932     }
3933 }
3934
3935 /* Combine pair lists *nbl generated on multiple threads nblc */
3936 static void combine_nblists(int nnbl, nbnxn_pairlist_t **nbl,
3937                             nbnxn_pairlist_t *nblc)
3938 {
3939     int nsci, ncj4, nexcl;
3940     int n, i;
3941
3942     if (nblc->bSimple)
3943     {
3944         gmx_incons("combine_nblists does not support simple lists");
3945     }
3946
3947     nsci  = nblc->nsci;
3948     ncj4  = nblc->ncj4;
3949     nexcl = nblc->nexcl;
3950     for (i = 0; i < nnbl; i++)
3951     {
3952         nsci  += nbl[i]->nsci;
3953         ncj4  += nbl[i]->ncj4;
3954         nexcl += nbl[i]->nexcl;
3955     }
3956
3957     if (nsci > nblc->sci_nalloc)
3958     {
3959         nb_realloc_sci(nblc, nsci);
3960     }
3961     if (ncj4 > nblc->cj4_nalloc)
3962     {
3963         nblc->cj4_nalloc = over_alloc_small(ncj4);
3964         nbnxn_realloc_void((void **)&nblc->cj4,
3965                            nblc->ncj4*sizeof(*nblc->cj4),
3966                            nblc->cj4_nalloc*sizeof(*nblc->cj4),
3967                            nblc->alloc, nblc->free);
3968     }
3969     if (nexcl > nblc->excl_nalloc)
3970     {
3971         nblc->excl_nalloc = over_alloc_small(nexcl);
3972         nbnxn_realloc_void((void **)&nblc->excl,
3973                            nblc->nexcl*sizeof(*nblc->excl),
3974                            nblc->excl_nalloc*sizeof(*nblc->excl),
3975                            nblc->alloc, nblc->free);
3976     }
3977
3978     /* Each thread should copy its own data to the combined arrays,
3979      * as otherwise data will go back and forth between different caches.
3980      */
3981 #pragma omp parallel for num_threads(gmx_omp_nthreads_get(emntPairsearch)) schedule(static)
3982     for (n = 0; n < nnbl; n++)
3983     {
3984         int sci_offset;
3985         int cj4_offset;
3986         int ci_offset;
3987         int excl_offset;
3988         int i, j4;
3989         const nbnxn_pairlist_t *nbli;
3990
3991         /* Determine the offset in the combined data for our thread */
3992         sci_offset  = nblc->nsci;
3993         cj4_offset  = nblc->ncj4;
3994         ci_offset   = nblc->nci_tot;
3995         excl_offset = nblc->nexcl;
3996
3997         for (i = 0; i < n; i++)
3998         {
3999             sci_offset  += nbl[i]->nsci;
4000             cj4_offset  += nbl[i]->ncj4;
4001             ci_offset   += nbl[i]->nci_tot;
4002             excl_offset += nbl[i]->nexcl;
4003         }
4004
4005         nbli = nbl[n];
4006
4007         for (i = 0; i < nbli->nsci; i++)
4008         {
4009             nblc->sci[sci_offset+i]                = nbli->sci[i];
4010             nblc->sci[sci_offset+i].cj4_ind_start += cj4_offset;
4011             nblc->sci[sci_offset+i].cj4_ind_end   += cj4_offset;
4012         }
4013
4014         for (j4 = 0; j4 < nbli->ncj4; j4++)
4015         {
4016             nblc->cj4[cj4_offset+j4]                   = nbli->cj4[j4];
4017             nblc->cj4[cj4_offset+j4].imei[0].excl_ind += excl_offset;
4018             nblc->cj4[cj4_offset+j4].imei[1].excl_ind += excl_offset;
4019         }
4020
4021         for (j4 = 0; j4 < nbli->nexcl; j4++)
4022         {
4023             nblc->excl[excl_offset+j4] = nbli->excl[j4];
4024         }
4025     }
4026
4027     for (n = 0; n < nnbl; n++)
4028     {
4029         nblc->nsci    += nbl[n]->nsci;
4030         nblc->ncj4    += nbl[n]->ncj4;
4031         nblc->nci_tot += nbl[n]->nci_tot;
4032         nblc->nexcl   += nbl[n]->nexcl;
4033     }
4034 }
4035
4036 /* Returns the next ci to be processes by our thread */
4037 static gmx_bool next_ci(const nbnxn_grid_t *grid,
4038                         int conv,
4039                         int nth, int ci_block,
4040                         int *ci_x, int *ci_y,
4041                         int *ci_b, int *ci)
4042 {
4043     (*ci_b)++;
4044     (*ci)++;
4045
4046     if (*ci_b == ci_block)
4047     {
4048         /* Jump to the next block assigned to this task */
4049         *ci   += (nth - 1)*ci_block;
4050         *ci_b  = 0;
4051     }
4052
4053     if (*ci >= grid->nc*conv)
4054     {
4055         return FALSE;
4056     }
4057
4058     while (*ci >= grid->cxy_ind[*ci_x*grid->ncy + *ci_y + 1]*conv)
4059     {
4060         *ci_y += 1;
4061         if (*ci_y == grid->ncy)
4062         {
4063             *ci_x += 1;
4064             *ci_y  = 0;
4065         }
4066     }
4067
4068     return TRUE;
4069 }
4070
4071 /* Returns the distance^2 for which we put cell pairs in the list
4072  * without checking atom pair distances. This is usually < rlist^2.
4073  */
4074 static float boundingbox_only_distance2(const nbnxn_grid_t *gridi,
4075                                         const nbnxn_grid_t *gridj,
4076                                         real                rlist,
4077                                         gmx_bool            simple)
4078 {
4079     /* If the distance between two sub-cell bounding boxes is less
4080      * than this distance, do not check the distance between
4081      * all particle pairs in the sub-cell, since then it is likely
4082      * that the box pair has atom pairs within the cut-off.
4083      * We use the nblist cut-off minus 0.5 times the average x/y diagonal
4084      * spacing of the sub-cells. Around 40% of the checked pairs are pruned.
4085      * Using more than 0.5 gains at most 0.5%.
4086      * If forces are calculated more than twice, the performance gain
4087      * in the force calculation outweighs the cost of checking.
4088      * Note that with subcell lists, the atom-pair distance check
4089      * is only performed when only 1 out of 8 sub-cells in within range,
4090      * this is because the GPU is much faster than the cpu.
4091      */
4092     real bbx, bby;
4093     real rbb2;
4094
4095     bbx = 0.5*(gridi->sx + gridj->sx);
4096     bby = 0.5*(gridi->sy + gridj->sy);
4097     if (!simple)
4098     {
4099         bbx /= GPU_NSUBCELL_X;
4100         bby /= GPU_NSUBCELL_Y;
4101     }
4102
4103     rbb2 = sqr(max(0, rlist - 0.5*sqrt(bbx*bbx + bby*bby)));
4104
4105 #ifndef GMX_DOUBLE
4106     return rbb2;
4107 #else
4108     return (float)((1+GMX_FLOAT_EPS)*rbb2);
4109 #endif
4110 }
4111
4112 static int get_ci_block_size(const nbnxn_grid_t *gridi,
4113                              gmx_bool bDomDec, int nth)
4114 {
4115     const int ci_block_enum      = 5;
4116     const int ci_block_denom     = 11;
4117     const int ci_block_min_atoms = 16;
4118     int ci_block;
4119
4120     /* Here we decide how to distribute the blocks over the threads.
4121      * We use prime numbers to try to avoid that the grid size becomes
4122      * a multiple of the number of threads, which would lead to some
4123      * threads getting "inner" pairs and others getting boundary pairs,
4124      * which in turns will lead to load imbalance between threads.
4125      * Set the block size as 5/11/ntask times the average number of cells
4126      * in a y,z slab. This should ensure a quite uniform distribution
4127      * of the grid parts of the different thread along all three grid
4128      * zone boundaries with 3D domain decomposition. At the same time
4129      * the blocks will not become too small.
4130      */
4131     ci_block = (gridi->nc*ci_block_enum)/(ci_block_denom*gridi->ncx*nth);
4132
4133     /* Ensure the blocks are not too small: avoids cache invalidation */
4134     if (ci_block*gridi->na_sc < ci_block_min_atoms)
4135     {
4136         ci_block = (ci_block_min_atoms + gridi->na_sc - 1)/gridi->na_sc;
4137     }
4138
4139     /* Without domain decomposition
4140      * or with less than 3 blocks per task, divide in nth blocks.
4141      */
4142     if (!bDomDec || ci_block*3*nth > gridi->nc)
4143     {
4144         ci_block = (gridi->nc + nth - 1)/nth;
4145     }
4146
4147     return ci_block;
4148 }
4149
4150 /* Generates the part of pair-list nbl assigned to our thread */
4151 static void nbnxn_make_pairlist_part(const nbnxn_search_t nbs,
4152                                      const nbnxn_grid_t *gridi,
4153                                      const nbnxn_grid_t *gridj,
4154                                      nbnxn_search_work_t *work,
4155                                      const nbnxn_atomdata_t *nbat,
4156                                      const t_blocka *excl,
4157                                      real rlist,
4158                                      int nb_kernel_type,
4159                                      int ci_block,
4160                                      gmx_bool bFBufferFlag,
4161                                      int nsubpair_max,
4162                                      gmx_bool progBal,
4163                                      int min_ci_balanced,
4164                                      int th, int nth,
4165                                      nbnxn_pairlist_t *nbl)
4166 {
4167     int  na_cj_2log;
4168     matrix box;
4169     real rl2;
4170     float rbb2;
4171     int  d;
4172     int  ci_b, ci, ci_x, ci_y, ci_xy, cj;
4173     ivec shp;
4174     int  tx, ty, tz;
4175     int  shift;
4176     gmx_bool bMakeList;
4177     real shx, shy, shz;
4178     int  conv_i, cell0_i;
4179     const nbnxn_bb_t *bb_i = NULL;
4180 #ifdef NBNXN_BBXXXX
4181     const float *pbb_i = NULL;
4182 #endif
4183     const float *bbcz_i, *bbcz_j;
4184     const int *flags_i;
4185     real bx0, bx1, by0, by1, bz0, bz1;
4186     real bz1_frac;
4187     real d2cx, d2z, d2z_cx, d2z_cy, d2zx, d2zxy, d2xy;
4188     int  cxf, cxl, cyf, cyf_x, cyl;
4189     int  cx, cy;
4190     int  c0, c1, cs, cf, cl;
4191     int  ndistc;
4192     int  ncpcheck;
4193     int  gridi_flag_shift = 0, gridj_flag_shift = 0;
4194     unsigned *gridj_flag  = NULL;
4195     int  ncj_old_i, ncj_old_j;
4196
4197     nbs_cycle_start(&work->cc[enbsCCsearch]);
4198
4199     if (gridj->bSimple != nbl->bSimple)
4200     {
4201         gmx_incons("Grid incompatible with pair-list");
4202     }
4203
4204     sync_work(nbl);
4205     nbl->na_sc = gridj->na_sc;
4206     nbl->na_ci = gridj->na_c;
4207     nbl->na_cj = nbnxn_kernel_to_cj_size(nb_kernel_type);
4208     na_cj_2log = get_2log(nbl->na_cj);
4209
4210     nbl->rlist  = rlist;
4211
4212     if (bFBufferFlag)
4213     {
4214         /* Determine conversion of clusters to flag blocks */
4215         gridi_flag_shift = 0;
4216         while ((nbl->na_ci<<gridi_flag_shift) < NBNXN_BUFFERFLAG_SIZE)
4217         {
4218             gridi_flag_shift++;
4219         }
4220         gridj_flag_shift = 0;
4221         while ((nbl->na_cj<<gridj_flag_shift) < NBNXN_BUFFERFLAG_SIZE)
4222         {
4223             gridj_flag_shift++;
4224         }
4225
4226         gridj_flag = work->buffer_flags.flag;
4227     }
4228
4229     copy_mat(nbs->box, box);
4230
4231     rl2 = nbl->rlist*nbl->rlist;
4232
4233     rbb2 = boundingbox_only_distance2(gridi, gridj, nbl->rlist, nbl->bSimple);
4234
4235     if (debug)
4236     {
4237         fprintf(debug, "nbl bounding box only distance %f\n", sqrt(rbb2));
4238     }
4239
4240     /* Set the shift range */
4241     for (d = 0; d < DIM; d++)
4242     {
4243         /* Check if we need periodicity shifts.
4244          * Without PBC or with domain decomposition we don't need them.
4245          */
4246         if (d >= ePBC2npbcdim(nbs->ePBC) || nbs->dd_dim[d])
4247         {
4248             shp[d] = 0;
4249         }
4250         else
4251         {
4252             if (d == XX &&
4253                 box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
4254             {
4255                 shp[d] = 2;
4256             }
4257             else
4258             {
4259                 shp[d] = 1;
4260             }
4261         }
4262     }
4263
4264     if (nbl->bSimple && !gridi->bSimple)
4265     {
4266         conv_i  = gridi->na_sc/gridj->na_sc;
4267         bb_i    = gridi->bb_simple;
4268         bbcz_i  = gridi->bbcz_simple;
4269         flags_i = gridi->flags_simple;
4270     }
4271     else
4272     {
4273         conv_i  = 1;
4274 #ifdef NBNXN_BBXXXX
4275         if (gridi->bSimple)
4276         {
4277             bb_i  = gridi->bb;
4278         }
4279         else
4280         {
4281             pbb_i = gridi->pbb;
4282         }
4283 #else
4284         /* We use the normal bounding box format for both grid types */
4285         bb_i  = gridi->bb;
4286 #endif
4287         bbcz_i  = gridi->bbcz;
4288         flags_i = gridi->flags;
4289     }
4290     cell0_i = gridi->cell0*conv_i;
4291
4292     bbcz_j = gridj->bbcz;
4293
4294     if (conv_i != 1)
4295     {
4296         /* Blocks of the conversion factor - 1 give a large repeat count
4297          * combined with a small block size. This should result in good
4298          * load balancing for both small and large domains.
4299          */
4300         ci_block = conv_i - 1;
4301     }
4302     if (debug)
4303     {
4304         fprintf(debug, "nbl nc_i %d col.av. %.1f ci_block %d\n",
4305                 gridi->nc, gridi->nc/(double)(gridi->ncx*gridi->ncy), ci_block);
4306     }
4307
4308     ndistc   = 0;
4309     ncpcheck = 0;
4310
4311     /* Initially ci_b and ci to 1 before where we want them to start,
4312      * as they will both be incremented in next_ci.
4313      */
4314     ci_b = -1;
4315     ci   = th*ci_block - 1;
4316     ci_x = 0;
4317     ci_y = 0;
4318     while (next_ci(gridi, conv_i, nth, ci_block, &ci_x, &ci_y, &ci_b, &ci))
4319     {
4320         if (nbl->bSimple && flags_i[ci] == 0)
4321         {
4322             continue;
4323         }
4324
4325         ncj_old_i = nbl->ncj;
4326
4327         d2cx = 0;
4328         if (gridj != gridi && shp[XX] == 0)
4329         {
4330             if (nbl->bSimple)
4331             {
4332                 bx1 = bb_i[ci].upper[BB_X];
4333             }
4334             else
4335             {
4336                 bx1 = gridi->c0[XX] + (ci_x+1)*gridi->sx;
4337             }
4338             if (bx1 < gridj->c0[XX])
4339             {
4340                 d2cx = sqr(gridj->c0[XX] - bx1);
4341
4342                 if (d2cx >= rl2)
4343                 {
4344                     continue;
4345                 }
4346             }
4347         }
4348
4349         ci_xy = ci_x*gridi->ncy + ci_y;
4350
4351         /* Loop over shift vectors in three dimensions */
4352         for (tz = -shp[ZZ]; tz <= shp[ZZ]; tz++)
4353         {
4354             shz = tz*box[ZZ][ZZ];
4355
4356             bz0 = bbcz_i[ci*NNBSBB_D  ] + shz;
4357             bz1 = bbcz_i[ci*NNBSBB_D+1] + shz;
4358
4359             if (tz == 0)
4360             {
4361                 d2z = 0;
4362             }
4363             else if (tz < 0)
4364             {
4365                 d2z = sqr(bz1);
4366             }
4367             else
4368             {
4369                 d2z = sqr(bz0 - box[ZZ][ZZ]);
4370             }
4371
4372             d2z_cx = d2z + d2cx;
4373
4374             if (d2z_cx >= rl2)
4375             {
4376                 continue;
4377             }
4378
4379             bz1_frac =
4380                 bz1/((real)(gridi->cxy_ind[ci_xy+1] - gridi->cxy_ind[ci_xy]));
4381             if (bz1_frac < 0)
4382             {
4383                 bz1_frac = 0;
4384             }
4385             /* The check with bz1_frac close to or larger than 1 comes later */
4386
4387             for (ty = -shp[YY]; ty <= shp[YY]; ty++)
4388             {
4389                 shy = ty*box[YY][YY] + tz*box[ZZ][YY];
4390
4391                 if (nbl->bSimple)
4392                 {
4393                     by0 = bb_i[ci].lower[BB_Y] + shy;
4394                     by1 = bb_i[ci].upper[BB_Y] + shy;
4395                 }
4396                 else
4397                 {
4398                     by0 = gridi->c0[YY] + (ci_y  )*gridi->sy + shy;
4399                     by1 = gridi->c0[YY] + (ci_y+1)*gridi->sy + shy;
4400                 }
4401
4402                 get_cell_range(by0, by1,
4403                                gridj->ncy, gridj->c0[YY], gridj->sy, gridj->inv_sy,
4404                                d2z_cx, rl2,
4405                                &cyf, &cyl);
4406
4407                 if (cyf > cyl)
4408                 {
4409                     continue;
4410                 }
4411
4412                 d2z_cy = d2z;
4413                 if (by1 < gridj->c0[YY])
4414                 {
4415                     d2z_cy += sqr(gridj->c0[YY] - by1);
4416                 }
4417                 else if (by0 > gridj->c1[YY])
4418                 {
4419                     d2z_cy += sqr(by0 - gridj->c1[YY]);
4420                 }
4421
4422                 for (tx = -shp[XX]; tx <= shp[XX]; tx++)
4423                 {
4424                     shift = XYZ2IS(tx, ty, tz);
4425
4426 #ifdef NBNXN_SHIFT_BACKWARD
4427                     if (gridi == gridj && shift > CENTRAL)
4428                     {
4429                         continue;
4430                     }
4431 #endif
4432
4433                     shx = tx*box[XX][XX] + ty*box[YY][XX] + tz*box[ZZ][XX];
4434
4435                     if (nbl->bSimple)
4436                     {
4437                         bx0 = bb_i[ci].lower[BB_X] + shx;
4438                         bx1 = bb_i[ci].upper[BB_X] + shx;
4439                     }
4440                     else
4441                     {
4442                         bx0 = gridi->c0[XX] + (ci_x  )*gridi->sx + shx;
4443                         bx1 = gridi->c0[XX] + (ci_x+1)*gridi->sx + shx;
4444                     }
4445
4446                     get_cell_range(bx0, bx1,
4447                                    gridj->ncx, gridj->c0[XX], gridj->sx, gridj->inv_sx,
4448                                    d2z_cy, rl2,
4449                                    &cxf, &cxl);
4450
4451                     if (cxf > cxl)
4452                     {
4453                         continue;
4454                     }
4455
4456                     if (nbl->bSimple)
4457                     {
4458                         new_ci_entry(nbl, cell0_i+ci, shift, flags_i[ci]);
4459                     }
4460                     else
4461                     {
4462                         new_sci_entry(nbl, cell0_i+ci, shift);
4463                     }
4464
4465 #ifndef NBNXN_SHIFT_BACKWARD
4466                     if (cxf < ci_x)
4467 #else
4468                     if (shift == CENTRAL && gridi == gridj &&
4469                         cxf < ci_x)
4470 #endif
4471                     {
4472                         /* Leave the pairs with i > j.
4473                          * x is the major index, so skip half of it.
4474                          */
4475                         cxf = ci_x;
4476                     }
4477
4478                     if (nbl->bSimple)
4479                     {
4480                         set_icell_bb_simple(bb_i, ci, shx, shy, shz,
4481                                             nbl->work->bb_ci);
4482                     }
4483                     else
4484                     {
4485 #ifdef NBNXN_BBXXXX
4486                         set_icell_bbxxxx_supersub(pbb_i, ci, shx, shy, shz,
4487                                                   nbl->work->pbb_ci);
4488 #else
4489                         set_icell_bb_supersub(bb_i, ci, shx, shy, shz,
4490                                               nbl->work->bb_ci);
4491 #endif
4492                     }
4493
4494                     nbs->icell_set_x(cell0_i+ci, shx, shy, shz,
4495                                      gridi->na_c, nbat->xstride, nbat->x,
4496                                      nbl->work);
4497
4498                     for (cx = cxf; cx <= cxl; cx++)
4499                     {
4500                         d2zx = d2z;
4501                         if (gridj->c0[XX] + cx*gridj->sx > bx1)
4502                         {
4503                             d2zx += sqr(gridj->c0[XX] + cx*gridj->sx - bx1);
4504                         }
4505                         else if (gridj->c0[XX] + (cx+1)*gridj->sx < bx0)
4506                         {
4507                             d2zx += sqr(gridj->c0[XX] + (cx+1)*gridj->sx - bx0);
4508                         }
4509
4510 #ifndef NBNXN_SHIFT_BACKWARD
4511                         if (gridi == gridj &&
4512                             cx == 0 && cyf < ci_y)
4513 #else
4514                         if (gridi == gridj &&
4515                             cx == 0 && shift == CENTRAL && cyf < ci_y)
4516 #endif
4517                         {
4518                             /* Leave the pairs with i > j.
4519                              * Skip half of y when i and j have the same x.
4520                              */
4521                             cyf_x = ci_y;
4522                         }
4523                         else
4524                         {
4525                             cyf_x = cyf;
4526                         }
4527
4528                         for (cy = cyf_x; cy <= cyl; cy++)
4529                         {
4530                             c0 = gridj->cxy_ind[cx*gridj->ncy+cy];
4531                             c1 = gridj->cxy_ind[cx*gridj->ncy+cy+1];
4532 #ifdef NBNXN_SHIFT_BACKWARD
4533                             if (gridi == gridj &&
4534                                 shift == CENTRAL && c0 < ci)
4535                             {
4536                                 c0 = ci;
4537                             }
4538 #endif
4539
4540                             d2zxy = d2zx;
4541                             if (gridj->c0[YY] + cy*gridj->sy > by1)
4542                             {
4543                                 d2zxy += sqr(gridj->c0[YY] + cy*gridj->sy - by1);
4544                             }
4545                             else if (gridj->c0[YY] + (cy+1)*gridj->sy < by0)
4546                             {
4547                                 d2zxy += sqr(gridj->c0[YY] + (cy+1)*gridj->sy - by0);
4548                             }
4549                             if (c1 > c0 && d2zxy < rl2)
4550                             {
4551                                 cs = c0 + (int)(bz1_frac*(c1 - c0));
4552                                 if (cs >= c1)
4553                                 {
4554                                     cs = c1 - 1;
4555                                 }
4556
4557                                 d2xy = d2zxy - d2z;
4558
4559                                 /* Find the lowest cell that can possibly
4560                                  * be within range.
4561                                  */
4562                                 cf = cs;
4563                                 while (cf > c0 &&
4564                                        (bbcz_j[cf*NNBSBB_D+1] >= bz0 ||
4565                                         d2xy + sqr(bbcz_j[cf*NNBSBB_D+1] - bz0) < rl2))
4566                                 {
4567                                     cf--;
4568                                 }
4569
4570                                 /* Find the highest cell that can possibly
4571                                  * be within range.
4572                                  */
4573                                 cl = cs;
4574                                 while (cl < c1-1 &&
4575                                        (bbcz_j[cl*NNBSBB_D] <= bz1 ||
4576                                         d2xy + sqr(bbcz_j[cl*NNBSBB_D] - bz1) < rl2))
4577                                 {
4578                                     cl++;
4579                                 }
4580
4581 #ifdef NBNXN_REFCODE
4582                                 {
4583                                     /* Simple reference code, for debugging,
4584                                      * overrides the more complex code above.
4585                                      */
4586                                     int k;
4587                                     cf = c1;
4588                                     cl = -1;
4589                                     for (k = c0; k < c1; k++)
4590                                     {
4591                                         if (box_dist2(bx0, bx1, by0, by1, bz0, bz1, bb+k) < rl2 &&
4592                                             k < cf)
4593                                         {
4594                                             cf = k;
4595                                         }
4596                                         if (box_dist2(bx0, bx1, by0, by1, bz0, bz1, bb+k) < rl2 &&
4597                                             k > cl)
4598                                         {
4599                                             cl = k;
4600                                         }
4601                                     }
4602                                 }
4603 #endif
4604
4605                                 if (gridi == gridj)
4606                                 {
4607                                     /* We want each atom/cell pair only once,
4608                                      * only use cj >= ci.
4609                                      */
4610 #ifndef NBNXN_SHIFT_BACKWARD
4611                                     cf = max(cf, ci);
4612 #else
4613                                     if (shift == CENTRAL)
4614                                     {
4615                                         cf = max(cf, ci);
4616                                     }
4617 #endif
4618                                 }
4619
4620                                 if (cf <= cl)
4621                                 {
4622                                     /* For f buffer flags with simple lists */
4623                                     ncj_old_j = nbl->ncj;
4624
4625                                     switch (nb_kernel_type)
4626                                     {
4627                                         case nbnxnk4x4_PlainC:
4628                                             check_subcell_list_space_simple(nbl, cl-cf+1);
4629
4630                                             make_cluster_list_simple(gridj,
4631                                                                      nbl, ci, cf, cl,
4632                                                                      (gridi == gridj && shift == CENTRAL),
4633                                                                      nbat->x,
4634                                                                      rl2, rbb2,
4635                                                                      &ndistc);
4636                                             break;
4637 #ifdef GMX_NBNXN_SIMD_4XN
4638                                         case nbnxnk4xN_SIMD_4xN:
4639                                             check_subcell_list_space_simple(nbl, ci_to_cj(na_cj_2log, cl-cf)+2);
4640                                             make_cluster_list_simd_4xn(gridj,
4641                                                                        nbl, ci, cf, cl,
4642                                                                        (gridi == gridj && shift == CENTRAL),
4643                                                                        nbat->x,
4644                                                                        rl2, rbb2,
4645                                                                        &ndistc);
4646                                             break;
4647 #endif
4648 #ifdef GMX_NBNXN_SIMD_2XNN
4649                                         case nbnxnk4xN_SIMD_2xNN:
4650                                             check_subcell_list_space_simple(nbl, ci_to_cj(na_cj_2log, cl-cf)+2);
4651                                             make_cluster_list_simd_2xnn(gridj,
4652                                                                         nbl, ci, cf, cl,
4653                                                                         (gridi == gridj && shift == CENTRAL),
4654                                                                         nbat->x,
4655                                                                         rl2, rbb2,
4656                                                                         &ndistc);
4657                                             break;
4658 #endif
4659                                         case nbnxnk8x8x8_PlainC:
4660                                         case nbnxnk8x8x8_CUDA:
4661                                             check_subcell_list_space_supersub(nbl, cl-cf+1);
4662                                             for (cj = cf; cj <= cl; cj++)
4663                                             {
4664                                                 make_cluster_list_supersub(gridi, gridj,
4665                                                                            nbl, ci, cj,
4666                                                                            (gridi == gridj && shift == CENTRAL && ci == cj),
4667                                                                            nbat->xstride, nbat->x,
4668                                                                            rl2, rbb2,
4669                                                                            &ndistc);
4670                                             }
4671                                             break;
4672                                     }
4673                                     ncpcheck += cl - cf + 1;
4674
4675                                     if (bFBufferFlag && nbl->ncj > ncj_old_j)
4676                                     {
4677                                         int cbf, cbl, cb;
4678
4679                                         cbf = nbl->cj[ncj_old_j].cj >> gridj_flag_shift;
4680                                         cbl = nbl->cj[nbl->ncj-1].cj >> gridj_flag_shift;
4681                                         for (cb = cbf; cb <= cbl; cb++)
4682                                         {
4683                                             gridj_flag[cb] = 1U<<th;
4684                                         }
4685                                     }
4686                                 }
4687                             }
4688                         }
4689                     }
4690
4691                     /* Set the exclusions for this ci list */
4692                     if (nbl->bSimple)
4693                     {
4694                         set_ci_top_excls(nbs,
4695                                          nbl,
4696                                          shift == CENTRAL && gridi == gridj,
4697                                          gridj->na_c_2log,
4698                                          na_cj_2log,
4699                                          &(nbl->ci[nbl->nci]),
4700                                          excl);
4701                     }
4702                     else
4703                     {
4704                         set_sci_top_excls(nbs,
4705                                           nbl,
4706                                           shift == CENTRAL && gridi == gridj,
4707                                           gridj->na_c_2log,
4708                                           &(nbl->sci[nbl->nsci]),
4709                                           excl);
4710                     }
4711
4712                     /* Close this ci list */
4713                     if (nbl->bSimple)
4714                     {
4715                         close_ci_entry_simple(nbl);
4716                     }
4717                     else
4718                     {
4719                         close_ci_entry_supersub(nbl,
4720                                                 nsubpair_max,
4721                                                 progBal, min_ci_balanced,
4722                                                 th, nth);
4723                     }
4724                 }
4725             }
4726         }
4727
4728         if (bFBufferFlag && nbl->ncj > ncj_old_i)
4729         {
4730             work->buffer_flags.flag[(gridi->cell0+ci)>>gridi_flag_shift] = 1U<<th;
4731         }
4732     }
4733
4734     work->ndistc = ndistc;
4735
4736     nbs_cycle_stop(&work->cc[enbsCCsearch]);
4737
4738     if (debug)
4739     {
4740         fprintf(debug, "number of distance checks %d\n", ndistc);
4741         fprintf(debug, "ncpcheck %s %d\n", gridi == gridj ? "local" : "non-local",
4742                 ncpcheck);
4743
4744         if (nbl->bSimple)
4745         {
4746             print_nblist_statistics_simple(debug, nbl, nbs, rlist);
4747         }
4748         else
4749         {
4750             print_nblist_statistics_supersub(debug, nbl, nbs, rlist);
4751         }
4752
4753     }
4754 }
4755
4756 static void reduce_buffer_flags(const nbnxn_search_t        nbs,
4757                                 int                         nsrc,
4758                                 const nbnxn_buffer_flags_t *dest)
4759 {
4760     int s, b;
4761     const unsigned *flag;
4762
4763     for (s = 0; s < nsrc; s++)
4764     {
4765         flag = nbs->work[s].buffer_flags.flag;
4766
4767         for (b = 0; b < dest->nflag; b++)
4768         {
4769             dest->flag[b] |= flag[b];
4770         }
4771     }
4772 }
4773
4774 static void print_reduction_cost(const nbnxn_buffer_flags_t *flags, int nout)
4775 {
4776     int nelem, nkeep, ncopy, nred, b, c, out;
4777
4778     nelem = 0;
4779     nkeep = 0;
4780     ncopy = 0;
4781     nred  = 0;
4782     for (b = 0; b < flags->nflag; b++)
4783     {
4784         if (flags->flag[b] == 1)
4785         {
4786             /* Only flag 0 is set, no copy of reduction required */
4787             nelem++;
4788             nkeep++;
4789         }
4790         else if (flags->flag[b] > 0)
4791         {
4792             c = 0;
4793             for (out = 0; out < nout; out++)
4794             {
4795                 if (flags->flag[b] & (1U<<out))
4796                 {
4797                     c++;
4798                 }
4799             }
4800             nelem += c;
4801             if (c == 1)
4802             {
4803                 ncopy++;
4804             }
4805             else
4806             {
4807                 nred += c;
4808             }
4809         }
4810     }
4811
4812     fprintf(debug, "nbnxn reduction: #flag %d #list %d elem %4.2f, keep %4.2f copy %4.2f red %4.2f\n",
4813             flags->nflag, nout,
4814             nelem/(double)(flags->nflag),
4815             nkeep/(double)(flags->nflag),
4816             ncopy/(double)(flags->nflag),
4817             nred/(double)(flags->nflag));
4818 }
4819
4820 /* Perform a count (linear) sort to sort the smaller lists to the end.
4821  * This avoids load imbalance on the GPU, as large lists will be
4822  * scheduled and executed first and the smaller lists later.
4823  * Load balancing between multi-processors only happens at the end
4824  * and there smaller lists lead to more effective load balancing.
4825  * The sorting is done on the cj4 count, not on the actual pair counts.
4826  * Not only does this make the sort faster, but it also results in
4827  * better load balancing than using a list sorted on exact load.
4828  * This function swaps the pointer in the pair list to avoid a copy operation.
4829  */
4830 static void sort_sci(nbnxn_pairlist_t *nbl)
4831 {
4832     nbnxn_list_work_t *work;
4833     int                m, i, s, s0, s1;
4834     nbnxn_sci_t       *sci_sort;
4835
4836     if (nbl->ncj4 <= nbl->nsci)
4837     {
4838         /* nsci = 0 or all sci have size 1, sorting won't change the order */
4839         return;
4840     }
4841
4842     work = nbl->work;
4843
4844     /* We will distinguish differences up to double the average */
4845     m = (2*nbl->ncj4)/nbl->nsci;
4846
4847     if (m + 1 > work->sort_nalloc)
4848     {
4849         work->sort_nalloc = over_alloc_large(m + 1);
4850         srenew(work->sort, work->sort_nalloc);
4851     }
4852
4853     if (work->sci_sort_nalloc != nbl->sci_nalloc)
4854     {
4855         work->sci_sort_nalloc = nbl->sci_nalloc;
4856         nbnxn_realloc_void((void **)&work->sci_sort,
4857                            0,
4858                            work->sci_sort_nalloc*sizeof(*work->sci_sort),
4859                            nbl->alloc, nbl->free);
4860     }
4861
4862     /* Count the entries of each size */
4863     for (i = 0; i <= m; i++)
4864     {
4865         work->sort[i] = 0;
4866     }
4867     for (s = 0; s < nbl->nsci; s++)
4868     {
4869         i = min(m, nbl->sci[s].cj4_ind_end - nbl->sci[s].cj4_ind_start);
4870         work->sort[i]++;
4871     }
4872     /* Calculate the offset for each count */
4873     s0            = work->sort[m];
4874     work->sort[m] = 0;
4875     for (i = m - 1; i >= 0; i--)
4876     {
4877         s1            = work->sort[i];
4878         work->sort[i] = work->sort[i + 1] + s0;
4879         s0            = s1;
4880     }
4881
4882     /* Sort entries directly into place */
4883     sci_sort = work->sci_sort;
4884     for (s = 0; s < nbl->nsci; s++)
4885     {
4886         i = min(m, nbl->sci[s].cj4_ind_end - nbl->sci[s].cj4_ind_start);
4887         sci_sort[work->sort[i]++] = nbl->sci[s];
4888     }
4889
4890     /* Swap the sci pointers so we use the new, sorted list */
4891     work->sci_sort = nbl->sci;
4892     nbl->sci       = sci_sort;
4893 }
4894
4895 /* Make a local or non-local pair-list, depending on iloc */
4896 void nbnxn_make_pairlist(const nbnxn_search_t  nbs,
4897                          nbnxn_atomdata_t     *nbat,
4898                          const t_blocka       *excl,
4899                          real                  rlist,
4900                          int                   min_ci_balanced,
4901                          nbnxn_pairlist_set_t *nbl_list,
4902                          int                   iloc,
4903                          int                   nb_kernel_type,
4904                          t_nrnb               *nrnb)
4905 {
4906     nbnxn_grid_t *gridi, *gridj;
4907     gmx_bool bGPUCPU;
4908     int nzi, zi, zj0, zj1, zj;
4909     int nsubpair_max;
4910     int th;
4911     int nnbl;
4912     nbnxn_pairlist_t **nbl;
4913     int ci_block;
4914     gmx_bool CombineNBLists;
4915     gmx_bool progBal;
4916     int np_tot, np_noq, np_hlj, nap;
4917
4918     /* Check if we are running hybrid GPU + CPU nbnxn mode */
4919     bGPUCPU = (!nbs->grid[0].bSimple && nbl_list->bSimple);
4920
4921     nnbl            = nbl_list->nnbl;
4922     nbl             = nbl_list->nbl;
4923     CombineNBLists  = nbl_list->bCombined;
4924
4925     if (debug)
4926     {
4927         fprintf(debug, "ns making %d nblists\n", nnbl);
4928     }
4929
4930     nbat->bUseBufferFlags = (nbat->nout > 1);
4931     /* We should re-init the flags before making the first list */
4932     if (nbat->bUseBufferFlags && (LOCAL_I(iloc) || bGPUCPU))
4933     {
4934         init_buffer_flags(&nbat->buffer_flags, nbat->natoms);
4935     }
4936
4937     if (nbl_list->bSimple)
4938     {
4939         switch (nb_kernel_type)
4940         {
4941 #ifdef GMX_NBNXN_SIMD_4XN
4942             case nbnxnk4xN_SIMD_4xN:
4943                 nbs->icell_set_x = icell_set_x_simd_4xn;
4944                 break;
4945 #endif
4946 #ifdef GMX_NBNXN_SIMD_2XNN
4947             case nbnxnk4xN_SIMD_2xNN:
4948                 nbs->icell_set_x = icell_set_x_simd_2xnn;
4949                 break;
4950 #endif
4951             default:
4952                 nbs->icell_set_x = icell_set_x_simple;
4953                 break;
4954         }
4955     }
4956     else
4957     {
4958 #ifdef NBNXN_SEARCH_BB_SIMD4
4959         nbs->icell_set_x = icell_set_x_supersub_simd4;
4960 #else
4961         nbs->icell_set_x = icell_set_x_supersub;
4962 #endif
4963     }
4964
4965     if (LOCAL_I(iloc))
4966     {
4967         /* Only zone (grid) 0 vs 0 */
4968         nzi = 1;
4969         zj0 = 0;
4970         zj1 = 1;
4971     }
4972     else
4973     {
4974         nzi = nbs->zones->nizone;
4975     }
4976
4977     if (!nbl_list->bSimple && min_ci_balanced > 0)
4978     {
4979         nsubpair_max = get_nsubpair_max(nbs, iloc, rlist, min_ci_balanced);
4980     }
4981     else
4982     {
4983         nsubpair_max = 0;
4984     }
4985
4986     /* Clear all pair-lists */
4987     for (th = 0; th < nnbl; th++)
4988     {
4989         clear_pairlist(nbl[th]);
4990     }
4991
4992     for (zi = 0; zi < nzi; zi++)
4993     {
4994         gridi = &nbs->grid[zi];
4995
4996         if (NONLOCAL_I(iloc))
4997         {
4998             zj0 = nbs->zones->izone[zi].j0;
4999             zj1 = nbs->zones->izone[zi].j1;
5000             if (zi == 0)
5001             {
5002                 zj0++;
5003             }
5004         }
5005         for (zj = zj0; zj < zj1; zj++)
5006         {
5007             gridj = &nbs->grid[zj];
5008
5009             if (debug)
5010             {
5011                 fprintf(debug, "ns search grid %d vs %d\n", zi, zj);
5012             }
5013
5014             nbs_cycle_start(&nbs->cc[enbsCCsearch]);
5015
5016             if (nbl[0]->bSimple && !gridi->bSimple)
5017             {
5018                 /* Hybrid list, determine blocking later */
5019                 ci_block = 0;
5020             }
5021             else
5022             {
5023                 ci_block = get_ci_block_size(gridi, nbs->DomDec, nnbl);
5024             }
5025
5026 #pragma omp parallel for num_threads(nnbl) schedule(static)
5027             for (th = 0; th < nnbl; th++)
5028             {
5029                 /* Re-init the thread-local work flag data before making
5030                  * the first list (not an elegant conditional).
5031                  */
5032                 if (nbat->bUseBufferFlags && ((zi == 0 && zj == 0) ||
5033                                               (bGPUCPU && zi == 0 && zj == 1)))
5034                 {
5035                     init_buffer_flags(&nbs->work[th].buffer_flags, nbat->natoms);
5036                 }
5037
5038                 if (CombineNBLists && th > 0)
5039                 {
5040                     clear_pairlist(nbl[th]);
5041                 }
5042
5043                 /* With GPU: generate progressively smaller lists for
5044                  * load balancing for local only or non-local with 2 zones.
5045                  */
5046                 progBal = (LOCAL_I(iloc) || nbs->zones->n <= 2);
5047
5048                 /* Divide the i super cell equally over the nblists */
5049                 nbnxn_make_pairlist_part(nbs, gridi, gridj,
5050                                          &nbs->work[th], nbat, excl,
5051                                          rlist,
5052                                          nb_kernel_type,
5053                                          ci_block,
5054                                          nbat->bUseBufferFlags,
5055                                          nsubpair_max,
5056                                          progBal, min_ci_balanced,
5057                                          th, nnbl,
5058                                          nbl[th]);
5059             }
5060             nbs_cycle_stop(&nbs->cc[enbsCCsearch]);
5061
5062             np_tot = 0;
5063             np_noq = 0;
5064             np_hlj = 0;
5065             for (th = 0; th < nnbl; th++)
5066             {
5067                 inc_nrnb(nrnb, eNR_NBNXN_DIST2, nbs->work[th].ndistc);
5068
5069                 if (nbl_list->bSimple)
5070                 {
5071                     np_tot += nbl[th]->ncj;
5072                     np_noq += nbl[th]->work->ncj_noq;
5073                     np_hlj += nbl[th]->work->ncj_hlj;
5074                 }
5075                 else
5076                 {
5077                     /* This count ignores potential subsequent pair pruning */
5078                     np_tot += nbl[th]->nci_tot;
5079                 }
5080             }
5081             nap                   = nbl[0]->na_ci*nbl[0]->na_cj;
5082             nbl_list->natpair_ljq = (np_tot - np_noq)*nap - np_hlj*nap/2;
5083             nbl_list->natpair_lj  = np_noq*nap;
5084             nbl_list->natpair_q   = np_hlj*nap/2;
5085
5086             if (CombineNBLists && nnbl > 1)
5087             {
5088                 nbs_cycle_start(&nbs->cc[enbsCCcombine]);
5089
5090                 combine_nblists(nnbl-1, nbl+1, nbl[0]);
5091
5092                 nbs_cycle_stop(&nbs->cc[enbsCCcombine]);
5093             }
5094         }
5095     }
5096
5097     if (!nbl_list->bSimple)
5098     {
5099         /* Sort the entries on size, large ones first */
5100         if (CombineNBLists || nnbl == 1)
5101         {
5102             sort_sci(nbl[0]);
5103         }
5104         else
5105         {
5106 #pragma omp parallel for num_threads(nnbl) schedule(static)
5107             for (th = 0; th < nnbl; th++)
5108             {
5109                 sort_sci(nbl[th]);
5110             }
5111         }
5112     }
5113
5114     if (nbat->bUseBufferFlags)
5115     {
5116         reduce_buffer_flags(nbs, nnbl, &nbat->buffer_flags);
5117     }
5118
5119     /* Special performance logging stuff (env.var. GMX_NBNXN_CYCLE) */
5120     if (LOCAL_I(iloc))
5121     {
5122         nbs->search_count++;
5123     }
5124     if (nbs->print_cycles &&
5125         (!nbs->DomDec || (nbs->DomDec && !LOCAL_I(iloc))) &&
5126         nbs->search_count % 100 == 0)
5127     {
5128         nbs_cycle_print(stderr, nbs);
5129     }
5130
5131     if (debug && (CombineNBLists && nnbl > 1))
5132     {
5133         if (nbl[0]->bSimple)
5134         {
5135             print_nblist_statistics_simple(debug, nbl[0], nbs, rlist);
5136         }
5137         else
5138         {
5139             print_nblist_statistics_supersub(debug, nbl[0], nbs, rlist);
5140         }
5141     }
5142
5143     if (debug)
5144     {
5145         if (gmx_debug_at)
5146         {
5147             if (nbl[0]->bSimple)
5148             {
5149                 print_nblist_ci_cj(debug, nbl[0]);
5150             }
5151             else
5152             {
5153                 print_nblist_sci_cj(debug, nbl[0]);
5154             }
5155         }
5156
5157         if (nbat->bUseBufferFlags)
5158         {
5159             print_reduction_cost(&nbat->buffer_flags, nnbl);
5160         }
5161     }
5162 }