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