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