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