mdlib: Clean up -Wunused-parameter warnings
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_atomdata.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 "smalloc.h"
40 #include "macros.h"
41 #include "vec.h"
42 #include "nbnxn_consts.h"
43 #include "nbnxn_internal.h"
44 #include "nbnxn_search.h"
45 #include "gmx_omp_nthreads.h"
46
47 /* Default nbnxn allocation routine, allocates NBNXN_MEM_ALIGN byte aligned */
48 void nbnxn_alloc_aligned(void **ptr, size_t nbytes)
49 {
50     *ptr = save_malloc_aligned("ptr", __FILE__, __LINE__, nbytes, 1, NBNXN_MEM_ALIGN);
51 }
52
53 /* Free function for memory allocated with nbnxn_alloc_aligned */
54 void nbnxn_free_aligned(void *ptr)
55 {
56     sfree_aligned(ptr);
57 }
58
59 /* Reallocation wrapper function for nbnxn data structures */
60 void nbnxn_realloc_void(void **ptr,
61                         int nbytes_copy, int nbytes_new,
62                         nbnxn_alloc_t *ma,
63                         nbnxn_free_t  *mf)
64 {
65     void *ptr_new;
66
67     ma(&ptr_new, nbytes_new);
68
69     if (nbytes_new > 0 && ptr_new == NULL)
70     {
71         gmx_fatal(FARGS, "Allocation of %d bytes failed", nbytes_new);
72     }
73
74     if (nbytes_copy > 0)
75     {
76         if (nbytes_new < nbytes_copy)
77         {
78             gmx_incons("In nbnxn_realloc_void: new size less than copy size");
79         }
80         memcpy(ptr_new, *ptr, nbytes_copy);
81     }
82     if (*ptr != NULL)
83     {
84         mf(*ptr);
85     }
86     *ptr = ptr_new;
87 }
88
89 /* Reallocate the nbnxn_atomdata_t for a size of n atoms */
90 void nbnxn_atomdata_realloc(nbnxn_atomdata_t *nbat, int n)
91 {
92     int t;
93
94     nbnxn_realloc_void((void **)&nbat->type,
95                        nbat->natoms*sizeof(*nbat->type),
96                        n*sizeof(*nbat->type),
97                        nbat->alloc, nbat->free);
98     nbnxn_realloc_void((void **)&nbat->lj_comb,
99                        nbat->natoms*2*sizeof(*nbat->lj_comb),
100                        n*2*sizeof(*nbat->lj_comb),
101                        nbat->alloc, nbat->free);
102     if (nbat->XFormat != nbatXYZQ)
103     {
104         nbnxn_realloc_void((void **)&nbat->q,
105                            nbat->natoms*sizeof(*nbat->q),
106                            n*sizeof(*nbat->q),
107                            nbat->alloc, nbat->free);
108     }
109     if (nbat->nenergrp > 1)
110     {
111         nbnxn_realloc_void((void **)&nbat->energrp,
112                            nbat->natoms/nbat->na_c*sizeof(*nbat->energrp),
113                            n/nbat->na_c*sizeof(*nbat->energrp),
114                            nbat->alloc, nbat->free);
115     }
116     nbnxn_realloc_void((void **)&nbat->x,
117                        nbat->natoms*nbat->xstride*sizeof(*nbat->x),
118                        n*nbat->xstride*sizeof(*nbat->x),
119                        nbat->alloc, nbat->free);
120     for (t = 0; t < nbat->nout; t++)
121     {
122         /* Allocate one element extra for possible signaling with CUDA */
123         nbnxn_realloc_void((void **)&nbat->out[t].f,
124                            nbat->natoms*nbat->fstride*sizeof(*nbat->out[t].f),
125                            n*nbat->fstride*sizeof(*nbat->out[t].f),
126                            nbat->alloc, nbat->free);
127     }
128     nbat->nalloc = n;
129 }
130
131 /* Initializes an nbnxn_atomdata_output_t data structure */
132 static void nbnxn_atomdata_output_init(nbnxn_atomdata_output_t *out,
133                                        int nb_kernel_type,
134                                        int nenergrp, int stride,
135                                        nbnxn_alloc_t *ma)
136 {
137     int cj_size;
138
139     out->f = NULL;
140     ma((void **)&out->fshift, SHIFTS*DIM*sizeof(*out->fshift));
141     out->nV = nenergrp*nenergrp;
142     ma((void **)&out->Vvdw, out->nV*sizeof(*out->Vvdw));
143     ma((void **)&out->Vc, out->nV*sizeof(*out->Vc  ));
144
145     if (nb_kernel_type == nbnxnk4xN_SIMD_4xN ||
146         nb_kernel_type == nbnxnk4xN_SIMD_2xNN)
147     {
148         cj_size  = nbnxn_kernel_to_cj_size(nb_kernel_type);
149         out->nVS = nenergrp*nenergrp*stride*(cj_size>>1)*cj_size;
150         ma((void **)&out->VSvdw, out->nVS*sizeof(*out->VSvdw));
151         ma((void **)&out->VSc, out->nVS*sizeof(*out->VSc  ));
152     }
153     else
154     {
155         out->nVS = 0;
156     }
157 }
158
159 static void copy_int_to_nbat_int(const int *a, int na, int na_round,
160                                  const int *in, int fill, int *innb)
161 {
162     int i, j;
163
164     j = 0;
165     for (i = 0; i < na; i++)
166     {
167         innb[j++] = in[a[i]];
168     }
169     /* Complete the partially filled last cell with fill */
170     for (; i < na_round; i++)
171     {
172         innb[j++] = fill;
173     }
174 }
175
176 static void clear_nbat_real(int na, int nbatFormat, real *xnb, int a0)
177 {
178     int a, d, j, c;
179
180     switch (nbatFormat)
181     {
182         case nbatXYZ:
183             for (a = 0; a < na; a++)
184             {
185                 for (d = 0; d < DIM; d++)
186                 {
187                     xnb[(a0+a)*STRIDE_XYZ+d] = 0;
188                 }
189             }
190             break;
191         case nbatXYZQ:
192             for (a = 0; a < na; a++)
193             {
194                 for (d = 0; d < DIM; d++)
195                 {
196                     xnb[(a0+a)*STRIDE_XYZQ+d] = 0;
197                 }
198             }
199             break;
200         case nbatX4:
201             j = X4_IND_A(a0);
202             c = a0 & (PACK_X4-1);
203             for (a = 0; a < na; a++)
204             {
205                 xnb[j+XX*PACK_X4] = 0;
206                 xnb[j+YY*PACK_X4] = 0;
207                 xnb[j+ZZ*PACK_X4] = 0;
208                 j++;
209                 c++;
210                 if (c == PACK_X4)
211                 {
212                     j += (DIM-1)*PACK_X4;
213                     c  = 0;
214                 }
215             }
216             break;
217         case nbatX8:
218             j = X8_IND_A(a0);
219             c = a0 & (PACK_X8-1);
220             for (a = 0; a < na; a++)
221             {
222                 xnb[j+XX*PACK_X8] = 0;
223                 xnb[j+YY*PACK_X8] = 0;
224                 xnb[j+ZZ*PACK_X8] = 0;
225                 j++;
226                 c++;
227                 if (c == PACK_X8)
228                 {
229                     j += (DIM-1)*PACK_X8;
230                     c  = 0;
231                 }
232             }
233             break;
234     }
235 }
236
237 void copy_rvec_to_nbat_real(const int *a, int na, int na_round,
238                             rvec *x, int nbatFormat, real *xnb, int a0,
239                             int cx, int cy, int cz)
240 {
241     int i, j, c;
242
243 /* We might need to place filler particles to fill up the cell to na_round.
244  * The coefficients (LJ and q) for such particles are zero.
245  * But we might still get NaN as 0*NaN when distances are too small.
246  * We hope that -107 nm is far away enough from to zero
247  * to avoid accidental short distances to particles shifted down for pbc.
248  */
249 #define NBAT_FAR_AWAY 107
250
251     switch (nbatFormat)
252     {
253         case nbatXYZ:
254             j = a0*STRIDE_XYZ;
255             for (i = 0; i < na; i++)
256             {
257                 xnb[j++] = x[a[i]][XX];
258                 xnb[j++] = x[a[i]][YY];
259                 xnb[j++] = x[a[i]][ZZ];
260             }
261             /* Complete the partially filled last cell with copies of the last element.
262              * This simplifies the bounding box calculation and avoid
263              * numerical issues with atoms that are coincidentally close.
264              */
265             for (; i < na_round; i++)
266             {
267                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cx);
268                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cy);
269                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cz + i);
270             }
271             break;
272         case nbatXYZQ:
273             j = a0*STRIDE_XYZQ;
274             for (i = 0; i < na; i++)
275             {
276                 xnb[j++] = x[a[i]][XX];
277                 xnb[j++] = x[a[i]][YY];
278                 xnb[j++] = x[a[i]][ZZ];
279                 j++;
280             }
281             /* Complete the partially filled last cell with particles far apart */
282             for (; i < na_round; i++)
283             {
284                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cx);
285                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cy);
286                 xnb[j++] = -NBAT_FAR_AWAY*(1 + cz + i);
287                 j++;
288             }
289             break;
290         case nbatX4:
291             j = X4_IND_A(a0);
292             c = a0 & (PACK_X4-1);
293             for (i = 0; i < na; i++)
294             {
295                 xnb[j+XX*PACK_X4] = x[a[i]][XX];
296                 xnb[j+YY*PACK_X4] = x[a[i]][YY];
297                 xnb[j+ZZ*PACK_X4] = x[a[i]][ZZ];
298                 j++;
299                 c++;
300                 if (c == PACK_X4)
301                 {
302                     j += (DIM-1)*PACK_X4;
303                     c  = 0;
304                 }
305             }
306             /* Complete the partially filled last cell with particles far apart */
307             for (; i < na_round; i++)
308             {
309                 xnb[j+XX*PACK_X4] = -NBAT_FAR_AWAY*(1 + cx);
310                 xnb[j+YY*PACK_X4] = -NBAT_FAR_AWAY*(1 + cy);
311                 xnb[j+ZZ*PACK_X4] = -NBAT_FAR_AWAY*(1 + cz + i);
312                 j++;
313                 c++;
314                 if (c == PACK_X4)
315                 {
316                     j += (DIM-1)*PACK_X4;
317                     c  = 0;
318                 }
319             }
320             break;
321         case nbatX8:
322             j = X8_IND_A(a0);
323             c = a0 & (PACK_X8 - 1);
324             for (i = 0; i < na; i++)
325             {
326                 xnb[j+XX*PACK_X8] = x[a[i]][XX];
327                 xnb[j+YY*PACK_X8] = x[a[i]][YY];
328                 xnb[j+ZZ*PACK_X8] = x[a[i]][ZZ];
329                 j++;
330                 c++;
331                 if (c == PACK_X8)
332                 {
333                     j += (DIM-1)*PACK_X8;
334                     c  = 0;
335                 }
336             }
337             /* Complete the partially filled last cell with particles far apart */
338             for (; i < na_round; i++)
339             {
340                 xnb[j+XX*PACK_X8] = -NBAT_FAR_AWAY*(1 + cx);
341                 xnb[j+YY*PACK_X8] = -NBAT_FAR_AWAY*(1 + cy);
342                 xnb[j+ZZ*PACK_X8] = -NBAT_FAR_AWAY*(1 + cz + i);
343                 j++;
344                 c++;
345                 if (c == PACK_X8)
346                 {
347                     j += (DIM-1)*PACK_X8;
348                     c  = 0;
349                 }
350             }
351             break;
352         default:
353             gmx_incons("Unsupported nbnxn_atomdata_t format");
354     }
355 }
356
357 /* Determines the combination rule (or none) to be used, stores it,
358  * and sets the LJ parameters required with the rule.
359  */
360 static void set_combination_rule_data(nbnxn_atomdata_t *nbat)
361 {
362     int  nt, i, j;
363     real c6, c12;
364
365     nt = nbat->ntype;
366
367     switch (nbat->comb_rule)
368     {
369         case  ljcrGEOM:
370             nbat->comb_rule = ljcrGEOM;
371
372             for (i = 0; i < nt; i++)
373             {
374                 /* Copy the diagonal from the nbfp matrix */
375                 nbat->nbfp_comb[i*2  ] = sqrt(nbat->nbfp[(i*nt+i)*2  ]);
376                 nbat->nbfp_comb[i*2+1] = sqrt(nbat->nbfp[(i*nt+i)*2+1]);
377             }
378             break;
379         case ljcrLB:
380             for (i = 0; i < nt; i++)
381             {
382                 /* Get 6*C6 and 12*C12 from the diagonal of the nbfp matrix */
383                 c6  = nbat->nbfp[(i*nt+i)*2  ];
384                 c12 = nbat->nbfp[(i*nt+i)*2+1];
385                 if (c6 > 0 && c12 > 0)
386                 {
387                     /* We store 0.5*2^1/6*sigma and sqrt(4*3*eps),
388                      * so we get 6*C6 and 12*C12 after combining.
389                      */
390                     nbat->nbfp_comb[i*2  ] = 0.5*pow(c12/c6, 1.0/6.0);
391                     nbat->nbfp_comb[i*2+1] = sqrt(c6*c6/c12);
392                 }
393                 else
394                 {
395                     nbat->nbfp_comb[i*2  ] = 0;
396                     nbat->nbfp_comb[i*2+1] = 0;
397                 }
398             }
399             break;
400         case ljcrNONE:
401             /* nbfp_s4 stores two parameters using a stride of 4,
402              * because this would suit x86 SIMD single-precision
403              * quad-load intrinsics. There's a slight inefficiency in
404              * allocating and initializing nbfp_s4 when it might not
405              * be used, but introducing the conditional code is not
406              * really worth it. */
407             nbat->alloc((void **)&nbat->nbfp_s4, nt*nt*4*sizeof(*nbat->nbfp_s4));
408             for (i = 0; i < nt; i++)
409             {
410                 for (j = 0; j < nt; j++)
411                 {
412                     nbat->nbfp_s4[(i*nt+j)*4+0] = nbat->nbfp[(i*nt+j)*2+0];
413                     nbat->nbfp_s4[(i*nt+j)*4+1] = nbat->nbfp[(i*nt+j)*2+1];
414                     nbat->nbfp_s4[(i*nt+j)*4+2] = 0;
415                     nbat->nbfp_s4[(i*nt+j)*4+3] = 0;
416                 }
417             }
418             break;
419         default:
420             gmx_incons("Unknown combination rule");
421             break;
422     }
423 }
424
425 #ifdef GMX_NBNXN_SIMD
426 static void
427 nbnxn_atomdata_init_simple_exclusion_masks(nbnxn_atomdata_t *nbat)
428 {
429     int       i, j;
430     const int simd_width = GMX_SIMD_WIDTH_HERE;
431     int       simd_excl_size;
432     /* Set the diagonal cluster pair exclusion mask setup data.
433      * In the kernel we check 0 < j - i to generate the masks.
434      * Here we store j - i for generating the mask for the first i,
435      * we substract 0.5 to avoid rounding issues.
436      * In the kernel we can subtract 1 to generate the subsequent mask.
437      */
438     int        simd_4xn_diag_size;
439     const real simdFalse = -1, simdTrue = 1;
440     real      *simd_interaction_array;
441
442     simd_4xn_diag_size = max(NBNXN_CPU_CLUSTER_I_SIZE, simd_width);
443     snew_aligned(nbat->simd_4xn_diagonal_j_minus_i, simd_4xn_diag_size, NBNXN_MEM_ALIGN);
444     for (j = 0; j < simd_4xn_diag_size; j++)
445     {
446         nbat->simd_4xn_diagonal_j_minus_i[j] = j - 0.5;
447     }
448
449     snew_aligned(nbat->simd_2xnn_diagonal_j_minus_i, simd_width, NBNXN_MEM_ALIGN);
450     for (j = 0; j < simd_width/2; j++)
451     {
452         /* The j-cluster size is half the SIMD width */
453         nbat->simd_2xnn_diagonal_j_minus_i[j]              = j - 0.5;
454         /* The next half of the SIMD width is for i + 1 */
455         nbat->simd_2xnn_diagonal_j_minus_i[simd_width/2+j] = j - 1 - 0.5;
456     }
457
458     /* We use up to 32 bits for exclusion masking.
459      * The same masks are used for the 4xN and 2x(N+N) kernels.
460      * The masks are read either into epi32 SIMD registers or into
461      * real SIMD registers (together with a cast).
462      * In single precision this means the real and epi32 SIMD registers
463      * are of equal size.
464      * In double precision the epi32 registers can be smaller than
465      * the real registers, so depending on the architecture, we might
466      * need to use two, identical, 32-bit masks per real.
467      */
468     simd_excl_size = NBNXN_CPU_CLUSTER_I_SIZE*simd_width;
469     snew_aligned(nbat->simd_exclusion_filter1, simd_excl_size,   NBNXN_MEM_ALIGN);
470     snew_aligned(nbat->simd_exclusion_filter2, simd_excl_size*2, NBNXN_MEM_ALIGN);
471
472     for (j = 0; j < simd_excl_size; j++)
473     {
474         /* Set the consecutive bits for masking pair exclusions */
475         nbat->simd_exclusion_filter1[j]       = (1U << j);
476         nbat->simd_exclusion_filter2[j*2 + 0] = (1U << j);
477         nbat->simd_exclusion_filter2[j*2 + 1] = (1U << j);
478     }
479
480 #if (defined GMX_CPU_ACCELERATION_IBM_QPX)
481     /* The QPX kernels shouldn't do the bit masking that is done on
482      * x86, because the SIMD units lack bit-wise operations. Instead,
483      * we generate a vector of all 2^4 possible ways an i atom
484      * interacts with its 4 j atoms. Each array entry contains
485      * simd_width signed ints that are read in a single SIMD
486      * load. These ints must contain values that will be interpreted
487      * as true and false when loaded in the SIMD floating-point
488      * registers, ie. any positive or any negative value,
489      * respectively. Each array entry encodes how this i atom will
490      * interact with the 4 j atoms. Matching code exists in
491      * set_ci_top_excls() to generate indices into this array. Those
492      * indices are used in the kernels. */
493
494     simd_excl_size = NBNXN_CPU_CLUSTER_I_SIZE*NBNXN_CPU_CLUSTER_I_SIZE;
495     const int qpx_simd_width = GMX_SIMD_WIDTH_HERE;
496     snew_aligned(simd_interaction_array, simd_excl_size * qpx_simd_width, NBNXN_MEM_ALIGN);
497     for (j = 0; j < simd_excl_size; j++)
498     {
499         int index = j * qpx_simd_width;
500         for (i = 0; i < qpx_simd_width; i++)
501         {
502             simd_interaction_array[index + i] = (j & (1 << i)) ? simdTrue : simdFalse;
503         }
504     }
505     nbat->simd_interaction_array = simd_interaction_array;
506 #endif
507 }
508 #endif
509
510 /* Initializes an nbnxn_atomdata_t data structure */
511 void nbnxn_atomdata_init(FILE *fp,
512                          nbnxn_atomdata_t *nbat,
513                          int nb_kernel_type,
514                          int ntype, const real *nbfp,
515                          int n_energygroups,
516                          int nout,
517                          nbnxn_alloc_t *alloc,
518                          nbnxn_free_t  *free)
519 {
520     int      i, j;
521     real     c6, c12, tol;
522     char    *ptr;
523     gmx_bool simple, bCombGeom, bCombLB;
524
525     if (alloc == NULL)
526     {
527         nbat->alloc = nbnxn_alloc_aligned;
528     }
529     else
530     {
531         nbat->alloc = alloc;
532     }
533     if (free == NULL)
534     {
535         nbat->free = nbnxn_free_aligned;
536     }
537     else
538     {
539         nbat->free = free;
540     }
541
542     if (debug)
543     {
544         fprintf(debug, "There are %d atom types in the system, adding one for nbnxn_atomdata_t\n", ntype);
545     }
546     nbat->ntype = ntype + 1;
547     nbat->alloc((void **)&nbat->nbfp,
548                 nbat->ntype*nbat->ntype*2*sizeof(*nbat->nbfp));
549     nbat->alloc((void **)&nbat->nbfp_comb, nbat->ntype*2*sizeof(*nbat->nbfp_comb));
550
551     /* A tolerance of 1e-5 seems reasonable for (possibly hand-typed)
552      * force-field floating point parameters.
553      */
554     tol = 1e-5;
555     ptr = getenv("GMX_LJCOMB_TOL");
556     if (ptr != NULL)
557     {
558         double dbl;
559
560         sscanf(ptr, "%lf", &dbl);
561         tol = dbl;
562     }
563     bCombGeom = TRUE;
564     bCombLB   = TRUE;
565
566     /* Temporarily fill nbat->nbfp_comb with sigma and epsilon
567      * to check for the LB rule.
568      */
569     for (i = 0; i < ntype; i++)
570     {
571         c6  = nbfp[(i*ntype+i)*2  ]/6.0;
572         c12 = nbfp[(i*ntype+i)*2+1]/12.0;
573         if (c6 > 0 && c12 > 0)
574         {
575             nbat->nbfp_comb[i*2  ] = pow(c12/c6, 1.0/6.0);
576             nbat->nbfp_comb[i*2+1] = 0.25*c6*c6/c12;
577         }
578         else if (c6 == 0 && c12 == 0)
579         {
580             nbat->nbfp_comb[i*2  ] = 0;
581             nbat->nbfp_comb[i*2+1] = 0;
582         }
583         else
584         {
585             /* Can not use LB rule with only dispersion or repulsion */
586             bCombLB = FALSE;
587         }
588     }
589
590     for (i = 0; i < nbat->ntype; i++)
591     {
592         for (j = 0; j < nbat->ntype; j++)
593         {
594             if (i < ntype && j < ntype)
595             {
596                 /* fr->nbfp has been updated, so that array too now stores c6/c12 including
597                  * the 6.0/12.0 prefactors to save 2 flops in the most common case (force-only).
598                  */
599                 c6  = nbfp[(i*ntype+j)*2  ];
600                 c12 = nbfp[(i*ntype+j)*2+1];
601                 nbat->nbfp[(i*nbat->ntype+j)*2  ] = c6;
602                 nbat->nbfp[(i*nbat->ntype+j)*2+1] = c12;
603
604                 /* Compare 6*C6 and 12*C12 for geometric cobination rule */
605                 bCombGeom = bCombGeom &&
606                     gmx_within_tol(c6*c6, nbfp[(i*ntype+i)*2  ]*nbfp[(j*ntype+j)*2  ], tol) &&
607                     gmx_within_tol(c12*c12, nbfp[(i*ntype+i)*2+1]*nbfp[(j*ntype+j)*2+1], tol);
608
609                 /* Compare C6 and C12 for Lorentz-Berthelot combination rule */
610                 c6     /= 6.0;
611                 c12    /= 12.0;
612                 bCombLB = bCombLB &&
613                     ((c6 == 0 && c12 == 0 &&
614                       (nbat->nbfp_comb[i*2+1] == 0 || nbat->nbfp_comb[j*2+1] == 0)) ||
615                      (c6 > 0 && c12 > 0 &&
616                       gmx_within_tol(pow(c12/c6, 1.0/6.0), 0.5*(nbat->nbfp_comb[i*2]+nbat->nbfp_comb[j*2]), tol) &&
617                       gmx_within_tol(0.25*c6*c6/c12, sqrt(nbat->nbfp_comb[i*2+1]*nbat->nbfp_comb[j*2+1]), tol)));
618             }
619             else
620             {
621                 /* Add zero parameters for the additional dummy atom type */
622                 nbat->nbfp[(i*nbat->ntype+j)*2  ] = 0;
623                 nbat->nbfp[(i*nbat->ntype+j)*2+1] = 0;
624             }
625         }
626     }
627     if (debug)
628     {
629         fprintf(debug, "Combination rules: geometric %d Lorentz-Berthelot %d\n",
630                 bCombGeom, bCombLB);
631     }
632
633     simple = nbnxn_kernel_pairlist_simple(nb_kernel_type);
634
635     if (simple)
636     {
637         /* We prefer the geometic combination rule,
638          * as that gives a slightly faster kernel than the LB rule.
639          */
640         if (bCombGeom)
641         {
642             nbat->comb_rule = ljcrGEOM;
643         }
644         else if (bCombLB)
645         {
646             nbat->comb_rule = ljcrLB;
647         }
648         else
649         {
650             nbat->comb_rule = ljcrNONE;
651
652             nbat->free(nbat->nbfp_comb);
653         }
654
655         if (fp)
656         {
657             if (nbat->comb_rule == ljcrNONE)
658             {
659                 fprintf(fp, "Using full Lennard-Jones parameter combination matrix\n\n");
660             }
661             else
662             {
663                 fprintf(fp, "Using %s Lennard-Jones combination rule\n\n",
664                         nbat->comb_rule == ljcrGEOM ? "geometric" : "Lorentz-Berthelot");
665             }
666         }
667
668         set_combination_rule_data(nbat);
669     }
670     else
671     {
672         nbat->comb_rule = ljcrNONE;
673
674         nbat->free(nbat->nbfp_comb);
675     }
676
677     nbat->natoms  = 0;
678     nbat->type    = NULL;
679     nbat->lj_comb = NULL;
680     if (simple)
681     {
682         int pack_x;
683
684         switch (nb_kernel_type)
685         {
686             case nbnxnk4xN_SIMD_4xN:
687             case nbnxnk4xN_SIMD_2xNN:
688                 pack_x = max(NBNXN_CPU_CLUSTER_I_SIZE,
689                              nbnxn_kernel_to_cj_size(nb_kernel_type));
690                 switch (pack_x)
691                 {
692                     case 4:
693                         nbat->XFormat = nbatX4;
694                         break;
695                     case 8:
696                         nbat->XFormat = nbatX8;
697                         break;
698                     default:
699                         gmx_incons("Unsupported packing width");
700                 }
701                 break;
702             default:
703                 nbat->XFormat = nbatXYZ;
704                 break;
705         }
706
707         nbat->FFormat = nbat->XFormat;
708     }
709     else
710     {
711         nbat->XFormat = nbatXYZQ;
712         nbat->FFormat = nbatXYZ;
713     }
714     nbat->q        = NULL;
715     nbat->nenergrp = n_energygroups;
716     if (!simple)
717     {
718         /* Energy groups not supported yet for super-sub lists */
719         if (n_energygroups > 1 && fp != NULL)
720         {
721             fprintf(fp, "\nNOTE: With GPUs, reporting energy group contributions is not supported\n\n");
722         }
723         nbat->nenergrp = 1;
724     }
725     /* Temporary storage goes as #grp^3*simd_width^2/2, so limit to 64 */
726     if (nbat->nenergrp > 64)
727     {
728         gmx_fatal(FARGS, "With NxN kernels not more than 64 energy groups are supported\n");
729     }
730     nbat->neg_2log = 1;
731     while (nbat->nenergrp > (1<<nbat->neg_2log))
732     {
733         nbat->neg_2log++;
734     }
735     nbat->energrp = NULL;
736     nbat->alloc((void **)&nbat->shift_vec, SHIFTS*sizeof(*nbat->shift_vec));
737     nbat->xstride = (nbat->XFormat == nbatXYZQ ? STRIDE_XYZQ : DIM);
738     nbat->fstride = (nbat->FFormat == nbatXYZQ ? STRIDE_XYZQ : DIM);
739     nbat->x       = NULL;
740
741 #ifdef GMX_NBNXN_SIMD
742     if (simple)
743     {
744         nbnxn_atomdata_init_simple_exclusion_masks(nbat);
745     }
746 #endif
747
748     /* Initialize the output data structures */
749     nbat->nout    = nout;
750     snew(nbat->out, nbat->nout);
751     nbat->nalloc  = 0;
752     for (i = 0; i < nbat->nout; i++)
753     {
754         nbnxn_atomdata_output_init(&nbat->out[i],
755                                    nb_kernel_type,
756                                    nbat->nenergrp, 1<<nbat->neg_2log,
757                                    nbat->alloc);
758     }
759     nbat->buffer_flags.flag        = NULL;
760     nbat->buffer_flags.flag_nalloc = 0;
761 }
762
763 static void copy_lj_to_nbat_lj_comb_x4(const real *ljparam_type,
764                                        const int *type, int na,
765                                        real *ljparam_at)
766 {
767     int is, k, i;
768
769     /* The LJ params follow the combination rule:
770      * copy the params for the type array to the atom array.
771      */
772     for (is = 0; is < na; is += PACK_X4)
773     {
774         for (k = 0; k < PACK_X4; k++)
775         {
776             i = is + k;
777             ljparam_at[is*2        +k] = ljparam_type[type[i]*2  ];
778             ljparam_at[is*2+PACK_X4+k] = ljparam_type[type[i]*2+1];
779         }
780     }
781 }
782
783 static void copy_lj_to_nbat_lj_comb_x8(const real *ljparam_type,
784                                        const int *type, int na,
785                                        real *ljparam_at)
786 {
787     int is, k, i;
788
789     /* The LJ params follow the combination rule:
790      * copy the params for the type array to the atom array.
791      */
792     for (is = 0; is < na; is += PACK_X8)
793     {
794         for (k = 0; k < PACK_X8; k++)
795         {
796             i = is + k;
797             ljparam_at[is*2        +k] = ljparam_type[type[i]*2  ];
798             ljparam_at[is*2+PACK_X8+k] = ljparam_type[type[i]*2+1];
799         }
800     }
801 }
802
803 /* Sets the atom type and LJ data in nbnxn_atomdata_t */
804 static void nbnxn_atomdata_set_atomtypes(nbnxn_atomdata_t    *nbat,
805                                          int                  ngrid,
806                                          const nbnxn_search_t nbs,
807                                          const int           *type)
808 {
809     int                 g, i, ncz, ash;
810     const nbnxn_grid_t *grid;
811
812     for (g = 0; g < ngrid; g++)
813     {
814         grid = &nbs->grid[g];
815
816         /* Loop over all columns and copy and fill */
817         for (i = 0; i < grid->ncx*grid->ncy; i++)
818         {
819             ncz = grid->cxy_ind[i+1] - grid->cxy_ind[i];
820             ash = (grid->cell0 + grid->cxy_ind[i])*grid->na_sc;
821
822             copy_int_to_nbat_int(nbs->a+ash, grid->cxy_na[i], ncz*grid->na_sc,
823                                  type, nbat->ntype-1, nbat->type+ash);
824
825             if (nbat->comb_rule != ljcrNONE)
826             {
827                 if (nbat->XFormat == nbatX4)
828                 {
829                     copy_lj_to_nbat_lj_comb_x4(nbat->nbfp_comb,
830                                                nbat->type+ash, ncz*grid->na_sc,
831                                                nbat->lj_comb+ash*2);
832                 }
833                 else if (nbat->XFormat == nbatX8)
834                 {
835                     copy_lj_to_nbat_lj_comb_x8(nbat->nbfp_comb,
836                                                nbat->type+ash, ncz*grid->na_sc,
837                                                nbat->lj_comb+ash*2);
838                 }
839             }
840         }
841     }
842 }
843
844 /* Sets the charges in nbnxn_atomdata_t *nbat */
845 static void nbnxn_atomdata_set_charges(nbnxn_atomdata_t    *nbat,
846                                        int                  ngrid,
847                                        const nbnxn_search_t nbs,
848                                        const real          *charge)
849 {
850     int                 g, cxy, ncz, ash, na, na_round, i, j;
851     real               *q;
852     const nbnxn_grid_t *grid;
853
854     for (g = 0; g < ngrid; g++)
855     {
856         grid = &nbs->grid[g];
857
858         /* Loop over all columns and copy and fill */
859         for (cxy = 0; cxy < grid->ncx*grid->ncy; cxy++)
860         {
861             ash      = (grid->cell0 + grid->cxy_ind[cxy])*grid->na_sc;
862             na       = grid->cxy_na[cxy];
863             na_round = (grid->cxy_ind[cxy+1] - grid->cxy_ind[cxy])*grid->na_sc;
864
865             if (nbat->XFormat == nbatXYZQ)
866             {
867                 q = nbat->x + ash*STRIDE_XYZQ + ZZ + 1;
868                 for (i = 0; i < na; i++)
869                 {
870                     *q = charge[nbs->a[ash+i]];
871                     q += STRIDE_XYZQ;
872                 }
873                 /* Complete the partially filled last cell with zeros */
874                 for (; i < na_round; i++)
875                 {
876                     *q = 0;
877                     q += STRIDE_XYZQ;
878                 }
879             }
880             else
881             {
882                 q = nbat->q + ash;
883                 for (i = 0; i < na; i++)
884                 {
885                     *q = charge[nbs->a[ash+i]];
886                     q++;
887                 }
888                 /* Complete the partially filled last cell with zeros */
889                 for (; i < na_round; i++)
890                 {
891                     *q = 0;
892                     q++;
893                 }
894             }
895         }
896     }
897 }
898
899 /* Copies the energy group indices to a reordered and packed array */
900 static void copy_egp_to_nbat_egps(const int *a, int na, int na_round,
901                                   int na_c, int bit_shift,
902                                   const int *in, int *innb)
903 {
904     int i, j, sa, at;
905     int comb;
906
907     j = 0;
908     for (i = 0; i < na; i += na_c)
909     {
910         /* Store na_c energy group numbers into one int */
911         comb = 0;
912         for (sa = 0; sa < na_c; sa++)
913         {
914             at = a[i+sa];
915             if (at >= 0)
916             {
917                 comb |= (GET_CGINFO_GID(in[at]) << (sa*bit_shift));
918             }
919         }
920         innb[j++] = comb;
921     }
922     /* Complete the partially filled last cell with fill */
923     for (; i < na_round; i += na_c)
924     {
925         innb[j++] = 0;
926     }
927 }
928
929 /* Set the energy group indices for atoms in nbnxn_atomdata_t */
930 static void nbnxn_atomdata_set_energygroups(nbnxn_atomdata_t    *nbat,
931                                             int                  ngrid,
932                                             const nbnxn_search_t nbs,
933                                             const int           *atinfo)
934 {
935     int                 g, i, ncz, ash;
936     const nbnxn_grid_t *grid;
937
938     for (g = 0; g < ngrid; g++)
939     {
940         grid = &nbs->grid[g];
941
942         /* Loop over all columns and copy and fill */
943         for (i = 0; i < grid->ncx*grid->ncy; i++)
944         {
945             ncz = grid->cxy_ind[i+1] - grid->cxy_ind[i];
946             ash = (grid->cell0 + grid->cxy_ind[i])*grid->na_sc;
947
948             copy_egp_to_nbat_egps(nbs->a+ash, grid->cxy_na[i], ncz*grid->na_sc,
949                                   nbat->na_c, nbat->neg_2log,
950                                   atinfo, nbat->energrp+(ash>>grid->na_c_2log));
951         }
952     }
953 }
954
955 /* Sets all required atom parameter data in nbnxn_atomdata_t */
956 void nbnxn_atomdata_set(nbnxn_atomdata_t    *nbat,
957                         int                  locality,
958                         const nbnxn_search_t nbs,
959                         const t_mdatoms     *mdatoms,
960                         const int           *atinfo)
961 {
962     int ngrid;
963
964     if (locality == eatLocal)
965     {
966         ngrid = 1;
967     }
968     else
969     {
970         ngrid = nbs->ngrid;
971     }
972
973     nbnxn_atomdata_set_atomtypes(nbat, ngrid, nbs, mdatoms->typeA);
974
975     nbnxn_atomdata_set_charges(nbat, ngrid, nbs, mdatoms->chargeA);
976
977     if (nbat->nenergrp > 1)
978     {
979         nbnxn_atomdata_set_energygroups(nbat, ngrid, nbs, atinfo);
980     }
981 }
982
983 /* Copies the shift vector array to nbnxn_atomdata_t */
984 void nbnxn_atomdata_copy_shiftvec(gmx_bool          bDynamicBox,
985                                   rvec             *shift_vec,
986                                   nbnxn_atomdata_t *nbat)
987 {
988     int i;
989
990     nbat->bDynamicBox = bDynamicBox;
991     for (i = 0; i < SHIFTS; i++)
992     {
993         copy_rvec(shift_vec[i], nbat->shift_vec[i]);
994     }
995 }
996
997 /* Copies (and reorders) the coordinates to nbnxn_atomdata_t */
998 void nbnxn_atomdata_copy_x_to_nbat_x(const nbnxn_search_t nbs,
999                                      int                  locality,
1000                                      gmx_bool             FillLocal,
1001                                      rvec                *x,
1002                                      nbnxn_atomdata_t    *nbat)
1003 {
1004     int g0 = 0, g1 = 0;
1005     int nth, th;
1006
1007     switch (locality)
1008     {
1009         case eatAll:
1010             g0 = 0;
1011             g1 = nbs->ngrid;
1012             break;
1013         case eatLocal:
1014             g0 = 0;
1015             g1 = 1;
1016             break;
1017         case eatNonlocal:
1018             g0 = 1;
1019             g1 = nbs->ngrid;
1020             break;
1021     }
1022
1023     if (FillLocal)
1024     {
1025         nbat->natoms_local = nbs->grid[0].nc*nbs->grid[0].na_sc;
1026     }
1027
1028     nth = gmx_omp_nthreads_get(emntPairsearch);
1029
1030 #pragma omp parallel for num_threads(nth) schedule(static)
1031     for (th = 0; th < nth; th++)
1032     {
1033         int g;
1034
1035         for (g = g0; g < g1; g++)
1036         {
1037             const nbnxn_grid_t *grid;
1038             int                 cxy0, cxy1, cxy;
1039
1040             grid = &nbs->grid[g];
1041
1042             cxy0 = (grid->ncx*grid->ncy* th   +nth-1)/nth;
1043             cxy1 = (grid->ncx*grid->ncy*(th+1)+nth-1)/nth;
1044
1045             for (cxy = cxy0; cxy < cxy1; cxy++)
1046             {
1047                 int na, ash, na_fill;
1048
1049                 na  = grid->cxy_na[cxy];
1050                 ash = (grid->cell0 + grid->cxy_ind[cxy])*grid->na_sc;
1051
1052                 if (g == 0 && FillLocal)
1053                 {
1054                     na_fill =
1055                         (grid->cxy_ind[cxy+1] - grid->cxy_ind[cxy])*grid->na_sc;
1056                 }
1057                 else
1058                 {
1059                     /* We fill only the real particle locations.
1060                      * We assume the filling entries at the end have been
1061                      * properly set before during ns.
1062                      */
1063                     na_fill = na;
1064                 }
1065                 copy_rvec_to_nbat_real(nbs->a+ash, na, na_fill, x,
1066                                        nbat->XFormat, nbat->x, ash,
1067                                        0, 0, 0);
1068             }
1069         }
1070     }
1071 }
1072
1073 static void
1074 nbnxn_atomdata_clear_reals(real * gmx_restrict dest,
1075                            int i0, int i1)
1076 {
1077     int i;
1078
1079     for (i = i0; i < i1; i++)
1080     {
1081         dest[i] = 0;
1082     }
1083 }
1084
1085 static void
1086 nbnxn_atomdata_reduce_reals(real * gmx_restrict dest,
1087                             gmx_bool bDestSet,
1088                             real ** gmx_restrict src,
1089                             int nsrc,
1090                             int i0, int i1)
1091 {
1092     int i, s;
1093
1094     if (bDestSet)
1095     {
1096         /* The destination buffer contains data, add to it */
1097         for (i = i0; i < i1; i++)
1098         {
1099             for (s = 0; s < nsrc; s++)
1100             {
1101                 dest[i] += src[s][i];
1102             }
1103         }
1104     }
1105     else
1106     {
1107         /* The destination buffer is unitialized, set it first */
1108         for (i = i0; i < i1; i++)
1109         {
1110             dest[i] = src[0][i];
1111             for (s = 1; s < nsrc; s++)
1112             {
1113                 dest[i] += src[s][i];
1114             }
1115         }
1116     }
1117 }
1118
1119 static void
1120 nbnxn_atomdata_reduce_reals_simd(real gmx_unused * gmx_restrict dest,
1121                                  gmx_bool gmx_unused bDestSet,
1122                                  real gmx_unused ** gmx_restrict src,
1123                                  int gmx_unused nsrc,
1124                                  int gmx_unused i0, int gmx_unused i1)
1125 {
1126 #ifdef GMX_NBNXN_SIMD
1127 /* The SIMD width here is actually independent of that in the kernels,
1128  * but we use the same width for simplicity (usually optimal anyhow).
1129  */
1130     int       i, s;
1131     gmx_mm_pr dest_SSE, src_SSE;
1132
1133     if (bDestSet)
1134     {
1135         for (i = i0; i < i1; i += GMX_SIMD_WIDTH_HERE)
1136         {
1137             dest_SSE = gmx_load_pr(dest+i);
1138             for (s = 0; s < nsrc; s++)
1139             {
1140                 src_SSE  = gmx_load_pr(src[s]+i);
1141                 dest_SSE = gmx_add_pr(dest_SSE, src_SSE);
1142             }
1143             gmx_store_pr(dest+i, dest_SSE);
1144         }
1145     }
1146     else
1147     {
1148         for (i = i0; i < i1; i += GMX_SIMD_WIDTH_HERE)
1149         {
1150             dest_SSE = gmx_load_pr(src[0]+i);
1151             for (s = 1; s < nsrc; s++)
1152             {
1153                 src_SSE  = gmx_load_pr(src[s]+i);
1154                 dest_SSE = gmx_add_pr(dest_SSE, src_SSE);
1155             }
1156             gmx_store_pr(dest+i, dest_SSE);
1157         }
1158     }
1159 #endif
1160 }
1161
1162 /* Add part of the force array(s) from nbnxn_atomdata_t to f */
1163 static void
1164 nbnxn_atomdata_add_nbat_f_to_f_part(const nbnxn_search_t nbs,
1165                                     const nbnxn_atomdata_t *nbat,
1166                                     nbnxn_atomdata_output_t *out,
1167                                     int nfa,
1168                                     int a0, int a1,
1169                                     rvec *f)
1170 {
1171     int         a, i, fa;
1172     const int  *cell;
1173     const real *fnb;
1174
1175     cell = nbs->cell;
1176
1177     /* Loop over all columns and copy and fill */
1178     switch (nbat->FFormat)
1179     {
1180         case nbatXYZ:
1181         case nbatXYZQ:
1182             if (nfa == 1)
1183             {
1184                 fnb = out[0].f;
1185
1186                 for (a = a0; a < a1; a++)
1187                 {
1188                     i = cell[a]*nbat->fstride;
1189
1190                     f[a][XX] += fnb[i];
1191                     f[a][YY] += fnb[i+1];
1192                     f[a][ZZ] += fnb[i+2];
1193                 }
1194             }
1195             else
1196             {
1197                 for (a = a0; a < a1; a++)
1198                 {
1199                     i = cell[a]*nbat->fstride;
1200
1201                     for (fa = 0; fa < nfa; fa++)
1202                     {
1203                         f[a][XX] += out[fa].f[i];
1204                         f[a][YY] += out[fa].f[i+1];
1205                         f[a][ZZ] += out[fa].f[i+2];
1206                     }
1207                 }
1208             }
1209             break;
1210         case nbatX4:
1211             if (nfa == 1)
1212             {
1213                 fnb = out[0].f;
1214
1215                 for (a = a0; a < a1; a++)
1216                 {
1217                     i = X4_IND_A(cell[a]);
1218
1219                     f[a][XX] += fnb[i+XX*PACK_X4];
1220                     f[a][YY] += fnb[i+YY*PACK_X4];
1221                     f[a][ZZ] += fnb[i+ZZ*PACK_X4];
1222                 }
1223             }
1224             else
1225             {
1226                 for (a = a0; a < a1; a++)
1227                 {
1228                     i = X4_IND_A(cell[a]);
1229
1230                     for (fa = 0; fa < nfa; fa++)
1231                     {
1232                         f[a][XX] += out[fa].f[i+XX*PACK_X4];
1233                         f[a][YY] += out[fa].f[i+YY*PACK_X4];
1234                         f[a][ZZ] += out[fa].f[i+ZZ*PACK_X4];
1235                     }
1236                 }
1237             }
1238             break;
1239         case nbatX8:
1240             if (nfa == 1)
1241             {
1242                 fnb = out[0].f;
1243
1244                 for (a = a0; a < a1; a++)
1245                 {
1246                     i = X8_IND_A(cell[a]);
1247
1248                     f[a][XX] += fnb[i+XX*PACK_X8];
1249                     f[a][YY] += fnb[i+YY*PACK_X8];
1250                     f[a][ZZ] += fnb[i+ZZ*PACK_X8];
1251                 }
1252             }
1253             else
1254             {
1255                 for (a = a0; a < a1; a++)
1256                 {
1257                     i = X8_IND_A(cell[a]);
1258
1259                     for (fa = 0; fa < nfa; fa++)
1260                     {
1261                         f[a][XX] += out[fa].f[i+XX*PACK_X8];
1262                         f[a][YY] += out[fa].f[i+YY*PACK_X8];
1263                         f[a][ZZ] += out[fa].f[i+ZZ*PACK_X8];
1264                     }
1265                 }
1266             }
1267             break;
1268         default:
1269             gmx_incons("Unsupported nbnxn_atomdata_t format");
1270     }
1271 }
1272
1273 /* Add the force array(s) from nbnxn_atomdata_t to f */
1274 void nbnxn_atomdata_add_nbat_f_to_f(const nbnxn_search_t    nbs,
1275                                     int                     locality,
1276                                     const nbnxn_atomdata_t *nbat,
1277                                     rvec                   *f)
1278 {
1279     int a0 = 0, na = 0;
1280     int nth, th;
1281
1282     nbs_cycle_start(&nbs->cc[enbsCCreducef]);
1283
1284     switch (locality)
1285     {
1286         case eatAll:
1287             a0 = 0;
1288             na = nbs->natoms_nonlocal;
1289             break;
1290         case eatLocal:
1291             a0 = 0;
1292             na = nbs->natoms_local;
1293             break;
1294         case eatNonlocal:
1295             a0 = nbs->natoms_local;
1296             na = nbs->natoms_nonlocal - nbs->natoms_local;
1297             break;
1298     }
1299
1300     nth = gmx_omp_nthreads_get(emntNonbonded);
1301
1302     if (nbat->nout > 1)
1303     {
1304         if (locality != eatAll)
1305         {
1306             gmx_incons("add_f_to_f called with nout>1 and locality!=eatAll");
1307         }
1308
1309         /* Reduce the force thread output buffers into buffer 0, before adding
1310          * them to the, differently ordered, "real" force buffer.
1311          */
1312 #pragma omp parallel for num_threads(nth) schedule(static)
1313         for (th = 0; th < nth; th++)
1314         {
1315             const nbnxn_buffer_flags_t *flags;
1316             int   b0, b1, b;
1317             int   i0, i1;
1318             int   nfptr;
1319             real *fptr[NBNXN_BUFFERFLAG_MAX_THREADS];
1320             int   out;
1321
1322             flags = &nbat->buffer_flags;
1323
1324             /* Calculate the cell-block range for our thread */
1325             b0 = (flags->nflag* th   )/nth;
1326             b1 = (flags->nflag*(th+1))/nth;
1327
1328             for (b = b0; b < b1; b++)
1329             {
1330                 i0 =  b   *NBNXN_BUFFERFLAG_SIZE*nbat->fstride;
1331                 i1 = (b+1)*NBNXN_BUFFERFLAG_SIZE*nbat->fstride;
1332
1333                 nfptr = 0;
1334                 for (out = 1; out < nbat->nout; out++)
1335                 {
1336                     if (flags->flag[b] & (1U<<out))
1337                     {
1338                         fptr[nfptr++] = nbat->out[out].f;
1339                     }
1340                 }
1341                 if (nfptr > 0)
1342                 {
1343 #ifdef GMX_NBNXN_SIMD
1344                     nbnxn_atomdata_reduce_reals_simd
1345 #else
1346                     nbnxn_atomdata_reduce_reals
1347 #endif
1348                         (nbat->out[0].f,
1349                         flags->flag[b] & (1U<<0),
1350                         fptr, nfptr,
1351                         i0, i1);
1352                 }
1353                 else if (!(flags->flag[b] & (1U<<0)))
1354                 {
1355                     nbnxn_atomdata_clear_reals(nbat->out[0].f,
1356                                                i0, i1);
1357                 }
1358             }
1359         }
1360     }
1361
1362 #pragma omp parallel for num_threads(nth) schedule(static)
1363     for (th = 0; th < nth; th++)
1364     {
1365         nbnxn_atomdata_add_nbat_f_to_f_part(nbs, nbat,
1366                                             nbat->out,
1367                                             1,
1368                                             a0+((th+0)*na)/nth,
1369                                             a0+((th+1)*na)/nth,
1370                                             f);
1371     }
1372
1373     nbs_cycle_stop(&nbs->cc[enbsCCreducef]);
1374 }
1375
1376 /* Adds the shift forces from nbnxn_atomdata_t to fshift */
1377 void nbnxn_atomdata_add_nbat_fshift_to_fshift(const nbnxn_atomdata_t *nbat,
1378                                               rvec                   *fshift)
1379 {
1380     const nbnxn_atomdata_output_t *out;
1381     int  th;
1382     int  s;
1383     rvec sum;
1384
1385     out = nbat->out;
1386
1387     for (s = 0; s < SHIFTS; s++)
1388     {
1389         clear_rvec(sum);
1390         for (th = 0; th < nbat->nout; th++)
1391         {
1392             sum[XX] += out[th].fshift[s*DIM+XX];
1393             sum[YY] += out[th].fshift[s*DIM+YY];
1394             sum[ZZ] += out[th].fshift[s*DIM+ZZ];
1395         }
1396         rvec_inc(fshift[s], sum);
1397     }
1398 }