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