fde2b423447f668b793d3850f3770f610b2857bb
[alexxy/gromacs.git] / src / gromacs / mdlib / ns.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2017,2018, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "ns.h"
40
41 #include <cmath>
42 #include <cstdlib>
43 #include <cstring>
44
45 #include <algorithm>
46
47 #include "gromacs/domdec/domdec.h"
48 #include "gromacs/domdec/domdec_struct.h"
49 #include "gromacs/gmxlib/network.h"
50 #include "gromacs/gmxlib/nrnb.h"
51 #include "gromacs/gmxlib/nonbonded/nonbonded.h"
52 #include "gromacs/math/functions.h"
53 #include "gromacs/math/utilities.h"
54 #include "gromacs/math/vec.h"
55 #include "gromacs/math/vecdump.h"
56 #include "gromacs/mdlib/nsgrid.h"
57 #include "gromacs/mdlib/qmmm.h"
58 #include "gromacs/mdtypes/commrec.h"
59 #include "gromacs/mdtypes/forcerec.h"
60 #include "gromacs/mdtypes/group.h"
61 #include "gromacs/mdtypes/inputrec.h"
62 #include "gromacs/mdtypes/md_enums.h"
63 #include "gromacs/pbcutil/ishift.h"
64 #include "gromacs/pbcutil/pbc.h"
65 #include "gromacs/topology/mtop_util.h"
66 #include "gromacs/utility/fatalerror.h"
67 #include "gromacs/utility/smalloc.h"
68
69 /*
70  *    E X C L U S I O N   H A N D L I N G
71  */
72
73 #ifdef DEBUG
74 static void SETEXCL_(t_excl e[], int i, int j)
75 {
76     e[j] = e[j] | (1<<i);
77 }
78 static void RMEXCL_(t_excl e[], int i, int j)
79 {
80     e[j] = e[j] & ~(1<<i);
81 }
82 static gmx_bool ISEXCL_(t_excl e[], int i, int j)
83 {
84     return (gmx_bool)(e[j] & (1<<i));
85 }
86 static gmx_bool NOTEXCL_(t_excl e[], int i, int j)
87 {
88     return !(ISEXCL(e, i, j));
89 }
90 #else
91 #define SETEXCL(e, i, j) (e)[int(j)] |= (1<<(int(i)))
92 #define RMEXCL(e, i, j)  (e)[int(j)] &= (~(1<<(int(i))))
93 #define ISEXCL(e, i, j)  static_cast<gmx_bool>((e)[(int(j))] & (1<<(int(i))))
94 #define NOTEXCL(e, i, j) !(ISEXCL(e, i, j))
95 #endif
96
97 static int
98 round_up_to_simd_width(int length, int simd_width)
99 {
100     int offset;
101
102     offset = (simd_width > 0) ? length % simd_width : 0;
103
104     return (offset == 0) ? length : length-offset+simd_width;
105 }
106 /************************************************
107  *
108  *  U T I L I T I E S    F O R    N S
109  *
110  ************************************************/
111
112 void reallocate_nblist(t_nblist *nl)
113 {
114     if (gmx_debug_at)
115     {
116         fprintf(debug, "reallocating neigborlist (ielec=%d, ivdw=%d, igeometry=%d, type=%d), maxnri=%d\n",
117                 nl->ielec, nl->ivdw, nl->igeometry, nl->type, nl->maxnri);
118     }
119     srenew(nl->iinr,   nl->maxnri);
120     if (nl->igeometry == GMX_NBLIST_GEOMETRY_CG_CG)
121     {
122         srenew(nl->iinr_end, nl->maxnri);
123     }
124     srenew(nl->gid,    nl->maxnri);
125     srenew(nl->shift,  nl->maxnri);
126     srenew(nl->jindex, nl->maxnri+1);
127 }
128
129
130 static void init_nblist(FILE *log, t_nblist *nl_sr,
131                         int maxsr,
132                         int ivdw, int ivdwmod,
133                         int ielec, int ielecmod,
134                         int igeometry, int type,
135                         gmx_bool bElecAndVdwSwitchDiffers)
136 {
137     t_nblist *nl;
138     int       homenr;
139
140     {
141         nl     = nl_sr;
142         homenr = maxsr;
143
144         if (nl == nullptr)
145         {
146             return;
147         }
148
149
150         /* Set coul/vdw in neighborlist, and for the normal loops we determine
151          * an index of which one to call.
152          */
153         nl->ivdw        = ivdw;
154         nl->ivdwmod     = ivdwmod;
155         nl->ielec       = ielec;
156         nl->ielecmod    = ielecmod;
157         nl->type        = type;
158         nl->igeometry   = igeometry;
159
160         if (nl->type == GMX_NBLIST_INTERACTION_FREE_ENERGY)
161         {
162             nl->igeometry  = GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE;
163         }
164
165         /* This will also set the simd_padding_width field */
166         gmx_nonbonded_set_kernel_pointers(log, nl, bElecAndVdwSwitchDiffers);
167
168         /* maxnri is influenced by the number of shifts (maximum is 8)
169          * and the number of energy groups.
170          * If it is not enough, nl memory will be reallocated during the run.
171          * 4 seems to be a reasonable factor, which only causes reallocation
172          * during runs with tiny and many energygroups.
173          */
174         nl->maxnri      = homenr*4;
175         nl->maxnrj      = 0;
176         nl->nri         = -1;
177         nl->nrj         = 0;
178         nl->iinr        = nullptr;
179         nl->gid         = nullptr;
180         nl->shift       = nullptr;
181         nl->jindex      = nullptr;
182         nl->jjnr        = nullptr;
183         nl->excl_fep    = nullptr;
184         reallocate_nblist(nl);
185         nl->jindex[0] = 0;
186
187         if (debug)
188         {
189             fprintf(debug, "Initiating neighbourlist (ielec=%d, ivdw=%d, type=%d) for %s interactions,\nwith %d SR atoms.\n",
190                     nl->ielec, nl->ivdw, nl->type, gmx_nblist_geometry_names[nl->igeometry], maxsr);
191         }
192     }
193 }
194
195 void init_neighbor_list(FILE *log, t_forcerec *fr, int homenr)
196 {
197     int        maxsr, maxsr_wat;
198     int        ielec, ivdw, ielecmod, ivdwmod, type;
199     int        igeometry_def, igeometry_w, igeometry_ww;
200     int        i;
201     gmx_bool   bElecAndVdwSwitchDiffers;
202     t_nblists *nbl;
203
204     /* maxsr     = homenr-fr->nWatMol*3; */
205     maxsr     = homenr;
206
207     if (maxsr < 0)
208     {
209         gmx_fatal(FARGS, "%s, %d: Negative number of short range atoms.\n"
210                   "Call your GROMACS dealer for assistance.", __FILE__, __LINE__);
211     }
212     /* This is just for initial allocation, so we do not reallocate
213      * all the nlist arrays many times in a row.
214      * The numbers seem very accurate, but they are uncritical.
215      */
216     maxsr_wat = std::min(fr->nWatMol, (homenr+2)/3);
217
218     /* Determine the values for ielec/ivdw. */
219     ielec                    = fr->nbkernel_elec_interaction;
220     ivdw                     = fr->nbkernel_vdw_interaction;
221     ielecmod                 = fr->nbkernel_elec_modifier;
222     ivdwmod                  = fr->nbkernel_vdw_modifier;
223     type                     = GMX_NBLIST_INTERACTION_STANDARD;
224     bElecAndVdwSwitchDiffers = ( (fr->ic->rcoulomb_switch != fr->ic->rvdw_switch) || (fr->ic->rcoulomb != fr->ic->rvdw));
225
226     fr->ns->bCGlist = (getenv("GMX_NBLISTCG") != nullptr);
227     if (!fr->ns->bCGlist)
228     {
229         igeometry_def = GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE;
230     }
231     else
232     {
233         igeometry_def = GMX_NBLIST_GEOMETRY_CG_CG;
234         if (log != nullptr)
235         {
236             fprintf(log, "\nUsing charge-group - charge-group neighbor lists and kernels\n\n");
237         }
238     }
239
240     if (fr->solvent_opt == esolTIP4P)
241     {
242         igeometry_w  = GMX_NBLIST_GEOMETRY_WATER4_PARTICLE;
243         igeometry_ww = GMX_NBLIST_GEOMETRY_WATER4_WATER4;
244     }
245     else
246     {
247         igeometry_w  = GMX_NBLIST_GEOMETRY_WATER3_PARTICLE;
248         igeometry_ww = GMX_NBLIST_GEOMETRY_WATER3_WATER3;
249     }
250
251     for (i = 0; i < fr->nnblists; i++)
252     {
253         nbl = &(fr->nblists[i]);
254
255         init_nblist(log, &nbl->nlist_sr[eNL_VDWQQ],
256                     maxsr, ivdw, ivdwmod, ielec, ielecmod, igeometry_def, type, bElecAndVdwSwitchDiffers);
257         init_nblist(log, &nbl->nlist_sr[eNL_VDW],
258                     maxsr, ivdw, ivdwmod, GMX_NBKERNEL_ELEC_NONE, eintmodNONE, igeometry_def, type, bElecAndVdwSwitchDiffers);
259         init_nblist(log, &nbl->nlist_sr[eNL_QQ],
260                     maxsr, GMX_NBKERNEL_VDW_NONE, eintmodNONE, ielec, ielecmod, igeometry_def, type, bElecAndVdwSwitchDiffers);
261         init_nblist(log, &nbl->nlist_sr[eNL_VDWQQ_WATER],
262                     maxsr_wat, ivdw, ivdwmod, ielec, ielecmod, igeometry_w, type, bElecAndVdwSwitchDiffers);
263         init_nblist(log, &nbl->nlist_sr[eNL_QQ_WATER],
264                     maxsr_wat, GMX_NBKERNEL_VDW_NONE, eintmodNONE, ielec, ielecmod, igeometry_w, type, bElecAndVdwSwitchDiffers);
265         init_nblist(log, &nbl->nlist_sr[eNL_VDWQQ_WATERWATER],
266                     maxsr_wat, ivdw, ivdwmod, ielec, ielecmod, igeometry_ww, type, bElecAndVdwSwitchDiffers);
267         init_nblist(log, &nbl->nlist_sr[eNL_QQ_WATERWATER],
268                     maxsr_wat, GMX_NBKERNEL_VDW_NONE, eintmodNONE, ielec, ielecmod, igeometry_ww, type, bElecAndVdwSwitchDiffers);
269
270         /* Did we get the solvent loops so we can use optimized water kernels? */
271         if (nbl->nlist_sr[eNL_VDWQQ_WATER].kernelptr_vf == nullptr
272             || nbl->nlist_sr[eNL_QQ_WATER].kernelptr_vf == nullptr
273             || nbl->nlist_sr[eNL_VDWQQ_WATERWATER].kernelptr_vf == nullptr
274             || nbl->nlist_sr[eNL_QQ_WATERWATER].kernelptr_vf == nullptr)
275         {
276             fr->solvent_opt = esolNO;
277             if (log != nullptr)
278             {
279                 fprintf(log, "Note: The available nonbonded kernels do not support water optimization - disabling.\n");
280             }
281         }
282
283         if (fr->efep != efepNO)
284         {
285             init_nblist(log, &nbl->nlist_sr[eNL_VDWQQ_FREE],
286                         maxsr, ivdw, ivdwmod, ielec, ielecmod, GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY, bElecAndVdwSwitchDiffers);
287             init_nblist(log, &nbl->nlist_sr[eNL_VDW_FREE],
288                         maxsr, ivdw, ivdwmod, GMX_NBKERNEL_ELEC_NONE, eintmodNONE, GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY, bElecAndVdwSwitchDiffers);
289             init_nblist(log, &nbl->nlist_sr[eNL_QQ_FREE],
290                         maxsr, GMX_NBKERNEL_VDW_NONE, eintmodNONE, ielec, ielecmod, GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY, bElecAndVdwSwitchDiffers);
291         }
292     }
293     /* QMMM MM list */
294     if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
295     {
296         if (nullptr == fr->QMMMlist)
297         {
298             snew(fr->QMMMlist, 1);
299         }
300         init_nblist(log, fr->QMMMlist,
301                     maxsr, 0, 0, ielec, ielecmod, GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_STANDARD, bElecAndVdwSwitchDiffers);
302     }
303
304     if (log != nullptr)
305     {
306         fprintf(log, "\n");
307     }
308
309     fr->ns->nblist_initialized = TRUE;
310 }
311
312 static void reset_nblist(t_nblist *nl)
313 {
314     nl->nri       = -1;
315     nl->nrj       = 0;
316     if (nl->jindex)
317     {
318         nl->jindex[0] = 0;
319     }
320 }
321
322 static void reset_neighbor_lists(t_forcerec *fr)
323 {
324     int n, i;
325
326     if (fr->bQMMM)
327     {
328         /* only reset the short-range nblist */
329         reset_nblist(fr->QMMMlist);
330     }
331
332     for (n = 0; n < fr->nnblists; n++)
333     {
334         for (i = 0; i < eNL_NR; i++)
335         {
336             reset_nblist( &(fr->nblists[n].nlist_sr[i]) );
337         }
338     }
339 }
340
341
342
343
344 static inline void new_i_nblist(t_nblist *nlist, int i_atom, int shift, int gid)
345 {
346     int    nri = nlist->nri;
347
348     /* Check whether we have to increase the i counter */
349     if ((nri == -1) ||
350         (nlist->iinr[nri]  != i_atom) ||
351         (nlist->shift[nri] != shift) ||
352         (nlist->gid[nri]   != gid))
353     {
354         /* This is something else. Now see if any entries have
355          * been added in the list of the previous atom.
356          */
357         if ((nri == -1) ||
358             ((nlist->jindex[nri+1] > nlist->jindex[nri]) &&
359              (nlist->gid[nri] != -1)))
360         {
361             /* If so increase the counter */
362             nlist->nri++;
363             nri++;
364             if (nlist->nri >= nlist->maxnri)
365             {
366                 nlist->maxnri += over_alloc_large(nlist->nri);
367                 reallocate_nblist(nlist);
368             }
369         }
370         /* Set the number of neighbours and the atom number */
371         nlist->jindex[nri+1] = nlist->jindex[nri];
372         nlist->iinr[nri]     = i_atom;
373         nlist->gid[nri]      = gid;
374         nlist->shift[nri]    = shift;
375     }
376     else
377     {
378         /* Adding to previous list. First remove possible previous padding */
379         if (nlist->simd_padding_width > 1)
380         {
381             while (nlist->nrj > 0 && nlist->jjnr[nlist->nrj-1] < 0)
382             {
383                 nlist->nrj--;
384             }
385         }
386     }
387 }
388
389 static inline void close_i_nblist(t_nblist *nlist)
390 {
391     int nri = nlist->nri;
392     int len;
393
394     if (nri >= 0)
395     {
396         /* Add elements up to padding. Since we allocate memory in units
397          * of the simd_padding width, we do not have to check for possible
398          * list reallocation here.
399          */
400         while ((nlist->nrj % nlist->simd_padding_width) != 0)
401         {
402             /* Use -4 here, so we can write forces for 4 atoms before real data */
403             nlist->jjnr[nlist->nrj++] = -4;
404         }
405         nlist->jindex[nri+1] = nlist->nrj;
406
407         len = nlist->nrj -  nlist->jindex[nri];
408         /* If there are no j-particles we have to reduce the
409          * number of i-particles again, to prevent errors in the
410          * kernel functions.
411          */
412         if ((len == 0) && (nlist->nri > 0))
413         {
414             nlist->nri--;
415         }
416     }
417 }
418
419 static inline void close_nblist(t_nblist *nlist)
420 {
421     /* Only close this nblist when it has been initialized.
422      * Avoid the creation of i-lists with no j-particles.
423      */
424     if (nlist->nrj == 0)
425     {
426         /* Some assembly kernels do not support empty lists,
427          * make sure here that we don't generate any empty lists.
428          * With the current ns code this branch is taken in two cases:
429          * No i-particles at all: nri=-1 here
430          * There are i-particles, but no j-particles; nri=0 here
431          */
432         nlist->nri = 0;
433     }
434     else
435     {
436         /* Close list number nri by incrementing the count */
437         nlist->nri++;
438     }
439 }
440
441 static inline void close_neighbor_lists(t_forcerec *fr, gmx_bool bMakeQMMMnblist)
442 {
443     int n, i;
444
445     if (bMakeQMMMnblist)
446     {
447         close_nblist(fr->QMMMlist);
448     }
449
450     for (n = 0; n < fr->nnblists; n++)
451     {
452         for (i = 0; (i < eNL_NR); i++)
453         {
454             close_nblist(&(fr->nblists[n].nlist_sr[i]));
455         }
456     }
457 }
458
459
460 static inline void add_j_to_nblist(t_nblist *nlist, int j_atom)
461 {
462     int nrj = nlist->nrj;
463
464     if (nlist->nrj >= nlist->maxnrj)
465     {
466         nlist->maxnrj = round_up_to_simd_width(over_alloc_small(nlist->nrj + 1), nlist->simd_padding_width);
467
468         if (gmx_debug_at)
469         {
470             fprintf(debug, "Increasing SR nblist (ielec=%d,ivdw=%d,type=%d,igeometry=%d) j size to %d\n",
471                     nlist->ielec, nlist->ivdw, nlist->type, nlist->igeometry, nlist->maxnrj);
472         }
473
474         srenew(nlist->jjnr, nlist->maxnrj);
475     }
476
477     nlist->jjnr[nrj] = j_atom;
478     nlist->nrj++;
479 }
480
481 static inline void add_j_to_nblist_cg(t_nblist *nlist,
482                                       int j_start, int j_end,
483                                       const t_excl *bexcl, gmx_bool i_is_j)
484 {
485     int nrj = nlist->nrj;
486     int j;
487
488     if (nlist->nrj >= nlist->maxnrj)
489     {
490         nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
491         if (gmx_debug_at)
492         {
493             fprintf(debug, "Increasing SR nblist (ielec=%d,ivdw=%d,type=%d,igeometry=%d) j size to %d\n",
494                     nlist->ielec, nlist->ivdw, nlist->type, nlist->igeometry, nlist->maxnrj);
495         }
496
497         srenew(nlist->jjnr, nlist->maxnrj);
498         srenew(nlist->jjnr_end, nlist->maxnrj);
499         srenew(nlist->excl, nlist->maxnrj*MAX_CGCGSIZE);
500     }
501
502     nlist->jjnr[nrj]     = j_start;
503     nlist->jjnr_end[nrj] = j_end;
504
505     if (j_end - j_start > MAX_CGCGSIZE)
506     {
507         gmx_fatal(FARGS, "The charge-group - charge-group neighborlist do not support charge groups larger than %d, found a charge group of size %d", MAX_CGCGSIZE, j_end-j_start);
508     }
509
510     /* Set the exclusions */
511     for (j = j_start; j < j_end; j++)
512     {
513         nlist->excl[nrj*MAX_CGCGSIZE + j - j_start] = bexcl[j];
514     }
515     if (i_is_j)
516     {
517         /* Avoid double counting of intra-cg interactions */
518         for (j = 1; j < j_end-j_start; j++)
519         {
520             nlist->excl[nrj*MAX_CGCGSIZE + j] |= (1<<j) - 1;
521         }
522     }
523
524     nlist->nrj++;
525 }
526
527 typedef void
528     put_in_list_t (const gmx_bool        bHaveVdW[],
529                    int                   ngid,
530                    const t_mdatoms      *md,
531                    int                   icg,
532                    int                   jgid,
533                    int                   nj,
534                    const int             jjcg[],
535                    const int             index[],
536                    const t_excl          bExcl[],
537                    int                   shift,
538                    t_forcerec     *      fr,
539                    gmx_bool              bDoVdW,
540                    gmx_bool              bDoCoul,
541                    int                   solvent_opt);
542
543 static void
544 put_in_list_at(const gmx_bool              bHaveVdW[],
545                int                         ngid,
546                const t_mdatoms            *md,
547                int                         icg,
548                int                         jgid,
549                int                         nj,
550                const int                   jjcg[],
551                const int                   index[],
552                const t_excl                bExcl[],
553                int                         shift,
554                t_forcerec           *      fr,
555                gmx_bool                    bDoVdW,
556                gmx_bool                    bDoCoul,
557                int                         solvent_opt)
558 {
559     /* The a[] index has been removed,
560      * to put it back in i_atom should be a[i0] and jj should be a[jj].
561      */
562     t_nblist  *   vdwc;
563     t_nblist  *   vdw;
564     t_nblist  *   coul;
565     t_nblist  *   vdwc_free  = nullptr;
566     t_nblist  *   vdw_free   = nullptr;
567     t_nblist  *   coul_free  = nullptr;
568     t_nblist  *   vdwc_ww    = nullptr;
569     t_nblist  *   coul_ww    = nullptr;
570
571     int           i, j, jcg, igid, gid, nbl_ind;
572     int           jj, jj0, jj1, i_atom;
573     int           i0, nicg;
574
575     int          *cginfo;
576     int          *type, *typeB;
577     real         *charge, *chargeB;
578     real          qi, qiB;
579     gmx_bool      bFreeEnergy, bFree, bFreeJ, bNotEx, *bPert;
580     gmx_bool      bDoVdW_i, bDoCoul_i, bDoCoul_i_sol;
581     int           iwater, jwater;
582     t_nblist     *nlist;
583
584     /* Copy some pointers */
585     cginfo  = fr->cginfo;
586     charge  = md->chargeA;
587     chargeB = md->chargeB;
588     type    = md->typeA;
589     typeB   = md->typeB;
590     bPert   = md->bPerturbed;
591
592     /* Get atom range */
593     i0     = index[icg];
594     nicg   = index[icg+1]-i0;
595
596     /* Get the i charge group info */
597     igid   = GET_CGINFO_GID(cginfo[icg]);
598
599     iwater = (solvent_opt != esolNO) ? GET_CGINFO_SOLOPT(cginfo[icg]) : esolNO;
600
601     bFreeEnergy = FALSE;
602     if (md->nPerturbed)
603     {
604         /* Check if any of the particles involved are perturbed.
605          * If not we can do the cheaper normal put_in_list
606          * and use more solvent optimization.
607          */
608         for (i = 0; i < nicg; i++)
609         {
610             bFreeEnergy |= bPert[i0+i];
611         }
612         /* Loop over the j charge groups */
613         for (j = 0; (j < nj && !bFreeEnergy); j++)
614         {
615             jcg = jjcg[j];
616             jj0 = index[jcg];
617             jj1 = index[jcg+1];
618             /* Finally loop over the atoms in the j-charge group */
619             for (jj = jj0; jj < jj1; jj++)
620             {
621                 bFreeEnergy |= bPert[jj];
622             }
623         }
624     }
625
626     /* Unpack pointers to neighbourlist structs */
627     if (fr->nnblists == 1)
628     {
629         nbl_ind = 0;
630     }
631     else
632     {
633         nbl_ind = fr->gid2nblists[GID(igid, jgid, ngid)];
634     }
635     nlist = fr->nblists[nbl_ind].nlist_sr;
636
637     if (iwater != esolNO)
638     {
639         vdwc    = &nlist[eNL_VDWQQ_WATER];
640         vdw     = &nlist[eNL_VDW];
641         coul    = &nlist[eNL_QQ_WATER];
642         vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
643         coul_ww = &nlist[eNL_QQ_WATERWATER];
644     }
645     else
646     {
647         vdwc = &nlist[eNL_VDWQQ];
648         vdw  = &nlist[eNL_VDW];
649         coul = &nlist[eNL_QQ];
650     }
651
652     if (!bFreeEnergy)
653     {
654         if (iwater != esolNO)
655         {
656             /* Loop over the atoms in the i charge group */
657             i_atom  = i0;
658             gid     = GID(igid, jgid, ngid);
659             /* Create new i_atom for each energy group */
660             if (bDoCoul && bDoVdW)
661             {
662                 new_i_nblist(vdwc, i_atom, shift, gid);
663                 new_i_nblist(vdwc_ww, i_atom, shift, gid);
664             }
665             if (bDoVdW)
666             {
667                 new_i_nblist(vdw, i_atom, shift, gid);
668             }
669             if (bDoCoul)
670             {
671                 new_i_nblist(coul, i_atom, shift, gid);
672                 new_i_nblist(coul_ww, i_atom, shift, gid);
673             }
674             /* Loop over the j charge groups */
675             for (j = 0; (j < nj); j++)
676             {
677                 jcg = jjcg[j];
678
679                 if (jcg == icg)
680                 {
681                     continue;
682                 }
683
684                 jj0    = index[jcg];
685                 jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
686
687                 if (iwater == esolSPC && jwater == esolSPC)
688                 {
689                     /* Interaction between two SPC molecules */
690                     if (!bDoCoul)
691                     {
692                         /* VdW only - only first atoms in each water interact */
693                         add_j_to_nblist(vdw, jj0);
694                     }
695                     else
696                     {
697                         /* One entry for the entire water-water interaction */
698                         if (!bDoVdW)
699                         {
700                             add_j_to_nblist(coul_ww, jj0);
701                         }
702                         else
703                         {
704                             add_j_to_nblist(vdwc_ww, jj0);
705                         }
706                     }
707                 }
708                 else if (iwater == esolTIP4P && jwater == esolTIP4P)
709                 {
710                     /* Interaction between two TIP4p molecules */
711                     if (!bDoCoul)
712                     {
713                         /* VdW only - only first atoms in each water interact */
714                         add_j_to_nblist(vdw, jj0);
715                     }
716                     else
717                     {
718                         /* One entry for the entire water-water interaction */
719                         if (!bDoVdW)
720                         {
721                             add_j_to_nblist(coul_ww, jj0);
722                         }
723                         else
724                         {
725                             add_j_to_nblist(vdwc_ww, jj0);
726                         }
727                     }
728                 }
729                 else
730                 {
731                     /* j charge group is not water, but i is.
732                      * Add entries to the water-other_atom lists; the geometry of the water
733                      * molecule doesn't matter - that is taken care of in the nonbonded kernel,
734                      * so we don't care if it is SPC or TIP4P...
735                      */
736
737                     jj1 = index[jcg+1];
738
739                     if (!bDoVdW)
740                     {
741                         for (jj = jj0; (jj < jj1); jj++)
742                         {
743                             if (charge[jj] != 0)
744                             {
745                                 add_j_to_nblist(coul, jj);
746                             }
747                         }
748                     }
749                     else if (!bDoCoul)
750                     {
751                         for (jj = jj0; (jj < jj1); jj++)
752                         {
753                             if (bHaveVdW[type[jj]])
754                             {
755                                 add_j_to_nblist(vdw, jj);
756                             }
757                         }
758                     }
759                     else
760                     {
761                         /* _charge_ _groups_ interact with both coulomb and LJ */
762                         /* Check which atoms we should add to the lists!       */
763                         for (jj = jj0; (jj < jj1); jj++)
764                         {
765                             if (bHaveVdW[type[jj]])
766                             {
767                                 if (charge[jj] != 0)
768                                 {
769                                     add_j_to_nblist(vdwc, jj);
770                                 }
771                                 else
772                                 {
773                                     add_j_to_nblist(vdw, jj);
774                                 }
775                             }
776                             else if (charge[jj] != 0)
777                             {
778                                 add_j_to_nblist(coul, jj);
779                             }
780                         }
781                     }
782                 }
783             }
784             close_i_nblist(vdw);
785             close_i_nblist(coul);
786             close_i_nblist(vdwc);
787             close_i_nblist(coul_ww);
788             close_i_nblist(vdwc_ww);
789         }
790         else
791         {
792             /* no solvent as i charge group */
793             /* Loop over the atoms in the i charge group */
794             for (i = 0; i < nicg; i++)
795             {
796                 i_atom  = i0+i;
797                 gid     = GID(igid, jgid, ngid);
798                 qi      = charge[i_atom];
799
800                 /* Create new i_atom for each energy group */
801                 if (bDoVdW && bDoCoul)
802                 {
803                     new_i_nblist(vdwc, i_atom, shift, gid);
804                 }
805                 if (bDoVdW)
806                 {
807                     new_i_nblist(vdw, i_atom, shift, gid);
808                 }
809                 if (bDoCoul)
810                 {
811                     new_i_nblist(coul, i_atom, shift, gid);
812                 }
813                 bDoVdW_i  = (bDoVdW  && bHaveVdW[type[i_atom]]);
814                 bDoCoul_i = (bDoCoul && qi != 0);
815
816                 if (bDoVdW_i || bDoCoul_i)
817                 {
818                     /* Loop over the j charge groups */
819                     for (j = 0; (j < nj); j++)
820                     {
821                         jcg = jjcg[j];
822
823                         /* Check for large charge groups */
824                         if (jcg == icg)
825                         {
826                             jj0 = i0 + i + 1;
827                         }
828                         else
829                         {
830                             jj0 = index[jcg];
831                         }
832
833                         jj1 = index[jcg+1];
834                         /* Finally loop over the atoms in the j-charge group */
835                         for (jj = jj0; jj < jj1; jj++)
836                         {
837                             bNotEx = NOTEXCL(bExcl, i, jj);
838
839                             if (bNotEx)
840                             {
841                                 if (!bDoVdW_i)
842                                 {
843                                     if (charge[jj] != 0)
844                                     {
845                                         add_j_to_nblist(coul, jj);
846                                     }
847                                 }
848                                 else if (!bDoCoul_i)
849                                 {
850                                     if (bHaveVdW[type[jj]])
851                                     {
852                                         add_j_to_nblist(vdw, jj);
853                                     }
854                                 }
855                                 else
856                                 {
857                                     if (bHaveVdW[type[jj]])
858                                     {
859                                         if (charge[jj] != 0)
860                                         {
861                                             add_j_to_nblist(vdwc, jj);
862                                         }
863                                         else
864                                         {
865                                             add_j_to_nblist(vdw, jj);
866                                         }
867                                     }
868                                     else if (charge[jj] != 0)
869                                     {
870                                         add_j_to_nblist(coul, jj);
871                                     }
872                                 }
873                             }
874                         }
875                     }
876                 }
877                 close_i_nblist(vdw);
878                 close_i_nblist(coul);
879                 close_i_nblist(vdwc);
880             }
881         }
882     }
883     else
884     {
885         /* we are doing free energy */
886         vdwc_free = &nlist[eNL_VDWQQ_FREE];
887         vdw_free  = &nlist[eNL_VDW_FREE];
888         coul_free = &nlist[eNL_QQ_FREE];
889         /* Loop over the atoms in the i charge group */
890         for (i = 0; i < nicg; i++)
891         {
892             i_atom  = i0+i;
893             gid     = GID(igid, jgid, ngid);
894             qi      = charge[i_atom];
895             qiB     = chargeB[i_atom];
896
897             /* Create new i_atom for each energy group */
898             if (bDoVdW && bDoCoul)
899             {
900                 new_i_nblist(vdwc, i_atom, shift, gid);
901             }
902             if (bDoVdW)
903             {
904                 new_i_nblist(vdw, i_atom, shift, gid);
905             }
906             if (bDoCoul)
907             {
908                 new_i_nblist(coul, i_atom, shift, gid);
909             }
910
911             new_i_nblist(vdw_free, i_atom, shift, gid);
912             new_i_nblist(coul_free, i_atom, shift, gid);
913             new_i_nblist(vdwc_free, i_atom, shift, gid);
914
915             bDoVdW_i  = (bDoVdW  &&
916                          (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
917             bDoCoul_i = (bDoCoul && (qi != 0 || qiB != 0));
918             /* For TIP4P the first atom does not have a charge,
919              * but the last three do. So we should still put an atom
920              * without LJ but with charge in the water-atom neighborlist
921              * for a TIP4p i charge group.
922              * For SPC type water the first atom has LJ and charge,
923              * so there is no such problem.
924              */
925             if (iwater == esolNO)
926             {
927                 bDoCoul_i_sol = bDoCoul_i;
928             }
929             else
930             {
931                 bDoCoul_i_sol = bDoCoul;
932             }
933
934             if (bDoVdW_i || bDoCoul_i_sol)
935             {
936                 /* Loop over the j charge groups */
937                 for (j = 0; (j < nj); j++)
938                 {
939                     jcg = jjcg[j];
940
941                     /* Check for large charge groups */
942                     if (jcg == icg)
943                     {
944                         jj0 = i0 + i + 1;
945                     }
946                     else
947                     {
948                         jj0 = index[jcg];
949                     }
950
951                     jj1 = index[jcg+1];
952                     /* Finally loop over the atoms in the j-charge group */
953                     bFree = bPert[i_atom];
954                     for (jj = jj0; (jj < jj1); jj++)
955                     {
956                         bFreeJ = bFree || bPert[jj];
957                         /* Complicated if, because the water H's should also
958                          * see perturbed j-particles
959                          */
960                         if (iwater == esolNO || i == 0 || bFreeJ)
961                         {
962                             bNotEx = NOTEXCL(bExcl, i, jj);
963
964                             if (bNotEx)
965                             {
966                                 if (bFreeJ)
967                                 {
968                                     if (!bDoVdW_i)
969                                     {
970                                         if (charge[jj] != 0 || chargeB[jj] != 0)
971                                         {
972                                             add_j_to_nblist(coul_free, jj);
973                                         }
974                                     }
975                                     else if (!bDoCoul_i)
976                                     {
977                                         if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
978                                         {
979                                             add_j_to_nblist(vdw_free, jj);
980                                         }
981                                     }
982                                     else
983                                     {
984                                         if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
985                                         {
986                                             if (charge[jj] != 0 || chargeB[jj] != 0)
987                                             {
988                                                 add_j_to_nblist(vdwc_free, jj);
989                                             }
990                                             else
991                                             {
992                                                 add_j_to_nblist(vdw_free, jj);
993                                             }
994                                         }
995                                         else if (charge[jj] != 0 || chargeB[jj] != 0)
996                                         {
997                                             add_j_to_nblist(coul_free, jj);
998                                         }
999                                     }
1000                                 }
1001                                 else if (!bDoVdW_i)
1002                                 {
1003                                     /* This is done whether or not bWater is set */
1004                                     if (charge[jj] != 0)
1005                                     {
1006                                         add_j_to_nblist(coul, jj);
1007                                     }
1008                                 }
1009                                 else if (!bDoCoul_i_sol)
1010                                 {
1011                                     if (bHaveVdW[type[jj]])
1012                                     {
1013                                         add_j_to_nblist(vdw, jj);
1014                                     }
1015                                 }
1016                                 else
1017                                 {
1018                                     if (bHaveVdW[type[jj]])
1019                                     {
1020                                         if (charge[jj] != 0)
1021                                         {
1022                                             add_j_to_nblist(vdwc, jj);
1023                                         }
1024                                         else
1025                                         {
1026                                             add_j_to_nblist(vdw, jj);
1027                                         }
1028                                     }
1029                                     else if (charge[jj] != 0)
1030                                     {
1031                                         add_j_to_nblist(coul, jj);
1032                                     }
1033                                 }
1034                             }
1035                         }
1036                     }
1037                 }
1038             }
1039             close_i_nblist(vdw);
1040             close_i_nblist(coul);
1041             close_i_nblist(vdwc);
1042             close_i_nblist(vdw_free);
1043             close_i_nblist(coul_free);
1044             close_i_nblist(vdwc_free);
1045         }
1046     }
1047 }
1048
1049 static void
1050 put_in_list_qmmm(const gmx_bool gmx_unused        bHaveVdW[],
1051                  int                              ngid,
1052                  const t_mdatoms                  * /* md */,
1053                  int                              icg,
1054                  int                              jgid,
1055                  int                              nj,
1056                  const int                        jjcg[],
1057                  const int                        index[],
1058                  const t_excl                     bExcl[],
1059                  int                              shift,
1060                  t_forcerec                *      fr,
1061                  gmx_bool  gmx_unused             bDoVdW,
1062                  gmx_bool  gmx_unused             bDoCoul,
1063                  int       gmx_unused             solvent_opt)
1064 {
1065     t_nblist  *   coul;
1066     int           i, j, jcg, igid, gid;
1067     int           jj, jj0, jj1, i_atom;
1068     int           i0, nicg;
1069     gmx_bool      bNotEx;
1070
1071     /* Get atom range */
1072     i0     = index[icg];
1073     nicg   = index[icg+1]-i0;
1074
1075     /* Get the i charge group info */
1076     igid   = GET_CGINFO_GID(fr->cginfo[icg]);
1077
1078     coul = fr->QMMMlist;
1079
1080     /* Loop over atoms in the ith charge group */
1081     for (i = 0; i < nicg; i++)
1082     {
1083         i_atom = i0+i;
1084         gid    = GID(igid, jgid, ngid);
1085         /* Create new i_atom for each energy group */
1086         new_i_nblist(coul, i_atom, shift, gid);
1087
1088         /* Loop over the j charge groups */
1089         for (j = 0; j < nj; j++)
1090         {
1091             jcg = jjcg[j];
1092
1093             /* Charge groups cannot have QM and MM atoms simultaneously */
1094             if (jcg != icg)
1095             {
1096                 jj0 = index[jcg];
1097                 jj1 = index[jcg+1];
1098                 /* Finally loop over the atoms in the j-charge group */
1099                 for (jj = jj0; jj < jj1; jj++)
1100                 {
1101                     bNotEx = NOTEXCL(bExcl, i, jj);
1102                     if (bNotEx)
1103                     {
1104                         add_j_to_nblist(coul, jj);
1105                     }
1106                 }
1107             }
1108         }
1109         close_i_nblist(coul);
1110     }
1111 }
1112
1113 static void
1114 put_in_list_cg(const gmx_bool  gmx_unused       bHaveVdW[],
1115                int                              ngid,
1116                const t_mdatoms                  * /* md */,
1117                int                              icg,
1118                int                              jgid,
1119                int                              nj,
1120                const int                        jjcg[],
1121                const int                        index[],
1122                const t_excl                     bExcl[],
1123                int                              shift,
1124                t_forcerec                *      fr,
1125                gmx_bool   gmx_unused            bDoVdW,
1126                gmx_bool   gmx_unused            bDoCoul,
1127                int        gmx_unused            solvent_opt)
1128 {
1129     int          cginfo;
1130     int          igid, gid, nbl_ind;
1131     t_nblist *   vdwc;
1132     int          j, jcg;
1133
1134     cginfo = fr->cginfo[icg];
1135
1136     igid = GET_CGINFO_GID(cginfo);
1137     gid  = GID(igid, jgid, ngid);
1138
1139     /* Unpack pointers to neighbourlist structs */
1140     if (fr->nnblists == 1)
1141     {
1142         nbl_ind = 0;
1143     }
1144     else
1145     {
1146         nbl_ind = fr->gid2nblists[gid];
1147     }
1148     vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
1149
1150     /* Make a new neighbor list for charge group icg.
1151      * Currently simply one neighbor list is made with LJ and Coulomb.
1152      * If required, zero interactions could be removed here
1153      * or in the force loop.
1154      */
1155     new_i_nblist(vdwc, index[icg], shift, gid);
1156     vdwc->iinr_end[vdwc->nri] = index[icg+1];
1157
1158     for (j = 0; (j < nj); j++)
1159     {
1160         jcg = jjcg[j];
1161         /* Skip the icg-icg pairs if all self interactions are excluded */
1162         if (!(jcg == icg && GET_CGINFO_EXCL_INTRA(cginfo)))
1163         {
1164             /* Here we add the j charge group jcg to the list,
1165              * exclusions are also added to the list.
1166              */
1167             add_j_to_nblist_cg(vdwc, index[jcg], index[jcg+1], bExcl, icg == jcg);
1168         }
1169     }
1170
1171     close_i_nblist(vdwc);
1172 }
1173
1174 static void setexcl(int start, int end, t_blocka *excl, gmx_bool b,
1175                     t_excl bexcl[])
1176 {
1177     int i, k;
1178
1179     if (b)
1180     {
1181         for (i = start; i < end; i++)
1182         {
1183             for (k = excl->index[i]; k < excl->index[i+1]; k++)
1184             {
1185                 SETEXCL(bexcl, i-start, excl->a[k]);
1186             }
1187         }
1188     }
1189     else
1190     {
1191         for (i = start; i < end; i++)
1192         {
1193             for (k = excl->index[i]; k < excl->index[i+1]; k++)
1194             {
1195                 RMEXCL(bexcl, i-start, excl->a[k]);
1196             }
1197         }
1198     }
1199 }
1200
1201 int calc_naaj(int icg, int cgtot)
1202 {
1203     int naaj;
1204
1205     if ((cgtot % 2) == 1)
1206     {
1207         /* Odd number of charge groups, easy */
1208         naaj = 1 + (cgtot/2);
1209     }
1210     else if ((cgtot % 4) == 0)
1211     {
1212         /* Multiple of four is hard */
1213         if (icg < cgtot/2)
1214         {
1215             if ((icg % 2) == 0)
1216             {
1217                 naaj = 1+(cgtot/2);
1218             }
1219             else
1220             {
1221                 naaj = cgtot/2;
1222             }
1223         }
1224         else
1225         {
1226             if ((icg % 2) == 1)
1227             {
1228                 naaj = 1+(cgtot/2);
1229             }
1230             else
1231             {
1232                 naaj = cgtot/2;
1233             }
1234         }
1235     }
1236     else
1237     {
1238         /* cgtot/2 = odd */
1239         if ((icg % 2) == 0)
1240         {
1241             naaj = 1+(cgtot/2);
1242         }
1243         else
1244         {
1245             naaj = cgtot/2;
1246         }
1247     }
1248 #ifdef DEBUG
1249     fprintf(log, "naaj=%d\n", naaj);
1250 #endif
1251
1252     return naaj;
1253 }
1254
1255 /************************************************
1256  *
1257  *  S I M P L E      C O R E     S T U F F
1258  *
1259  ************************************************/
1260
1261 static real calc_image_tric(const rvec xi, const rvec xj, matrix box,
1262                             const rvec b_inv, int *shift)
1263 {
1264     /* This code assumes that the cut-off is smaller than
1265      * a half times the smallest diagonal element of the box.
1266      */
1267     const real h25 = 2.5;
1268     real       dx, dy, dz;
1269     real       r2;
1270     int        tx, ty, tz;
1271
1272     /* Compute diff vector */
1273     dz = xj[ZZ] - xi[ZZ];
1274     dy = xj[YY] - xi[YY];
1275     dx = xj[XX] - xi[XX];
1276
1277     /* Perform NINT operation, using trunc operation, therefore
1278      * we first add 2.5 then subtract 2 again
1279      */
1280     tz  = static_cast<int>(dz*b_inv[ZZ] + h25);
1281     tz -= 2;
1282     dz -= tz*box[ZZ][ZZ];
1283     dy -= tz*box[ZZ][YY];
1284     dx -= tz*box[ZZ][XX];
1285
1286     ty  = static_cast<int>(dy*b_inv[YY] + h25);
1287     ty -= 2;
1288     dy -= ty*box[YY][YY];
1289     dx -= ty*box[YY][XX];
1290
1291     tx  = static_cast<int>(dx*b_inv[XX]+h25);
1292     tx -= 2;
1293     dx -= tx*box[XX][XX];
1294
1295     /* Distance squared */
1296     r2 = (dx*dx) + (dy*dy) + (dz*dz);
1297
1298     *shift = XYZ2IS(tx, ty, tz);
1299
1300     return r2;
1301 }
1302
1303 static real calc_image_rect(const rvec xi, const rvec xj, const rvec box_size,
1304                             const rvec b_inv, int *shift)
1305 {
1306     const real h15 = 1.5;
1307     real       ddx, ddy, ddz;
1308     real       dx, dy, dz;
1309     real       r2;
1310     int        tx, ty, tz;
1311
1312     /* Compute diff vector */
1313     dx = xj[XX] - xi[XX];
1314     dy = xj[YY] - xi[YY];
1315     dz = xj[ZZ] - xi[ZZ];
1316
1317     /* Perform NINT operation, using trunc operation, therefore
1318      * we first add 1.5 then subtract 1 again
1319      */
1320     tx = static_cast<int>(dx*b_inv[XX] + h15);
1321     ty = static_cast<int>(dy*b_inv[YY] + h15);
1322     tz = static_cast<int>(dz*b_inv[ZZ] + h15);
1323     tx--;
1324     ty--;
1325     tz--;
1326
1327     /* Correct diff vector for translation */
1328     ddx = tx*box_size[XX] - dx;
1329     ddy = ty*box_size[YY] - dy;
1330     ddz = tz*box_size[ZZ] - dz;
1331
1332     /* Distance squared */
1333     r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
1334
1335     *shift = XYZ2IS(tx, ty, tz);
1336
1337     return r2;
1338 }
1339
1340 static void add_simple(t_ns_buf       * nsbuf,
1341                        int              nrj,
1342                        int              cg_j,
1343                        gmx_bool         bHaveVdW[],
1344                        int              ngid,
1345                        const t_mdatoms *md,
1346                        int              icg,
1347                        int              jgid,
1348                        t_block         *cgs,
1349                        t_excl           bexcl[],
1350                        int              shift,
1351                        t_forcerec      *fr,
1352                        put_in_list_t   *put_in_list)
1353 {
1354     if (nsbuf->nj + nrj > MAX_CG)
1355     {
1356         put_in_list(bHaveVdW, ngid, md, icg, jgid, nsbuf->ncg, nsbuf->jcg,
1357                     cgs->index, bexcl, shift, fr, TRUE, TRUE, fr->solvent_opt);
1358         /* Reset buffer contents */
1359         nsbuf->ncg = nsbuf->nj = 0;
1360     }
1361     nsbuf->jcg[nsbuf->ncg++] = cg_j;
1362     nsbuf->nj               += nrj;
1363 }
1364
1365 static void ns_inner_tric(rvec                   x[],
1366                           int                    icg,
1367                           const int             *i_egp_flags,
1368                           int                    njcg,
1369                           const int              jcg[],
1370                           matrix                 box,
1371                           rvec                   b_inv,
1372                           real                   rcut2,
1373                           t_block               *cgs,
1374                           t_ns_buf             **ns_buf,
1375                           gmx_bool               bHaveVdW[],
1376                           int                    ngid,
1377                           const t_mdatoms       *md,
1378                           t_excl                 bexcl[],
1379                           t_forcerec            *fr,
1380                           put_in_list_t         *put_in_list)
1381 {
1382     int       shift;
1383     int       j, nrj, jgid;
1384     int      *cginfo = fr->cginfo;
1385     int       cg_j, *cgindex;
1386
1387     cgindex = cgs->index;
1388     shift   = CENTRAL;
1389     for (j = 0; (j < njcg); j++)
1390     {
1391         cg_j   = jcg[j];
1392         nrj    = cgindex[cg_j+1]-cgindex[cg_j];
1393         if (calc_image_tric(x[icg], x[cg_j], box, b_inv, &shift) < rcut2)
1394         {
1395             jgid  = GET_CGINFO_GID(cginfo[cg_j]);
1396             if (!(i_egp_flags[jgid] & EGP_EXCL))
1397             {
1398                 add_simple(&ns_buf[jgid][shift], nrj, cg_j,
1399                            bHaveVdW, ngid, md, icg, jgid, cgs, bexcl, shift, fr,
1400                            put_in_list);
1401             }
1402         }
1403     }
1404 }
1405
1406 static void ns_inner_rect(rvec                   x[],
1407                           int                    icg,
1408                           const int             *i_egp_flags,
1409                           int                    njcg,
1410                           const int              jcg[],
1411                           gmx_bool               bBox,
1412                           rvec                   box_size,
1413                           rvec                   b_inv,
1414                           real                   rcut2,
1415                           t_block               *cgs,
1416                           t_ns_buf             **ns_buf,
1417                           gmx_bool               bHaveVdW[],
1418                           int                    ngid,
1419                           const t_mdatoms       *md,
1420                           t_excl                 bexcl[],
1421                           t_forcerec            *fr,
1422                           put_in_list_t         *put_in_list)
1423 {
1424     int       shift;
1425     int       j, nrj, jgid;
1426     int      *cginfo = fr->cginfo;
1427     int       cg_j, *cgindex;
1428
1429     cgindex = cgs->index;
1430     if (bBox)
1431     {
1432         shift = CENTRAL;
1433         for (j = 0; (j < njcg); j++)
1434         {
1435             cg_j   = jcg[j];
1436             nrj    = cgindex[cg_j+1]-cgindex[cg_j];
1437             if (calc_image_rect(x[icg], x[cg_j], box_size, b_inv, &shift) < rcut2)
1438             {
1439                 jgid  = GET_CGINFO_GID(cginfo[cg_j]);
1440                 if (!(i_egp_flags[jgid] & EGP_EXCL))
1441                 {
1442                     add_simple(&ns_buf[jgid][shift], nrj, cg_j,
1443                                bHaveVdW, ngid, md, icg, jgid, cgs, bexcl, shift, fr,
1444                                put_in_list);
1445                 }
1446             }
1447         }
1448     }
1449     else
1450     {
1451         for (j = 0; (j < njcg); j++)
1452         {
1453             cg_j   = jcg[j];
1454             nrj    = cgindex[cg_j+1]-cgindex[cg_j];
1455             if ((rcut2 == 0) || (distance2(x[icg], x[cg_j]) < rcut2))
1456             {
1457                 jgid  = GET_CGINFO_GID(cginfo[cg_j]);
1458                 if (!(i_egp_flags[jgid] & EGP_EXCL))
1459                 {
1460                     add_simple(&ns_buf[jgid][CENTRAL], nrj, cg_j,
1461                                bHaveVdW, ngid, md, icg, jgid, cgs, bexcl, CENTRAL, fr,
1462                                put_in_list);
1463                 }
1464             }
1465         }
1466     }
1467 }
1468
1469 /* ns_simple_core needs to be adapted for QMMM still 2005 */
1470
1471 static int ns_simple_core(t_forcerec      *fr,
1472                           gmx_localtop_t  *top,
1473                           const t_mdatoms *md,
1474                           matrix           box,
1475                           rvec             box_size,
1476                           t_excl           bexcl[],
1477                           int             *aaj,
1478                           int              ngid,
1479                           t_ns_buf       **ns_buf,
1480                           put_in_list_t   *put_in_list,
1481                           gmx_bool         bHaveVdW[])
1482 {
1483     int          naaj, k;
1484     real         rlist2;
1485     int          nsearch, icg, igid, nn;
1486     int         *cginfo;
1487     t_ns_buf    *nsbuf;
1488     /* int  *i_atoms; */
1489     t_block     *cgs  = &(top->cgs);
1490     t_blocka    *excl = &(top->excls);
1491     rvec         b_inv;
1492     int          m;
1493     gmx_bool     bBox, bTriclinic;
1494     int         *i_egp_flags;
1495
1496     rlist2 = gmx::square(fr->rlist);
1497
1498     bBox = (fr->ePBC != epbcNONE);
1499     if (bBox)
1500     {
1501         for (m = 0; (m < DIM); m++)
1502         {
1503             if (gmx_numzero(box_size[m]))
1504             {
1505                 gmx_fatal(FARGS, "Dividing by zero box size!");
1506             }
1507             b_inv[m] = 1.0/box_size[m];
1508         }
1509         bTriclinic = TRICLINIC(box);
1510     }
1511     else
1512     {
1513         bTriclinic = FALSE;
1514     }
1515
1516     cginfo = fr->cginfo;
1517
1518     nsearch = 0;
1519     for (icg = fr->cg0; (icg < fr->hcg); icg++)
1520     {
1521         /*
1522            i0        = cgs->index[icg];
1523            nri       = cgs->index[icg+1]-i0;
1524            i_atoms   = &(cgs->a[i0]);
1525            i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
1526            setexcl(nri,i_atoms,excl,TRUE,bexcl);
1527          */
1528         igid        = GET_CGINFO_GID(cginfo[icg]);
1529         i_egp_flags = fr->egp_flags + ngid*igid;
1530         setexcl(cgs->index[icg], cgs->index[icg+1], excl, TRUE, bexcl);
1531
1532         naaj = calc_naaj(icg, cgs->nr);
1533         if (bTriclinic)
1534         {
1535             ns_inner_tric(fr->cg_cm, icg, i_egp_flags, naaj, &(aaj[icg]),
1536                           box, b_inv, rlist2, cgs, ns_buf,
1537                           bHaveVdW, ngid, md, bexcl, fr, put_in_list);
1538         }
1539         else
1540         {
1541             ns_inner_rect(fr->cg_cm, icg, i_egp_flags, naaj, &(aaj[icg]),
1542                           bBox, box_size, b_inv, rlist2, cgs, ns_buf,
1543                           bHaveVdW, ngid, md, bexcl, fr, put_in_list);
1544         }
1545         nsearch += naaj;
1546
1547         for (nn = 0; (nn < ngid); nn++)
1548         {
1549             for (k = 0; (k < SHIFTS); k++)
1550             {
1551                 nsbuf = &(ns_buf[nn][k]);
1552                 if (nsbuf->ncg > 0)
1553                 {
1554                     put_in_list(bHaveVdW, ngid, md, icg, nn, nsbuf->ncg, nsbuf->jcg,
1555                                 cgs->index, bexcl, k, fr, TRUE, TRUE, fr->solvent_opt);
1556                     nsbuf->ncg = nsbuf->nj = 0;
1557                 }
1558             }
1559         }
1560         /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
1561         setexcl(cgs->index[icg], cgs->index[icg+1], excl, FALSE, bexcl);
1562     }
1563     close_neighbor_lists(fr, FALSE);
1564
1565     return nsearch;
1566 }
1567
1568 /************************************************
1569  *
1570  *    N S 5     G R I D     S T U F F
1571  *
1572  ************************************************/
1573
1574 static inline void get_dx_dd(int Nx, real gridx, real rc2, int xgi, real x,
1575                              int ncpddc, int shift_min, int shift_max,
1576                              int *g0, int *g1, real *dcx2)
1577 {
1578     real dcx, tmp;
1579     int  g_min, g_max, shift_home;
1580
1581     if (xgi < 0)
1582     {
1583         g_min = 0;
1584         g_max = Nx - 1;
1585         *g0   = 0;
1586         *g1   = -1;
1587     }
1588     else if (xgi >= Nx)
1589     {
1590         g_min = 0;
1591         g_max = Nx - 1;
1592         *g0   = Nx;
1593         *g1   = Nx - 1;
1594     }
1595     else
1596     {
1597         if (ncpddc == 0)
1598         {
1599             g_min = 0;
1600             g_max = Nx - 1;
1601         }
1602         else
1603         {
1604             if (xgi < ncpddc)
1605             {
1606                 shift_home = 0;
1607             }
1608             else
1609             {
1610                 shift_home = -1;
1611             }
1612             g_min = (shift_min == shift_home ? 0          : ncpddc);
1613             g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
1614         }
1615         if (shift_min > 0)
1616         {
1617             *g0 = g_min;
1618             *g1 = g_min - 1;
1619         }
1620         else if (shift_max < 0)
1621         {
1622             *g0 = g_max + 1;
1623             *g1 = g_max;
1624         }
1625         else
1626         {
1627             *g0       = xgi;
1628             *g1       = xgi;
1629             dcx2[xgi] = 0;
1630         }
1631     }
1632
1633     while (*g0 > g_min)
1634     {
1635         /* Check one grid cell down */
1636         dcx = ((*g0 - 1) + 1)*gridx - x;
1637         tmp = dcx*dcx;
1638         if (tmp >= rc2)
1639         {
1640             break;
1641         }
1642         (*g0)--;
1643         dcx2[*g0] = tmp;
1644     }
1645
1646     while (*g1 < g_max)
1647     {
1648         /* Check one grid cell up */
1649         dcx = (*g1 + 1)*gridx - x;
1650         tmp = dcx*dcx;
1651         if (tmp >= rc2)
1652         {
1653             break;
1654         }
1655         (*g1)++;
1656         dcx2[*g1] = tmp;
1657     }
1658 }
1659
1660
1661 #define calc_dx2(XI, YI, ZI, y) (gmx::square((XI)-(y)[XX]) + gmx::square((YI)-(y)[YY]) + gmx::square((ZI)-(y)[ZZ]))
1662 #define calc_cyl_dx2(XI, YI, y) (gmx::square((XI)-(y)[XX]) + gmx::square((YI)-(y)[YY]))
1663 /****************************************************
1664  *
1665  *    F A S T   N E I G H B O R  S E A R C H I N G
1666  *
1667  *    Optimized neighboursearching routine using grid
1668  *    at least 1x1x1, see GROMACS manual
1669  *
1670  ****************************************************/
1671
1672
1673 static void get_cutoff2(t_forcerec *fr, real *rs2)
1674 {
1675     *rs2 = gmx::square(fr->rlist);
1676 }
1677
1678 static void init_nsgrid_lists(t_forcerec *fr, int ngid, gmx_ns_t *ns)
1679 {
1680     real rs2;
1681     int  j;
1682
1683     get_cutoff2(fr, &rs2);
1684
1685     /* Short range buffers */
1686     snew(ns->nl_sr, ngid);
1687     /* Counters */
1688     snew(ns->nsr, ngid);
1689
1690     for (j = 0; (j < ngid); j++)
1691     {
1692         snew(ns->nl_sr[j], MAX_CG);
1693     }
1694     if (debug)
1695     {
1696         fprintf(debug,
1697                 "ns5_core: rs2 = %g (nm^2)\n",
1698                 rs2);
1699     }
1700 }
1701
1702 static int nsgrid_core(const t_commrec *cr,
1703                        t_forcerec      *fr,
1704                        matrix           box,
1705                        int              ngid,
1706                        gmx_localtop_t  *top,
1707                        t_grid          *grid,
1708                        t_excl           bexcl[],
1709                        const gmx_bool  *bExcludeAlleg,
1710                        const t_mdatoms *md,
1711                        put_in_list_t   *put_in_list,
1712                        gmx_bool         bHaveVdW[],
1713                        gmx_bool         bMakeQMMMnblist)
1714 {
1715     gmx_ns_t      *ns;
1716     int          **nl_sr;
1717     int           *nsr;
1718     gmx_domdec_t  *dd;
1719     const t_block *cgs    = &(top->cgs);
1720     int           *cginfo = fr->cginfo;
1721     /* int *i_atoms,*cgsindex=cgs->index; */
1722     ivec           sh0, sh1, shp;
1723     int            cell_x, cell_y, cell_z;
1724     int            d, tx, ty, tz, dx, dy, dz, cj;
1725 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
1726     int            zsh_ty, zsh_tx, ysh_tx;
1727 #endif
1728     int            dx0, dx1, dy0, dy1, dz0, dz1;
1729     int            Nx, Ny, Nz, shift = -1, j, nrj, nns, nn = -1;
1730     real           gridx, gridy, gridz, grid_x, grid_y;
1731     real          *dcx2, *dcy2, *dcz2;
1732     int            zgi, ygi, xgi;
1733     int            cg0, cg1, icg = -1, cgsnr, i0, igid, naaj, max_jcg;
1734     int            jcg0, jcg1, jjcg, cgj0, jgid;
1735     int           *grida, *gridnra, *gridind;
1736     rvec          *cgcm, grid_offset;
1737     real           r2, rs2, XI, YI, ZI, tmp1, tmp2;
1738     int           *i_egp_flags;
1739     gmx_bool       bDomDec, bTriclinicX, bTriclinicY;
1740     ivec           ncpddc;
1741
1742     ns = fr->ns;
1743
1744     bDomDec = DOMAINDECOMP(cr);
1745     dd      = cr->dd;
1746
1747     bTriclinicX = ((YY < grid->npbcdim &&
1748                     (!bDomDec || dd->nc[YY] == 1) && box[YY][XX] != 0) ||
1749                    (ZZ < grid->npbcdim &&
1750                     (!bDomDec || dd->nc[ZZ] == 1) && box[ZZ][XX] != 0));
1751     bTriclinicY =  (ZZ < grid->npbcdim &&
1752                     (!bDomDec || dd->nc[ZZ] == 1) && box[ZZ][YY] != 0);
1753
1754     cgsnr    = cgs->nr;
1755
1756     get_cutoff2(fr, &rs2);
1757
1758     nl_sr     = ns->nl_sr;
1759     nsr       = ns->nsr;
1760
1761     /* Unpack arrays */
1762     cgcm    = fr->cg_cm;
1763     Nx      = grid->n[XX];
1764     Ny      = grid->n[YY];
1765     Nz      = grid->n[ZZ];
1766     grida   = grid->a;
1767     gridind = grid->index;
1768     gridnra = grid->nra;
1769     nns     = 0;
1770
1771     gridx      = grid->cell_size[XX];
1772     gridy      = grid->cell_size[YY];
1773     gridz      = grid->cell_size[ZZ];
1774     grid_x     = 1/gridx;
1775     grid_y     = 1/gridy;
1776     copy_rvec(grid->cell_offset, grid_offset);
1777     copy_ivec(grid->ncpddc, ncpddc);
1778     dcx2       = grid->dcx2;
1779     dcy2       = grid->dcy2;
1780     dcz2       = grid->dcz2;
1781
1782 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
1783     zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
1784     zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
1785     ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
1786     if (zsh_tx != 0 && ysh_tx != 0)
1787     {
1788         /* This could happen due to rounding, when both ratios are 0.5 */
1789         ysh_tx = 0;
1790     }
1791 #endif
1792
1793     if (fr->n_tpi)
1794     {
1795         /* We only want a list for the test particle */
1796         cg0 = cgsnr - 1;
1797     }
1798     else
1799     {
1800         cg0 = grid->icg0;
1801     }
1802     cg1 = grid->icg1;
1803
1804     /* Set the shift range */
1805     for (d = 0; d < DIM; d++)
1806     {
1807         sh0[d] = -1;
1808         sh1[d] = 1;
1809         /* Check if we need periodicity shifts.
1810          * Without PBC or with domain decomposition we don't need them.
1811          */
1812         if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
1813         {
1814             shp[d] = 0;
1815         }
1816         else
1817         {
1818             if (d == XX &&
1819                 box[XX][XX] - std::abs(box[YY][XX]) - std::abs(box[ZZ][XX]) < std::sqrt(rs2))
1820             {
1821                 shp[d] = 2;
1822             }
1823             else
1824             {
1825                 shp[d] = 1;
1826             }
1827         }
1828     }
1829
1830     /* Loop over charge groups */
1831     for (icg = cg0; (icg < cg1); icg++)
1832     {
1833         igid = GET_CGINFO_GID(cginfo[icg]);
1834         /* Skip this charge group if all energy groups are excluded! */
1835         if (bExcludeAlleg[igid])
1836         {
1837             continue;
1838         }
1839
1840         i0   = cgs->index[icg];
1841
1842         if (bMakeQMMMnblist)
1843         {
1844             /* Skip this charge group if it is not a QM atom while making a
1845              * QM/MM neighbourlist
1846              */
1847             if (md->bQM[i0] == FALSE)
1848             {
1849                 continue; /* MM particle, go to next particle */
1850             }
1851
1852             /* Compute the number of charge groups that fall within the control
1853              * of this one (icg)
1854              */
1855             naaj    = calc_naaj(icg, cgsnr);
1856             jcg0    = icg;
1857             jcg1    = icg + naaj;
1858             max_jcg = cgsnr;
1859         }
1860         else
1861         {
1862             /* make a normal neighbourlist */
1863
1864             if (bDomDec)
1865             {
1866                 /* Get the j charge-group and dd cell shift ranges */
1867                 dd_get_ns_ranges(cr->dd, icg, &jcg0, &jcg1, sh0, sh1);
1868                 max_jcg = 0;
1869             }
1870             else
1871             {
1872                 /* Compute the number of charge groups that fall within the control
1873                  * of this one (icg)
1874                  */
1875                 naaj = calc_naaj(icg, cgsnr);
1876                 jcg0 = icg;
1877                 jcg1 = icg + naaj;
1878
1879                 if (fr->n_tpi)
1880                 {
1881                     /* The i-particle is awlways the test particle,
1882                      * so we want all j-particles
1883                      */
1884                     max_jcg = cgsnr - 1;
1885                 }
1886                 else
1887                 {
1888                     max_jcg  = jcg1 - cgsnr;
1889                 }
1890             }
1891         }
1892
1893         i_egp_flags = fr->egp_flags + igid*ngid;
1894
1895         /* Set the exclusions for the atoms in charge group icg using a bitmask */
1896         setexcl(i0, cgs->index[icg+1], &top->excls, TRUE, bexcl);
1897
1898         ci2xyz(grid, icg, &cell_x, &cell_y, &cell_z);
1899
1900         /* Changed iicg to icg, DvdS 990115
1901          * (but see consistency check above, DvdS 990330)
1902          */
1903 #ifdef NS5DB
1904         fprintf(log, "icg=%5d, naaj=%5d, cell %d %d %d\n",
1905                 icg, naaj, cell_x, cell_y, cell_z);
1906 #endif
1907         /* Loop over shift vectors in three dimensions */
1908         for (tz = -shp[ZZ]; tz <= shp[ZZ]; tz++)
1909         {
1910             ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
1911             /* Calculate range of cells in Z direction that have the shift tz */
1912             zgi = cell_z + tz*Nz;
1913             get_dx_dd(Nz, gridz, rs2, zgi, ZI-grid_offset[ZZ],
1914                       ncpddc[ZZ], sh0[ZZ], sh1[ZZ], &dz0, &dz1, dcz2);
1915             if (dz0 > dz1)
1916             {
1917                 continue;
1918             }
1919             for (ty = -shp[YY]; ty <= shp[YY]; ty++)
1920             {
1921                 YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
1922                 /* Calculate range of cells in Y direction that have the shift ty */
1923                 if (bTriclinicY)
1924                 {
1925                     ygi = static_cast<int>(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
1926                 }
1927                 else
1928                 {
1929                     ygi = cell_y + ty*Ny;
1930                 }
1931                 get_dx_dd(Ny, gridy, rs2, ygi, YI-grid_offset[YY],
1932                           ncpddc[YY], sh0[YY], sh1[YY], &dy0, &dy1, dcy2);
1933                 if (dy0 > dy1)
1934                 {
1935                     continue;
1936                 }
1937                 for (tx = -shp[XX]; tx <= shp[XX]; tx++)
1938                 {
1939                     XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
1940                     /* Calculate range of cells in X direction that have the shift tx */
1941                     if (bTriclinicX)
1942                     {
1943                         xgi = static_cast<int>(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
1944                     }
1945                     else
1946                     {
1947                         xgi = cell_x + tx*Nx;
1948                     }
1949                     get_dx_dd(Nx, gridx, rs2, xgi, XI-grid_offset[XX],
1950                               ncpddc[XX], sh0[XX], sh1[XX], &dx0, &dx1, dcx2);
1951                     if (dx0 > dx1)
1952                     {
1953                         continue;
1954                     }
1955                     /* Get shift vector */
1956                     shift = XYZ2IS(tx, ty, tz);
1957 #ifdef NS5DB
1958                     range_check(shift, 0, SHIFTS);
1959 #endif
1960                     for (nn = 0; (nn < ngid); nn++)
1961                     {
1962                         nsr[nn]      = 0;
1963                     }
1964 #ifdef NS5DB
1965                     fprintf(log, "shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
1966                             shift, dx0, dx1, dy0, dy1, dz0, dz1);
1967                     fprintf(log, "cgcm: %8.3f  %8.3f  %8.3f\n", cgcm[icg][XX],
1968                             cgcm[icg][YY], cgcm[icg][ZZ]);
1969                     fprintf(log, "xi:   %8.3f  %8.3f  %8.3f\n", XI, YI, ZI);
1970 #endif
1971                     for (dx = dx0; (dx <= dx1); dx++)
1972                     {
1973                         tmp1 = rs2 - dcx2[dx];
1974                         for (dy = dy0; (dy <= dy1); dy++)
1975                         {
1976                             tmp2 = tmp1 - dcy2[dy];
1977                             if (tmp2 > 0)
1978                             {
1979                                 for (dz = dz0; (dz <= dz1); dz++)
1980                                 {
1981                                     if (tmp2 > dcz2[dz])
1982                                     {
1983                                         /* Find grid-cell cj in which possible neighbours are */
1984                                         cj   = xyz2ci(Ny, Nz, dx, dy, dz);
1985
1986                                         /* Check out how many cgs (nrj) there in this cell */
1987                                         nrj  = gridnra[cj];
1988
1989                                         /* Find the offset in the cg list */
1990                                         cgj0 = gridind[cj];
1991
1992                                         /* Check if all j's are out of range so we
1993                                          * can skip the whole cell.
1994                                          * Should save some time, especially with DD.
1995                                          */
1996                                         if (nrj == 0 ||
1997                                             (grida[cgj0] >= max_jcg &&
1998                                              (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
1999                                         {
2000                                             continue;
2001                                         }
2002
2003                                         /* Loop over cgs */
2004                                         for (j = 0; (j < nrj); j++)
2005                                         {
2006                                             jjcg = grida[cgj0+j];
2007
2008                                             /* check whether this guy is in range! */
2009                                             if ((jjcg >= jcg0 && jjcg < jcg1) ||
2010                                                 (jjcg < max_jcg))
2011                                             {
2012                                                 r2 = calc_dx2(XI, YI, ZI, cgcm[jjcg]);
2013                                                 if (r2 < rs2)
2014                                                 {
2015                                                     /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
2016                                                     jgid = GET_CGINFO_GID(cginfo[jjcg]);
2017                                                     /* check energy group exclusions */
2018                                                     if (!(i_egp_flags[jgid] & EGP_EXCL))
2019                                                     {
2020                                                         if (nsr[jgid] >= MAX_CG)
2021                                                         {
2022                                                             /* Add to short-range list */
2023                                                             put_in_list(bHaveVdW, ngid, md, icg, jgid,
2024                                                                         nsr[jgid], nl_sr[jgid],
2025                                                                         cgs->index, /* cgsatoms, */ bexcl,
2026                                                                         shift, fr, TRUE, TRUE, fr->solvent_opt);
2027                                                             nsr[jgid] = 0;
2028                                                         }
2029                                                         nl_sr[jgid][nsr[jgid]++] = jjcg;
2030                                                     }
2031                                                 }
2032                                                 nns++;
2033                                             }
2034                                         }
2035                                     }
2036                                 }
2037                             }
2038                         }
2039                     }
2040                     /* CHECK whether there is anything left in the buffers */
2041                     for (nn = 0; (nn < ngid); nn++)
2042                     {
2043                         if (nsr[nn] > 0)
2044                         {
2045                             put_in_list(bHaveVdW, ngid, md, icg, nn, nsr[nn], nl_sr[nn],
2046                                         cgs->index, /* cgsatoms, */ bexcl,
2047                                         shift, fr, TRUE, TRUE, fr->solvent_opt);
2048                         }
2049                     }
2050                 }
2051             }
2052         }
2053         setexcl(cgs->index[icg], cgs->index[icg+1], &top->excls, FALSE, bexcl);
2054     }
2055     /* No need to perform any left-over force calculations anymore (as we used to do here)
2056      * since we now save the proper long-range lists for later evaluation.
2057      */
2058
2059     /* Close neighbourlists */
2060     close_neighbor_lists(fr, bMakeQMMMnblist);
2061
2062     return nns;
2063 }
2064
2065 static void ns_realloc_natoms(gmx_ns_t *ns, int natoms)
2066 {
2067     int i;
2068
2069     if (natoms > ns->nra_alloc)
2070     {
2071         ns->nra_alloc = over_alloc_dd(natoms);
2072         srenew(ns->bexcl, ns->nra_alloc);
2073         for (i = 0; i < ns->nra_alloc; i++)
2074         {
2075             ns->bexcl[i] = 0;
2076         }
2077     }
2078 }
2079
2080 void init_ns(FILE *fplog, const t_commrec *cr,
2081              gmx_ns_t *ns, t_forcerec *fr,
2082              const gmx_mtop_t *mtop)
2083 {
2084     int      icg, nr_in_cg, maxcg, i, j, jcg, ngid, ncg;
2085
2086     /* Compute largest charge groups size (# atoms) */
2087     nr_in_cg = 1;
2088     for (const gmx_moltype_t &molt : mtop->moltype)
2089     {
2090         const t_block *cgs = &molt.cgs;
2091         for (icg = 0; (icg < cgs->nr); icg++)
2092         {
2093             nr_in_cg = std::max(nr_in_cg, (cgs->index[icg+1]-cgs->index[icg]));
2094         }
2095     }
2096
2097     /* Verify whether largest charge group is <= max cg.
2098      * This is determined by the type of the local exclusion type
2099      * Exclusions are stored in bits. (If the type is not large
2100      * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
2101      */
2102     maxcg = sizeof(t_excl)*8;
2103     if (nr_in_cg > maxcg)
2104     {
2105         gmx_fatal(FARGS, "Max #atoms in a charge group: %d > %d\n",
2106                   nr_in_cg, maxcg);
2107     }
2108
2109     ngid = mtop->groups.grps[egcENER].nr;
2110     snew(ns->bExcludeAlleg, ngid);
2111     for (i = 0; i < ngid; i++)
2112     {
2113         ns->bExcludeAlleg[i] = TRUE;
2114         for (j = 0; j < ngid; j++)
2115         {
2116             if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
2117             {
2118                 ns->bExcludeAlleg[i] = FALSE;
2119             }
2120         }
2121     }
2122
2123     if (fr->bGrid)
2124     {
2125         /* Grid search */
2126         ns->grid = init_grid(fplog, fr);
2127         init_nsgrid_lists(fr, ngid, ns);
2128     }
2129     else
2130     {
2131         /* Simple search */
2132         snew(ns->ns_buf, ngid);
2133         for (i = 0; (i < ngid); i++)
2134         {
2135             snew(ns->ns_buf[i], SHIFTS);
2136         }
2137         ncg = ncg_mtop(mtop);
2138         snew(ns->simple_aaj, 2*ncg);
2139         for (jcg = 0; (jcg < ncg); jcg++)
2140         {
2141             ns->simple_aaj[jcg]     = jcg;
2142             ns->simple_aaj[jcg+ncg] = jcg;
2143         }
2144     }
2145
2146     /* Create array that determines whether or not atoms have VdW */
2147     snew(ns->bHaveVdW, fr->ntype);
2148     for (i = 0; (i < fr->ntype); i++)
2149     {
2150         for (j = 0; (j < fr->ntype); j++)
2151         {
2152             ns->bHaveVdW[i] = (ns->bHaveVdW[i] ||
2153                                (fr->bBHAM ?
2154                                 ((BHAMA(fr->nbfp, fr->ntype, i, j) != 0) ||
2155                                  (BHAMB(fr->nbfp, fr->ntype, i, j) != 0) ||
2156                                  (BHAMC(fr->nbfp, fr->ntype, i, j) != 0)) :
2157                                 ((C6(fr->nbfp, fr->ntype, i, j) != 0) ||
2158                                  (C12(fr->nbfp, fr->ntype, i, j) != 0))));
2159         }
2160     }
2161     if (debug)
2162     {
2163         pr_bvec(debug, 0, "bHaveVdW", ns->bHaveVdW, fr->ntype, TRUE);
2164     }
2165
2166     ns->nra_alloc = 0;
2167     ns->bexcl     = nullptr;
2168     if (!DOMAINDECOMP(cr))
2169     {
2170         ns_realloc_natoms(ns, mtop->natoms);
2171     }
2172
2173     ns->nblist_initialized = FALSE;
2174
2175     /* nbr list debug dump */
2176     {
2177         char *ptr = getenv("GMX_DUMP_NL");
2178         if (ptr)
2179         {
2180             ns->dump_nl = strtol(ptr, nullptr, 10);
2181             if (fplog)
2182             {
2183                 fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
2184             }
2185         }
2186         else
2187         {
2188             ns->dump_nl = 0;
2189         }
2190     }
2191 }
2192
2193 void done_ns(gmx_ns_t *ns, int numEnergyGroups)
2194 {
2195     sfree(ns->bExcludeAlleg);
2196     if (ns->ns_buf)
2197     {
2198         for (int i = 0; i < numEnergyGroups; i++)
2199         {
2200             sfree(ns->ns_buf[i]);
2201         }
2202         sfree(ns->ns_buf);
2203     }
2204     sfree(ns->simple_aaj);
2205     sfree(ns->bHaveVdW);
2206     done_grid(ns->grid);
2207     sfree(ns);
2208 }
2209
2210 int search_neighbours(FILE               *log,
2211                       t_forcerec         *fr,
2212                       matrix              box,
2213                       gmx_localtop_t     *top,
2214                       const gmx_groups_t *groups,
2215                       const t_commrec    *cr,
2216                       t_nrnb             *nrnb,
2217                       const t_mdatoms    *md,
2218                       gmx_bool            bFillGrid)
2219 {
2220     const t_block      *cgs = &(top->cgs);
2221     rvec                box_size, grid_x0, grid_x1;
2222     int                 m, ngid;
2223     real                min_size, grid_dens;
2224     int                 nsearch;
2225     gmx_bool            bGrid;
2226     int                 start, end;
2227     gmx_ns_t           *ns;
2228     t_grid             *grid;
2229     gmx_domdec_zones_t *dd_zones;
2230     put_in_list_t      *put_in_list;
2231
2232     ns = fr->ns;
2233
2234     /* Set some local variables */
2235     bGrid = fr->bGrid;
2236     ngid  = groups->grps[egcENER].nr;
2237
2238     for (m = 0; (m < DIM); m++)
2239     {
2240         box_size[m] = box[m][m];
2241     }
2242
2243     if (fr->ePBC != epbcNONE)
2244     {
2245         if (gmx::square(fr->rlist) >= max_cutoff2(fr->ePBC, box))
2246         {
2247             gmx_fatal(FARGS, "One of the box vectors has become shorter than twice the cut-off length or box_yy-|box_zy| or box_zz has become smaller than the cut-off.");
2248         }
2249         if (!bGrid)
2250         {
2251             min_size = std::min(box_size[XX], std::min(box_size[YY], box_size[ZZ]));
2252             if (2*fr->rlist >= min_size)
2253             {
2254                 gmx_fatal(FARGS, "One of the box diagonal elements has become smaller than twice the cut-off length.");
2255             }
2256         }
2257     }
2258
2259     if (DOMAINDECOMP(cr))
2260     {
2261         ns_realloc_natoms(ns, cgs->index[cgs->nr]);
2262     }
2263
2264     /* Reset the neighbourlists */
2265     reset_neighbor_lists(fr);
2266
2267     if (bGrid && bFillGrid)
2268     {
2269
2270         grid = ns->grid;
2271         if (DOMAINDECOMP(cr))
2272         {
2273             dd_zones = domdec_zones(cr->dd);
2274         }
2275         else
2276         {
2277             dd_zones = nullptr;
2278
2279             get_nsgrid_boundaries(grid->nboundeddim, box, nullptr, nullptr, nullptr, nullptr,
2280                                   cgs->nr, fr->cg_cm, grid_x0, grid_x1, &grid_dens);
2281
2282             grid_first(log, grid, nullptr, nullptr, box, grid_x0, grid_x1,
2283                        fr->rlist, grid_dens);
2284         }
2285
2286         start = 0;
2287         end   = cgs->nr;
2288
2289         if (DOMAINDECOMP(cr))
2290         {
2291             end = cgs->nr;
2292             fill_grid(dd_zones, grid, end, -1, end, fr->cg_cm);
2293             grid->icg0 = 0;
2294             grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
2295         }
2296         else
2297         {
2298             fill_grid(nullptr, grid, cgs->nr, fr->cg0, fr->hcg, fr->cg_cm);
2299             grid->icg0 = fr->cg0;
2300             grid->icg1 = fr->hcg;
2301         }
2302
2303         calc_elemnr(grid, start, end, cgs->nr);
2304         calc_ptrs(grid);
2305         grid_last(grid, start, end, cgs->nr);
2306
2307         if (gmx_debug_at)
2308         {
2309             check_grid(grid);
2310             print_grid(debug, grid);
2311         }
2312     }
2313     else if (fr->n_tpi)
2314     {
2315         /* Set the grid cell index for the test particle only.
2316          * The cell to cg index is not corrected, but that does not matter.
2317          */
2318         fill_grid(nullptr, ns->grid, fr->hcg, fr->hcg-1, fr->hcg, fr->cg_cm);
2319     }
2320
2321     if (!fr->ns->bCGlist)
2322     {
2323         put_in_list = put_in_list_at;
2324     }
2325     else
2326     {
2327         put_in_list = put_in_list_cg;
2328     }
2329
2330     /* Do the core! */
2331     if (bGrid)
2332     {
2333         grid    = ns->grid;
2334         nsearch = nsgrid_core(cr, fr, box, ngid, top,
2335                               grid, ns->bexcl, ns->bExcludeAlleg,
2336                               md, put_in_list, ns->bHaveVdW,
2337                               FALSE);
2338
2339         /* neighbour searching withouth QMMM! QM atoms have zero charge in
2340          * the classical calculation. The charge-charge interaction
2341          * between QM and MM atoms is handled in the QMMM core calculation
2342          * (see QMMM.c). The VDW however, we'd like to compute classically
2343          * and the QM MM atom pairs have just been put in the
2344          * corresponding neighbourlists. in case of QMMM we still need to
2345          * fill a special QMMM neighbourlist that contains all neighbours
2346          * of the QM atoms. If bQMMM is true, this list will now be made:
2347          */
2348         if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
2349         {
2350             nsearch += nsgrid_core(cr, fr, box, ngid, top,
2351                                    grid, ns->bexcl, ns->bExcludeAlleg,
2352                                    md, put_in_list_qmmm, ns->bHaveVdW,
2353                                    TRUE);
2354         }
2355     }
2356     else
2357     {
2358         nsearch = ns_simple_core(fr, top, md, box, box_size,
2359                                  ns->bexcl, ns->simple_aaj,
2360                                  ngid, ns->ns_buf, put_in_list, ns->bHaveVdW);
2361     }
2362
2363     inc_nrnb(nrnb, eNR_NS, nsearch);
2364
2365     return nsearch;
2366 }