2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
52 #include "nonbonded.h"
56 #include "gmx_fatal.h"
59 #include "mtop_util.h"
66 * E X C L U S I O N H A N D L I N G
70 static void SETEXCL_(t_excl e[],atom_id i,atom_id j)
71 { e[j] = e[j] | (1<<i); }
72 static void RMEXCL_(t_excl e[],atom_id i,atom_id j)
73 { e[j]=e[j] & ~(1<<i); }
74 static gmx_bool ISEXCL_(t_excl e[],atom_id i,atom_id j)
75 { return (gmx_bool)(e[j] & (1<<i)); }
76 static gmx_bool NOTEXCL_(t_excl e[],atom_id i,atom_id j)
77 { return !(ISEXCL(e,i,j)); }
79 #define SETEXCL(e,i,j) (e)[((atom_id) (j))] |= (1<<((atom_id) (i)))
80 #define RMEXCL(e,i,j) (e)[((atom_id) (j))] &= (~(1<<((atom_id) (i))))
81 #define ISEXCL(e,i,j) (gmx_bool) ((e)[((atom_id) (j))] & (1<<((atom_id) (i))))
82 #define NOTEXCL(e,i,j) !(ISEXCL(e,i,j))
86 round_up_to_simd_width(int length, int simd_width)
90 offset = (simd_width>0) ? length % simd_width : 0;
92 return (offset==0) ? length : length-offset+simd_width;
94 /************************************************
96 * U T I L I T I E S F O R N S
98 ************************************************/
100 static void reallocate_nblist(t_nblist *nl)
104 fprintf(debug,"reallocating neigborlist (ielec=%d, ivdw=%d, igeometry=%d, type=%d), maxnri=%d\n",
105 nl->ielec,nl->ivdw,nl->igeometry,nl->type,nl->maxnri);
107 srenew(nl->iinr, nl->maxnri);
108 if (nl->igeometry == GMX_NBLIST_GEOMETRY_CG_CG)
110 srenew(nl->iinr_end,nl->maxnri);
112 srenew(nl->gid, nl->maxnri);
113 srenew(nl->shift, nl->maxnri);
114 srenew(nl->jindex, nl->maxnri+1);
118 static void init_nblist(FILE *log, t_nblist *nl_sr,t_nblist *nl_lr,
120 int ivdw, int ivdwmod,
121 int ielec, int ielecmod,
122 int igeometry, int type)
130 nl = (i == 0) ? nl_sr : nl_lr;
131 homenr = (i == 0) ? maxsr : maxlr;
139 /* Set coul/vdw in neighborlist, and for the normal loops we determine
140 * an index of which one to call.
143 nl->ivdwmod = ivdwmod;
145 nl->ielecmod = ielecmod;
147 nl->igeometry = igeometry;
149 if (nl->type==GMX_NBLIST_INTERACTION_FREE_ENERGY)
151 nl->igeometry = GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE;
154 /* This will also set the simd_padding_width field */
155 gmx_nonbonded_set_kernel_pointers( (i==0) ? log : NULL,nl);
157 /* maxnri is influenced by the number of shifts (maximum is 8)
158 * and the number of energy groups.
159 * If it is not enough, nl memory will be reallocated during the run.
160 * 4 seems to be a reasonable factor, which only causes reallocation
161 * during runs with tiny and many energygroups.
163 nl->maxnri = homenr*4;
172 reallocate_nblist(nl);
177 fprintf(debug,"Initiating neighbourlist (ielec=%d, ivdw=%d, type=%d) for %s interactions,\nwith %d SR, %d LR atoms.\n",
178 nl->ielec,nl->ivdw,nl->type,gmx_nblist_geometry_names[nl->igeometry],maxsr,maxlr);
183 void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
185 /* Make maxlr tunable! (does not seem to be a big difference though)
186 * This parameter determines the number of i particles in a long range
187 * neighbourlist. Too few means many function calls, too many means
190 int maxsr,maxsr_wat,maxlr,maxlr_wat;
191 int ielec,ielecf,ivdw,ielecmod,ielecmodf,ivdwmod,type;
193 int igeometry_def,igeometry_w,igeometry_ww;
197 /* maxsr = homenr-fr->nWatMol*3; */
202 gmx_fatal(FARGS,"%s, %d: Negative number of short range atoms.\n"
203 "Call your Gromacs dealer for assistance.",__FILE__,__LINE__);
205 /* This is just for initial allocation, so we do not reallocate
206 * all the nlist arrays many times in a row.
207 * The numbers seem very accurate, but they are uncritical.
209 maxsr_wat = min(fr->nWatMol,(homenr+2)/3);
213 maxlr_wat = min(maxsr_wat,maxlr);
217 maxlr = maxlr_wat = 0;
220 /* Determine the values for ielec/ivdw. */
221 ielec = fr->nbkernel_elec_interaction;
222 ivdw = fr->nbkernel_vdw_interaction;
223 ielecmod = fr->nbkernel_elec_modifier;
224 ivdwmod = fr->nbkernel_vdw_modifier;
225 type = GMX_NBLIST_INTERACTION_STANDARD;
227 fr->ns.bCGlist = (getenv("GMX_NBLISTCG") != 0);
230 igeometry_def = GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE;
234 igeometry_def = GMX_NBLIST_GEOMETRY_CG_CG;
237 fprintf(log,"\nUsing charge-group - charge-group neighbor lists and kernels\n\n");
241 if (fr->solvent_opt == esolTIP4P) {
242 igeometry_w = GMX_NBLIST_GEOMETRY_WATER4_PARTICLE;
243 igeometry_ww = GMX_NBLIST_GEOMETRY_WATER4_WATER4;
245 igeometry_w = GMX_NBLIST_GEOMETRY_WATER3_PARTICLE;
246 igeometry_ww = GMX_NBLIST_GEOMETRY_WATER3_WATER3;
249 for(i=0; i<fr->nnblists; i++)
251 nbl = &(fr->nblists[i]);
253 if ((fr->adress_type!=eAdressOff) && (i>=fr->nnblists/2)){
254 type=GMX_NBLIST_INTERACTION_ADRESS;
256 init_nblist(log,&nbl->nlist_sr[eNL_VDWQQ],&nbl->nlist_lr[eNL_VDWQQ],
257 maxsr,maxlr,ivdw,ivdwmod,ielec,ielecmod,igeometry_def, type);
258 init_nblist(log,&nbl->nlist_sr[eNL_VDW],&nbl->nlist_lr[eNL_VDW],
259 maxsr,maxlr,ivdw,ivdwmod,GMX_NBKERNEL_ELEC_NONE,eintmodNONE,igeometry_def, type);
260 init_nblist(log,&nbl->nlist_sr[eNL_QQ],&nbl->nlist_lr[eNL_QQ],
261 maxsr,maxlr,GMX_NBKERNEL_VDW_NONE,eintmodNONE,ielec,ielecmod,igeometry_def, type);
262 init_nblist(log,&nbl->nlist_sr[eNL_VDWQQ_WATER],&nbl->nlist_lr[eNL_VDWQQ_WATER],
263 maxsr_wat,maxlr_wat,ivdw,ivdwmod,ielec,ielecmod, igeometry_w, type);
264 init_nblist(log,&nbl->nlist_sr[eNL_QQ_WATER],&nbl->nlist_lr[eNL_QQ_WATER],
265 maxsr_wat,maxlr_wat,GMX_NBKERNEL_VDW_NONE,eintmodNONE,ielec,ielecmod, igeometry_w, type);
266 init_nblist(log,&nbl->nlist_sr[eNL_VDWQQ_WATERWATER],&nbl->nlist_lr[eNL_VDWQQ_WATERWATER],
267 maxsr_wat,maxlr_wat,ivdw,ivdwmod,ielec,ielecmod, igeometry_ww, type);
268 init_nblist(log,&nbl->nlist_sr[eNL_QQ_WATERWATER],&nbl->nlist_lr[eNL_QQ_WATERWATER],
269 maxsr_wat,maxlr_wat,GMX_NBKERNEL_VDW_NONE,eintmodNONE,ielec,ielecmod, igeometry_ww, type);
271 /* Did we get the solvent loops so we can use optimized water kernels? */
272 if(nbl->nlist_sr[eNL_VDWQQ_WATER].kernelptr_vf==NULL
273 || nbl->nlist_sr[eNL_QQ_WATER].kernelptr_vf==NULL
274 #ifndef DISABLE_WATERWATER_NLIST
275 || nbl->nlist_sr[eNL_VDWQQ_WATERWATER].kernelptr_vf==NULL
276 || nbl->nlist_sr[eNL_QQ_WATERWATER].kernelptr_vf==NULL
280 fr->solvent_opt = esolNO;
281 fprintf(log,"Note: The available nonbonded kernels do not support water optimization - disabling.\n");
284 if (fr->efep != efepNO)
286 if ((fr->bEwald) && (fr->sc_alphacoul > 0)) /* need to handle long range differently if using softcore */
288 ielecf = GMX_NBKERNEL_ELEC_EWALD;
289 ielecmodf = eintmodNONE;
294 ielecmodf = ielecmod;
297 init_nblist(log,&nbl->nlist_sr[eNL_VDWQQ_FREE],&nbl->nlist_lr[eNL_VDWQQ_FREE],
298 maxsr,maxlr,ivdw,ivdwmod,ielecf,ielecmod,GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY);
299 init_nblist(log,&nbl->nlist_sr[eNL_VDW_FREE],&nbl->nlist_lr[eNL_VDW_FREE],
300 maxsr,maxlr,ivdw,ivdwmod,GMX_NBKERNEL_ELEC_NONE,eintmodNONE,GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY);
301 init_nblist(log,&nbl->nlist_sr[eNL_QQ_FREE],&nbl->nlist_lr[eNL_QQ_FREE],
302 maxsr,maxlr,GMX_NBKERNEL_VDW_NONE,eintmodNONE,ielecf,ielecmod,GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_FREE_ENERGY);
306 if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
308 init_nblist(log,&fr->QMMMlist,NULL,
309 maxsr,maxlr,0,0,ielec,ielecmod,GMX_NBLIST_GEOMETRY_PARTICLE_PARTICLE, GMX_NBLIST_INTERACTION_STANDARD);
317 fr->ns.nblist_initialized=TRUE;
320 static void reset_nblist(t_nblist *nl)
331 static void reset_neighbor_lists(t_forcerec *fr,gmx_bool bResetSR, gmx_bool bResetLR)
337 /* only reset the short-range nblist */
338 reset_nblist(&(fr->QMMMlist));
341 for(n=0; n<fr->nnblists; n++)
343 for(i=0; i<eNL_NR; i++)
347 reset_nblist( &(fr->nblists[n].nlist_sr[i]) );
351 reset_nblist( &(fr->nblists[n].nlist_lr[i]) );
360 static inline void new_i_nblist(t_nblist *nlist,
361 gmx_bool bLR,atom_id i_atom,int shift,int gid)
367 /* Check whether we have to increase the i counter */
369 (nlist->iinr[nri] != i_atom) ||
370 (nlist->shift[nri] != shift) ||
371 (nlist->gid[nri] != gid))
373 /* This is something else. Now see if any entries have
374 * been added in the list of the previous atom.
377 ((nlist->jindex[nri+1] > nlist->jindex[nri]) &&
378 (nlist->gid[nri] != -1)))
380 /* If so increase the counter */
383 if (nlist->nri >= nlist->maxnri)
385 nlist->maxnri += over_alloc_large(nlist->nri);
386 reallocate_nblist(nlist);
389 /* Set the number of neighbours and the atom number */
390 nlist->jindex[nri+1] = nlist->jindex[nri];
391 nlist->iinr[nri] = i_atom;
392 nlist->gid[nri] = gid;
393 nlist->shift[nri] = shift;
397 static inline void close_i_nblist(t_nblist *nlist)
399 int nri = nlist->nri;
404 /* Add elements up to padding. Since we allocate memory in units
405 * of the simd_padding width, we do not have to check for possible
406 * list reallocation here.
408 while((nlist->nrj % nlist->simd_padding_width)!=0)
410 /* Use -4 here, so we can write forces for 4 atoms before real data */
411 nlist->jjnr[nlist->nrj++]=-4;
413 nlist->jindex[nri+1] = nlist->nrj;
415 len=nlist->nrj - nlist->jindex[nri];
417 /* nlist length for water i molecules is treated statically
420 if (len > nlist->maxlen)
427 static inline void close_nblist(t_nblist *nlist)
429 /* Only close this nblist when it has been initialized.
430 * Avoid the creation of i-lists with no j-particles.
434 /* Some assembly kernels do not support empty lists,
435 * make sure here that we don't generate any empty lists.
436 * With the current ns code this branch is taken in two cases:
437 * No i-particles at all: nri=-1 here
438 * There are i-particles, but no j-particles; nri=0 here
444 /* Close list number nri by incrementing the count */
449 static inline void close_neighbor_lists(t_forcerec *fr,gmx_bool bMakeQMMMnblist)
455 close_nblist(&(fr->QMMMlist));
458 for(n=0; n<fr->nnblists; n++)
460 for(i=0; (i<eNL_NR); i++)
462 close_nblist(&(fr->nblists[n].nlist_sr[i]));
463 close_nblist(&(fr->nblists[n].nlist_lr[i]));
469 static inline void add_j_to_nblist(t_nblist *nlist,atom_id j_atom,gmx_bool bLR)
473 if (nlist->nrj >= nlist->maxnrj)
475 nlist->maxnrj = round_up_to_simd_width(over_alloc_small(nlist->nrj + 1),nlist->simd_padding_width);
478 fprintf(debug,"Increasing %s nblist (ielec=%d,ivdw=%d,type=%d,igeometry=%d) j size to %d\n",
479 bLR ? "LR" : "SR",nlist->ielec,nlist->ivdw,nlist->type,nlist->igeometry,nlist->maxnrj);
481 srenew(nlist->jjnr,nlist->maxnrj);
484 nlist->jjnr[nrj] = j_atom;
488 static inline void add_j_to_nblist_cg(t_nblist *nlist,
489 atom_id j_start,int j_end,
490 t_excl *bexcl,gmx_bool i_is_j,
496 if (nlist->nrj >= nlist->maxnrj)
498 nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
500 fprintf(debug,"Increasing %s nblist (ielec=%d,ivdw=%d,type=%d,igeometry=%d) j size to %d\n",
501 bLR ? "LR" : "SR",nlist->ielec,nlist->ivdw,nlist->type,nlist->igeometry,nlist->maxnrj);
503 srenew(nlist->jjnr ,nlist->maxnrj);
504 srenew(nlist->jjnr_end,nlist->maxnrj);
505 srenew(nlist->excl ,nlist->maxnrj*MAX_CGCGSIZE);
508 nlist->jjnr[nrj] = j_start;
509 nlist->jjnr_end[nrj] = j_end;
511 if (j_end - j_start > MAX_CGCGSIZE)
513 gmx_fatal(FARGS,"The charge-group - charge-group neighborlist do not support charge groups larger than %d, found a charge group of size %d",MAX_CGCGSIZE,j_end-j_start);
516 /* Set the exclusions */
517 for(j=j_start; j<j_end; j++)
519 nlist->excl[nrj*MAX_CGCGSIZE + j - j_start] = bexcl[j];
523 /* Avoid double counting of intra-cg interactions */
524 for(j=1; j<j_end-j_start; j++)
526 nlist->excl[nrj*MAX_CGCGSIZE + j] |= (1<<j) - 1;
534 put_in_list_t(gmx_bool bHaveVdW[],
551 put_in_list_at(gmx_bool bHaveVdW[],
567 /* The a[] index has been removed,
568 * to put it back in i_atom should be a[i0] and jj should be a[jj].
573 t_nblist * vdwc_free = NULL;
574 t_nblist * vdw_free = NULL;
575 t_nblist * coul_free = NULL;
576 t_nblist * vdwc_ww = NULL;
577 t_nblist * coul_ww = NULL;
579 int i,j,jcg,igid,gid,nbl_ind,ind_ij;
580 atom_id jj,jj0,jj1,i_atom;
585 real *charge,*chargeB;
587 gmx_bool bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
588 gmx_bool bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
592 /* Copy some pointers */
594 charge = md->chargeA;
595 chargeB = md->chargeB;
598 bPert = md->bPerturbed;
602 nicg = index[icg+1]-i0;
604 /* Get the i charge group info */
605 igid = GET_CGINFO_GID(cginfo[icg]);
607 iwater = (solvent_opt!=esolNO) ? GET_CGINFO_SOLOPT(cginfo[icg]) : esolNO;
612 /* Check if any of the particles involved are perturbed.
613 * If not we can do the cheaper normal put_in_list
614 * and use more solvent optimization.
616 for(i=0; i<nicg; i++)
618 bFreeEnergy |= bPert[i0+i];
620 /* Loop over the j charge groups */
621 for(j=0; (j<nj && !bFreeEnergy); j++)
626 /* Finally loop over the atoms in the j-charge group */
627 for(jj=jj0; jj<jj1; jj++)
629 bFreeEnergy |= bPert[jj];
634 /* Unpack pointers to neighbourlist structs */
635 if (fr->nnblists == 1)
641 nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
645 nlist = fr->nblists[nbl_ind].nlist_lr;
649 nlist = fr->nblists[nbl_ind].nlist_sr;
652 if (iwater != esolNO)
654 vdwc = &nlist[eNL_VDWQQ_WATER];
655 vdw = &nlist[eNL_VDW];
656 coul = &nlist[eNL_QQ_WATER];
657 #ifndef DISABLE_WATERWATER_NLIST
658 vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
659 coul_ww = &nlist[eNL_QQ_WATERWATER];
664 vdwc = &nlist[eNL_VDWQQ];
665 vdw = &nlist[eNL_VDW];
666 coul = &nlist[eNL_QQ];
671 if (iwater != esolNO)
673 /* Loop over the atoms in the i charge group */
675 gid = GID(igid,jgid,ngid);
676 /* Create new i_atom for each energy group */
677 if (bDoCoul && bDoVdW)
679 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
680 #ifndef DISABLE_WATERWATER_NLIST
681 new_i_nblist(vdwc_ww,bLR,i_atom,shift,gid);
686 new_i_nblist(vdw,bLR,i_atom,shift,gid);
690 new_i_nblist(coul,bLR,i_atom,shift,gid);
691 #ifndef DISABLE_WATERWATER_NLIST
692 new_i_nblist(coul_ww,bLR,i_atom,shift,gid);
695 /* Loop over the j charge groups */
696 for(j=0; (j<nj); j++)
706 jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
708 if (iwater == esolSPC && jwater == esolSPC)
710 /* Interaction between two SPC molecules */
713 /* VdW only - only first atoms in each water interact */
714 add_j_to_nblist(vdw,jj0,bLR);
718 #ifdef DISABLE_WATERWATER_NLIST
719 /* Add entries for the three atoms - only do VdW if we need to */
722 add_j_to_nblist(coul,jj0,bLR);
726 add_j_to_nblist(vdwc,jj0,bLR);
728 add_j_to_nblist(coul,jj0+1,bLR);
729 add_j_to_nblist(coul,jj0+2,bLR);
731 /* One entry for the entire water-water interaction */
734 add_j_to_nblist(coul_ww,jj0,bLR);
738 add_j_to_nblist(vdwc_ww,jj0,bLR);
743 else if (iwater == esolTIP4P && jwater == esolTIP4P)
745 /* Interaction between two TIP4p molecules */
748 /* VdW only - only first atoms in each water interact */
749 add_j_to_nblist(vdw,jj0,bLR);
753 #ifdef DISABLE_WATERWATER_NLIST
754 /* Add entries for the four atoms - only do VdW if we need to */
757 add_j_to_nblist(vdw,jj0,bLR);
759 add_j_to_nblist(coul,jj0+1,bLR);
760 add_j_to_nblist(coul,jj0+2,bLR);
761 add_j_to_nblist(coul,jj0+3,bLR);
763 /* One entry for the entire water-water interaction */
766 add_j_to_nblist(coul_ww,jj0,bLR);
770 add_j_to_nblist(vdwc_ww,jj0,bLR);
777 /* j charge group is not water, but i is.
778 * Add entries to the water-other_atom lists; the geometry of the water
779 * molecule doesn't matter - that is taken care of in the nonbonded kernel,
780 * so we don't care if it is SPC or TIP4P...
787 for(jj=jj0; (jj<jj1); jj++)
791 add_j_to_nblist(coul,jj,bLR);
797 for(jj=jj0; (jj<jj1); jj++)
799 if (bHaveVdW[type[jj]])
801 add_j_to_nblist(vdw,jj,bLR);
807 /* _charge_ _groups_ interact with both coulomb and LJ */
808 /* Check which atoms we should add to the lists! */
809 for(jj=jj0; (jj<jj1); jj++)
811 if (bHaveVdW[type[jj]])
815 add_j_to_nblist(vdwc,jj,bLR);
819 add_j_to_nblist(vdw,jj,bLR);
822 else if (charge[jj] != 0)
824 add_j_to_nblist(coul,jj,bLR);
831 close_i_nblist(coul);
832 close_i_nblist(vdwc);
833 #ifndef DISABLE_WATERWATER_NLIST
834 close_i_nblist(coul_ww);
835 close_i_nblist(vdwc_ww);
840 /* no solvent as i charge group */
841 /* Loop over the atoms in the i charge group */
842 for(i=0; i<nicg; i++)
845 gid = GID(igid,jgid,ngid);
848 /* Create new i_atom for each energy group */
849 if (bDoVdW && bDoCoul)
851 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
855 new_i_nblist(vdw,bLR,i_atom,shift,gid);
859 new_i_nblist(coul,bLR,i_atom,shift,gid);
861 bDoVdW_i = (bDoVdW && bHaveVdW[type[i_atom]]);
862 bDoCoul_i = (bDoCoul && qi!=0);
864 if (bDoVdW_i || bDoCoul_i)
866 /* Loop over the j charge groups */
867 for(j=0; (j<nj); j++)
871 /* Check for large charge groups */
882 /* Finally loop over the atoms in the j-charge group */
883 for(jj=jj0; jj<jj1; jj++)
885 bNotEx = NOTEXCL(bExcl,i,jj);
893 add_j_to_nblist(coul,jj,bLR);
898 if (bHaveVdW[type[jj]])
900 add_j_to_nblist(vdw,jj,bLR);
905 if (bHaveVdW[type[jj]])
909 add_j_to_nblist(vdwc,jj,bLR);
913 add_j_to_nblist(vdw,jj,bLR);
916 else if (charge[jj] != 0)
918 add_j_to_nblist(coul,jj,bLR);
926 close_i_nblist(coul);
927 close_i_nblist(vdwc);
933 /* we are doing free energy */
934 vdwc_free = &nlist[eNL_VDWQQ_FREE];
935 vdw_free = &nlist[eNL_VDW_FREE];
936 coul_free = &nlist[eNL_QQ_FREE];
937 /* Loop over the atoms in the i charge group */
938 for(i=0; i<nicg; i++)
941 gid = GID(igid,jgid,ngid);
943 qiB = chargeB[i_atom];
945 /* Create new i_atom for each energy group */
946 if (bDoVdW && bDoCoul)
947 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
949 new_i_nblist(vdw,bLR,i_atom,shift,gid);
951 new_i_nblist(coul,bLR,i_atom,shift,gid);
953 new_i_nblist(vdw_free,bLR,i_atom,shift,gid);
954 new_i_nblist(coul_free,bLR,i_atom,shift,gid);
955 new_i_nblist(vdwc_free,bLR,i_atom,shift,gid);
957 bDoVdW_i = (bDoVdW &&
958 (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
959 bDoCoul_i = (bDoCoul && (qi!=0 || qiB!=0));
960 /* For TIP4P the first atom does not have a charge,
961 * but the last three do. So we should still put an atom
962 * without LJ but with charge in the water-atom neighborlist
963 * for a TIP4p i charge group.
964 * For SPC type water the first atom has LJ and charge,
965 * so there is no such problem.
967 if (iwater == esolNO)
969 bDoCoul_i_sol = bDoCoul_i;
973 bDoCoul_i_sol = bDoCoul;
976 if (bDoVdW_i || bDoCoul_i_sol)
978 /* Loop over the j charge groups */
979 for(j=0; (j<nj); j++)
983 /* Check for large charge groups */
994 /* Finally loop over the atoms in the j-charge group */
995 bFree = bPert[i_atom];
996 for(jj=jj0; (jj<jj1); jj++)
998 bFreeJ = bFree || bPert[jj];
999 /* Complicated if, because the water H's should also
1000 * see perturbed j-particles
1002 if (iwater==esolNO || i==0 || bFreeJ)
1004 bNotEx = NOTEXCL(bExcl,i,jj);
1012 if (charge[jj]!=0 || chargeB[jj]!=0)
1014 add_j_to_nblist(coul_free,jj,bLR);
1017 else if (!bDoCoul_i)
1019 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1021 add_j_to_nblist(vdw_free,jj,bLR);
1026 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1028 if (charge[jj]!=0 || chargeB[jj]!=0)
1030 add_j_to_nblist(vdwc_free,jj,bLR);
1034 add_j_to_nblist(vdw_free,jj,bLR);
1037 else if (charge[jj]!=0 || chargeB[jj]!=0)
1038 add_j_to_nblist(coul_free,jj,bLR);
1043 /* This is done whether or not bWater is set */
1044 if (charge[jj] != 0)
1046 add_j_to_nblist(coul,jj,bLR);
1049 else if (!bDoCoul_i_sol)
1051 if (bHaveVdW[type[jj]])
1053 add_j_to_nblist(vdw,jj,bLR);
1058 if (bHaveVdW[type[jj]])
1060 if (charge[jj] != 0)
1062 add_j_to_nblist(vdwc,jj,bLR);
1066 add_j_to_nblist(vdw,jj,bLR);
1069 else if (charge[jj] != 0)
1071 add_j_to_nblist(coul,jj,bLR);
1079 close_i_nblist(vdw);
1080 close_i_nblist(coul);
1081 close_i_nblist(vdwc);
1082 close_i_nblist(vdw_free);
1083 close_i_nblist(coul_free);
1084 close_i_nblist(vdwc_free);
1090 put_in_list_adress(gmx_bool bHaveVdW[],
1106 /* The a[] index has been removed,
1107 * to put it back in i_atom should be a[i0] and jj should be a[jj].
1112 t_nblist * vdwc_adress = NULL;
1113 t_nblist * vdw_adress = NULL;
1114 t_nblist * coul_adress = NULL;
1115 t_nblist * vdwc_ww = NULL;
1116 t_nblist * coul_ww = NULL;
1118 int i,j,jcg,igid,gid,nbl_ind,nbl_ind_adress;
1119 atom_id jj,jj0,jj1,i_atom;
1124 real *charge,*chargeB;
1127 gmx_bool bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
1128 gmx_bool bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
1130 gmx_bool j_all_atom;
1132 t_nblist *nlist, *nlist_adress;
1134 /* Copy some pointers */
1135 cginfo = fr->cginfo;
1136 charge = md->chargeA;
1137 chargeB = md->chargeB;
1140 bPert = md->bPerturbed;
1143 /* Get atom range */
1145 nicg = index[icg+1]-i0;
1147 /* Get the i charge group info */
1148 igid = GET_CGINFO_GID(cginfo[icg]);
1150 iwater = (solvent_opt!=esolNO) ? GET_CGINFO_SOLOPT(cginfo[icg]) : esolNO;
1154 gmx_fatal(FARGS,"AdResS does not support free energy pertubation\n");
1157 /* Unpack pointers to neighbourlist structs */
1158 if (fr->nnblists == 2)
1165 nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
1166 nbl_ind_adress = nbl_ind+fr->nnblists/2;
1170 nlist = fr->nblists[nbl_ind].nlist_lr;
1171 nlist_adress= fr->nblists[nbl_ind_adress].nlist_lr;
1175 nlist = fr->nblists[nbl_ind].nlist_sr;
1176 nlist_adress = fr->nblists[nbl_ind_adress].nlist_sr;
1180 vdwc = &nlist[eNL_VDWQQ];
1181 vdw = &nlist[eNL_VDW];
1182 coul = &nlist[eNL_QQ];
1184 vdwc_adress = &nlist_adress[eNL_VDWQQ];
1185 vdw_adress = &nlist_adress[eNL_VDW];
1186 coul_adress = &nlist_adress[eNL_QQ];
1188 /* We do not support solvent optimization with AdResS for now.
1189 For this we would need hybrid solvent-other kernels */
1191 /* no solvent as i charge group */
1192 /* Loop over the atoms in the i charge group */
1193 for(i=0; i<nicg; i++)
1196 gid = GID(igid,jgid,ngid);
1197 qi = charge[i_atom];
1199 /* Create new i_atom for each energy group */
1200 if (bDoVdW && bDoCoul)
1202 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
1203 new_i_nblist(vdwc_adress,bLR,i_atom,shift,gid);
1208 new_i_nblist(vdw,bLR,i_atom,shift,gid);
1209 new_i_nblist(vdw_adress,bLR,i_atom,shift,gid);
1214 new_i_nblist(coul,bLR,i_atom,shift,gid);
1215 new_i_nblist(coul_adress,bLR,i_atom,shift,gid);
1217 bDoVdW_i = (bDoVdW && bHaveVdW[type[i_atom]]);
1218 bDoCoul_i = (bDoCoul && qi!=0);
1220 if (bDoVdW_i || bDoCoul_i)
1222 /* Loop over the j charge groups */
1223 for(j=0; (j<nj); j++)
1227 /* Check for large charge groups */
1238 /* Finally loop over the atoms in the j-charge group */
1239 for(jj=jj0; jj<jj1; jj++)
1241 bNotEx = NOTEXCL(bExcl,i,jj);
1243 b_hybrid=!((wf[i_atom]==1&&wf[jj]==1)||(wf[i_atom] ==0 && wf[jj]==0));
1249 if (charge[jj] != 0)
1252 add_j_to_nblist(coul,jj,bLR);
1254 add_j_to_nblist(coul_adress,jj,bLR);
1258 else if (!bDoCoul_i)
1260 if (bHaveVdW[type[jj]])
1263 add_j_to_nblist(vdw,jj,bLR);
1265 add_j_to_nblist(vdw_adress,jj,bLR);
1271 if (bHaveVdW[type[jj]])
1273 if (charge[jj] != 0)
1276 add_j_to_nblist(vdwc,jj,bLR);
1278 add_j_to_nblist(vdwc_adress,jj,bLR);
1284 add_j_to_nblist(vdw,jj,bLR);
1286 add_j_to_nblist(vdw_adress,jj,bLR);
1291 else if (charge[jj] != 0)
1294 add_j_to_nblist(coul,jj,bLR);
1296 add_j_to_nblist(coul_adress,jj,bLR);
1305 close_i_nblist(vdw);
1306 close_i_nblist(coul);
1307 close_i_nblist(vdwc);
1308 close_i_nblist(vdw_adress);
1309 close_i_nblist(coul_adress);
1310 close_i_nblist(vdwc_adress);
1316 put_in_list_qmmm(gmx_bool bHaveVdW[],
1333 int i,j,jcg,igid,gid;
1334 atom_id jj,jj0,jj1,i_atom;
1338 /* Get atom range */
1340 nicg = index[icg+1]-i0;
1342 /* Get the i charge group info */
1343 igid = GET_CGINFO_GID(fr->cginfo[icg]);
1345 coul = &fr->QMMMlist;
1347 /* Loop over atoms in the ith charge group */
1348 for (i=0;i<nicg;i++)
1351 gid = GID(igid,jgid,ngid);
1352 /* Create new i_atom for each energy group */
1353 new_i_nblist(coul,bLR,i_atom,shift,gid);
1355 /* Loop over the j charge groups */
1360 /* Charge groups cannot have QM and MM atoms simultaneously */
1365 /* Finally loop over the atoms in the j-charge group */
1366 for(jj=jj0; jj<jj1; jj++)
1368 bNotEx = NOTEXCL(bExcl,i,jj);
1370 add_j_to_nblist(coul,jj,bLR);
1374 close_i_nblist(coul);
1379 put_in_list_cg(gmx_bool bHaveVdW[],
1396 int igid,gid,nbl_ind;
1400 cginfo = fr->cginfo[icg];
1402 igid = GET_CGINFO_GID(cginfo);
1403 gid = GID(igid,jgid,ngid);
1405 /* Unpack pointers to neighbourlist structs */
1406 if (fr->nnblists == 1)
1412 nbl_ind = fr->gid2nblists[gid];
1416 vdwc = &fr->nblists[nbl_ind].nlist_lr[eNL_VDWQQ];
1420 vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
1423 /* Make a new neighbor list for charge group icg.
1424 * Currently simply one neighbor list is made with LJ and Coulomb.
1425 * If required, zero interactions could be removed here
1426 * or in the force loop.
1428 new_i_nblist(vdwc,bLR,index[icg],shift,gid);
1429 vdwc->iinr_end[vdwc->nri] = index[icg+1];
1431 for(j=0; (j<nj); j++)
1434 /* Skip the icg-icg pairs if all self interactions are excluded */
1435 if (!(jcg == icg && GET_CGINFO_EXCL_INTRA(cginfo)))
1437 /* Here we add the j charge group jcg to the list,
1438 * exclusions are also added to the list.
1440 add_j_to_nblist_cg(vdwc,index[jcg],index[jcg+1],bExcl,icg==jcg,bLR);
1444 close_i_nblist(vdwc);
1447 static void setexcl(atom_id start,atom_id end,t_blocka *excl,gmx_bool b,
1454 for(i=start; i<end; i++)
1456 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1458 SETEXCL(bexcl,i-start,excl->a[k]);
1464 for(i=start; i<end; i++)
1466 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1468 RMEXCL(bexcl,i-start,excl->a[k]);
1474 int calc_naaj(int icg,int cgtot)
1478 if ((cgtot % 2) == 1)
1480 /* Odd number of charge groups, easy */
1481 naaj = 1 + (cgtot/2);
1483 else if ((cgtot % 4) == 0)
1485 /* Multiple of four is hard */
1522 fprintf(log,"naaj=%d\n",naaj);
1528 /************************************************
1530 * S I M P L E C O R E S T U F F
1532 ************************************************/
1534 static real calc_image_tric(rvec xi,rvec xj,matrix box,
1535 rvec b_inv,int *shift)
1537 /* This code assumes that the cut-off is smaller than
1538 * a half times the smallest diagonal element of the box.
1545 /* Compute diff vector */
1546 dz = xj[ZZ] - xi[ZZ];
1547 dy = xj[YY] - xi[YY];
1548 dx = xj[XX] - xi[XX];
1550 /* Perform NINT operation, using trunc operation, therefore
1551 * we first add 2.5 then subtract 2 again
1553 tz = dz*b_inv[ZZ] + h25;
1555 dz -= tz*box[ZZ][ZZ];
1556 dy -= tz*box[ZZ][YY];
1557 dx -= tz*box[ZZ][XX];
1559 ty = dy*b_inv[YY] + h25;
1561 dy -= ty*box[YY][YY];
1562 dx -= ty*box[YY][XX];
1564 tx = dx*b_inv[XX]+h25;
1566 dx -= tx*box[XX][XX];
1568 /* Distance squared */
1569 r2 = (dx*dx) + (dy*dy) + (dz*dz);
1571 *shift = XYZ2IS(tx,ty,tz);
1576 static real calc_image_rect(rvec xi,rvec xj,rvec box_size,
1577 rvec b_inv,int *shift)
1585 /* Compute diff vector */
1586 dx = xj[XX] - xi[XX];
1587 dy = xj[YY] - xi[YY];
1588 dz = xj[ZZ] - xi[ZZ];
1590 /* Perform NINT operation, using trunc operation, therefore
1591 * we first add 1.5 then subtract 1 again
1593 tx = dx*b_inv[XX] + h15;
1594 ty = dy*b_inv[YY] + h15;
1595 tz = dz*b_inv[ZZ] + h15;
1600 /* Correct diff vector for translation */
1601 ddx = tx*box_size[XX] - dx;
1602 ddy = ty*box_size[YY] - dy;
1603 ddz = tz*box_size[ZZ] - dz;
1605 /* Distance squared */
1606 r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
1608 *shift = XYZ2IS(tx,ty,tz);
1613 static void add_simple(t_ns_buf *nsbuf,int nrj,atom_id cg_j,
1614 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1615 int icg,int jgid,t_block *cgs,t_excl bexcl[],
1616 int shift,t_forcerec *fr,put_in_list_t *put_in_list)
1618 if (nsbuf->nj + nrj > MAX_CG)
1620 put_in_list(bHaveVdW,ngid,md,icg,jgid,nsbuf->ncg,nsbuf->jcg,
1621 cgs->index,bexcl,shift,fr,FALSE,TRUE,TRUE,fr->solvent_opt);
1622 /* Reset buffer contents */
1623 nsbuf->ncg = nsbuf->nj = 0;
1625 nsbuf->jcg[nsbuf->ncg++] = cg_j;
1629 static void ns_inner_tric(rvec x[],int icg,int *i_egp_flags,
1630 int njcg,atom_id jcg[],
1631 matrix box,rvec b_inv,real rcut2,
1632 t_block *cgs,t_ns_buf **ns_buf,
1633 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1634 t_excl bexcl[],t_forcerec *fr,
1635 put_in_list_t *put_in_list)
1639 int *cginfo=fr->cginfo;
1640 atom_id cg_j,*cgindex;
1643 cgindex = cgs->index;
1645 for(j=0; (j<njcg); j++)
1648 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1649 if (calc_image_tric(x[icg],x[cg_j],box,b_inv,&shift) < rcut2)
1651 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1652 if (!(i_egp_flags[jgid] & EGP_EXCL))
1654 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1655 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
1662 static void ns_inner_rect(rvec x[],int icg,int *i_egp_flags,
1663 int njcg,atom_id jcg[],
1664 gmx_bool bBox,rvec box_size,rvec b_inv,real rcut2,
1665 t_block *cgs,t_ns_buf **ns_buf,
1666 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1667 t_excl bexcl[],t_forcerec *fr,
1668 put_in_list_t *put_in_list)
1672 int *cginfo=fr->cginfo;
1673 atom_id cg_j,*cgindex;
1676 cgindex = cgs->index;
1680 for(j=0; (j<njcg); j++)
1683 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1684 if (calc_image_rect(x[icg],x[cg_j],box_size,b_inv,&shift) < rcut2)
1686 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1687 if (!(i_egp_flags[jgid] & EGP_EXCL))
1689 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1690 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
1698 for(j=0; (j<njcg); j++)
1701 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1702 if ((rcut2 == 0) || (distance2(x[icg],x[cg_j]) < rcut2)) {
1703 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1704 if (!(i_egp_flags[jgid] & EGP_EXCL))
1706 add_simple(&ns_buf[jgid][CENTRAL],nrj,cg_j,
1707 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,CENTRAL,fr,
1715 /* ns_simple_core needs to be adapted for QMMM still 2005 */
1717 static int ns_simple_core(t_forcerec *fr,
1718 gmx_localtop_t *top,
1720 matrix box,rvec box_size,
1721 t_excl bexcl[],atom_id *aaj,
1722 int ngid,t_ns_buf **ns_buf,
1723 put_in_list_t *put_in_list,gmx_bool bHaveVdW[])
1727 int nsearch,icg,jcg,igid,i0,nri,nn;
1730 /* atom_id *i_atoms; */
1731 t_block *cgs=&(top->cgs);
1732 t_blocka *excl=&(top->excls);
1735 gmx_bool bBox,bTriclinic;
1738 rlist2 = sqr(fr->rlist);
1740 bBox = (fr->ePBC != epbcNONE);
1743 for(m=0; (m<DIM); m++)
1745 b_inv[m] = divide(1.0,box_size[m]);
1747 bTriclinic = TRICLINIC(box);
1754 cginfo = fr->cginfo;
1757 for (icg=fr->cg0; (icg<fr->hcg); icg++)
1760 i0 = cgs->index[icg];
1761 nri = cgs->index[icg+1]-i0;
1762 i_atoms = &(cgs->a[i0]);
1763 i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
1764 setexcl(nri,i_atoms,excl,TRUE,bexcl);
1766 igid = GET_CGINFO_GID(cginfo[icg]);
1767 i_egp_flags = fr->egp_flags + ngid*igid;
1768 setexcl(cgs->index[icg],cgs->index[icg+1],excl,TRUE,bexcl);
1770 naaj=calc_naaj(icg,cgs->nr);
1773 ns_inner_tric(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1774 box,b_inv,rlist2,cgs,ns_buf,
1775 bHaveVdW,ngid,md,bexcl,fr,put_in_list);
1779 ns_inner_rect(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1780 bBox,box_size,b_inv,rlist2,cgs,ns_buf,
1781 bHaveVdW,ngid,md,bexcl,fr,put_in_list);
1785 for(nn=0; (nn<ngid); nn++)
1787 for(k=0; (k<SHIFTS); k++)
1789 nsbuf = &(ns_buf[nn][k]);
1792 put_in_list(bHaveVdW,ngid,md,icg,nn,nsbuf->ncg,nsbuf->jcg,
1793 cgs->index,bexcl,k,fr,FALSE,TRUE,TRUE,fr->solvent_opt);
1794 nsbuf->ncg=nsbuf->nj=0;
1798 /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
1799 setexcl(cgs->index[icg],cgs->index[icg+1],excl,FALSE,bexcl);
1801 close_neighbor_lists(fr,FALSE);
1806 /************************************************
1808 * N S 5 G R I D S T U F F
1810 ************************************************/
1812 static inline void get_dx(int Nx,real gridx,real rc2,int xgi,real x,
1813 int *dx0,int *dx1,real *dcx2)
1841 for(i=xgi0; i>=0; i--)
1843 dcx = (i+1)*gridx-x;
1850 for(i=xgi1; i<Nx; i++)
1863 static inline void get_dx_dd(int Nx,real gridx,real rc2,int xgi,real x,
1864 int ncpddc,int shift_min,int shift_max,
1865 int *g0,int *g1,real *dcx2)
1868 int g_min,g_max,shift_home;
1901 g_min = (shift_min == shift_home ? 0 : ncpddc);
1902 g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
1909 else if (shift_max < 0)
1924 /* Check one grid cell down */
1925 dcx = ((*g0 - 1) + 1)*gridx - x;
1937 /* Check one grid cell up */
1938 dcx = (*g1 + 1)*gridx - x;
1950 #define sqr(x) ((x)*(x))
1951 #define calc_dx2(XI,YI,ZI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]) + sqr(ZI-y[ZZ]))
1952 #define calc_cyl_dx2(XI,YI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]))
1953 /****************************************************
1955 * F A S T N E I G H B O R S E A R C H I N G
1957 * Optimized neighboursearching routine using grid
1958 * at least 1x1x1, see GROMACS manual
1960 ****************************************************/
1963 static void get_cutoff2(t_forcerec *fr,gmx_bool bDoLongRange,
1964 real *rvdw2,real *rcoul2,
1965 real *rs2,real *rm2,real *rl2)
1967 *rs2 = sqr(fr->rlist);
1969 if (bDoLongRange && fr->bTwinRange)
1971 /* The VdW and elec. LR cut-off's could be different,
1972 * so we can not simply set them to rlistlong.
1974 if (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(fr->vdwtype) &&
1975 fr->rvdw > fr->rlist)
1977 *rvdw2 = sqr(fr->rlistlong);
1981 *rvdw2 = sqr(fr->rvdw);
1983 if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(fr->eeltype) &&
1984 fr->rcoulomb > fr->rlist)
1986 *rcoul2 = sqr(fr->rlistlong);
1990 *rcoul2 = sqr(fr->rcoulomb);
1995 /* Workaround for a gcc -O3 or -ffast-math problem */
1999 *rm2 = min(*rvdw2,*rcoul2);
2000 *rl2 = max(*rvdw2,*rcoul2);
2003 static void init_nsgrid_lists(t_forcerec *fr,int ngid,gmx_ns_t *ns)
2005 real rvdw2,rcoul2,rs2,rm2,rl2;
2008 get_cutoff2(fr,TRUE,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
2010 /* Short range buffers */
2011 snew(ns->nl_sr,ngid);
2014 snew(ns->nlr_ljc,ngid);
2015 snew(ns->nlr_one,ngid);
2017 /* Always allocate both list types, since rcoulomb might now change with PME load balancing */
2018 /* Long range VdW and Coul buffers */
2019 snew(ns->nl_lr_ljc,ngid);
2020 /* Long range VdW or Coul only buffers */
2021 snew(ns->nl_lr_one,ngid);
2023 for(j=0; (j<ngid); j++) {
2024 snew(ns->nl_sr[j],MAX_CG);
2025 snew(ns->nl_lr_ljc[j],MAX_CG);
2026 snew(ns->nl_lr_one[j],MAX_CG);
2031 "ns5_core: rs2 = %g, rm2 = %g, rl2 = %g (nm^2)\n",
2036 static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
2037 matrix box,rvec box_size,int ngid,
2038 gmx_localtop_t *top,
2039 t_grid *grid,rvec x[],
2040 t_excl bexcl[],gmx_bool *bExcludeAlleg,
2041 t_nrnb *nrnb,t_mdatoms *md,
2042 real *lambda,real *dvdlambda,
2043 gmx_grppairener_t *grppener,
2044 put_in_list_t *put_in_list,
2045 gmx_bool bHaveVdW[],
2046 gmx_bool bDoLongRange,gmx_bool bMakeQMMMnblist)
2049 atom_id **nl_lr_ljc,**nl_lr_one,**nl_sr;
2050 int *nlr_ljc,*nlr_one,*nsr;
2051 gmx_domdec_t *dd=NULL;
2052 t_block *cgs=&(top->cgs);
2053 int *cginfo=fr->cginfo;
2054 /* atom_id *i_atoms,*cgsindex=cgs->index; */
2056 int cell_x,cell_y,cell_z;
2057 int d,tx,ty,tz,dx,dy,dz,cj;
2058 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
2059 int zsh_ty,zsh_tx,ysh_tx;
2061 int dx0,dx1,dy0,dy1,dz0,dz1;
2062 int Nx,Ny,Nz,shift=-1,j,nrj,nns,nn=-1;
2063 real gridx,gridy,gridz,grid_x,grid_y,grid_z;
2064 real *dcx2,*dcy2,*dcz2;
2066 int cg0,cg1,icg=-1,cgsnr,i0,igid,nri,naaj,max_jcg;
2067 int jcg0,jcg1,jjcg,cgj0,jgid;
2068 int *grida,*gridnra,*gridind;
2069 gmx_bool rvdw_lt_rcoul,rcoul_lt_rvdw;
2070 rvec xi,*cgcm,grid_offset;
2071 real r2,rs2,rvdw2,rcoul2,rm2,rl2,XI,YI,ZI,dcx,dcy,dcz,tmp1,tmp2;
2073 gmx_bool bDomDec,bTriclinicX,bTriclinicY;
2078 bDomDec = DOMAINDECOMP(cr);
2084 bTriclinicX = ((YY < grid->npbcdim &&
2085 (!bDomDec || dd->nc[YY]==1) && box[YY][XX] != 0) ||
2086 (ZZ < grid->npbcdim &&
2087 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][XX] != 0));
2088 bTriclinicY = (ZZ < grid->npbcdim &&
2089 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][YY] != 0);
2093 get_cutoff2(fr,bDoLongRange,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
2095 rvdw_lt_rcoul = (rvdw2 >= rcoul2);
2096 rcoul_lt_rvdw = (rcoul2 >= rvdw2);
2098 if (bMakeQMMMnblist)
2106 nl_lr_ljc = ns->nl_lr_ljc;
2107 nl_lr_one = ns->nl_lr_one;
2108 nlr_ljc = ns->nlr_ljc;
2109 nlr_one = ns->nlr_one;
2117 gridind = grid->index;
2118 gridnra = grid->nra;
2121 gridx = grid->cell_size[XX];
2122 gridy = grid->cell_size[YY];
2123 gridz = grid->cell_size[ZZ];
2127 copy_rvec(grid->cell_offset,grid_offset);
2128 copy_ivec(grid->ncpddc,ncpddc);
2133 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
2134 zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
2135 zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
2136 ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
2137 if (zsh_tx!=0 && ysh_tx!=0)
2139 /* This could happen due to rounding, when both ratios are 0.5 */
2148 /* We only want a list for the test particle */
2157 /* Set the shift range */
2158 for(d=0; d<DIM; d++)
2162 /* Check if we need periodicity shifts.
2163 * Without PBC or with domain decomposition we don't need them.
2165 if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
2172 box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
2183 /* Loop over charge groups */
2184 for(icg=cg0; (icg < cg1); icg++)
2186 igid = GET_CGINFO_GID(cginfo[icg]);
2187 /* Skip this charge group if all energy groups are excluded! */
2188 if (bExcludeAlleg[igid])
2193 i0 = cgs->index[icg];
2195 if (bMakeQMMMnblist)
2197 /* Skip this charge group if it is not a QM atom while making a
2198 * QM/MM neighbourlist
2200 if (md->bQM[i0]==FALSE)
2202 continue; /* MM particle, go to next particle */
2205 /* Compute the number of charge groups that fall within the control
2208 naaj = calc_naaj(icg,cgsnr);
2215 /* make a normal neighbourlist */
2219 /* Get the j charge-group and dd cell shift ranges */
2220 dd_get_ns_ranges(cr->dd,icg,&jcg0,&jcg1,sh0,sh1);
2225 /* Compute the number of charge groups that fall within the control
2228 naaj = calc_naaj(icg,cgsnr);
2234 /* The i-particle is awlways the test particle,
2235 * so we want all j-particles
2237 max_jcg = cgsnr - 1;
2241 max_jcg = jcg1 - cgsnr;
2246 i_egp_flags = fr->egp_flags + igid*ngid;
2248 /* Set the exclusions for the atoms in charge group icg using a bitmask */
2249 setexcl(i0,cgs->index[icg+1],&top->excls,TRUE,bexcl);
2251 ci2xyz(grid,icg,&cell_x,&cell_y,&cell_z);
2253 /* Changed iicg to icg, DvdS 990115
2254 * (but see consistency check above, DvdS 990330)
2257 fprintf(log,"icg=%5d, naaj=%5d, cell %d %d %d\n",
2258 icg,naaj,cell_x,cell_y,cell_z);
2260 /* Loop over shift vectors in three dimensions */
2261 for (tz=-shp[ZZ]; tz<=shp[ZZ]; tz++)
2263 ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
2264 /* Calculate range of cells in Z direction that have the shift tz */
2265 zgi = cell_z + tz*Nz;
2268 get_dx(Nz,gridz,rl2,zgi,ZI,&dz0,&dz1,dcz2);
2270 get_dx_dd(Nz,gridz,rl2,zgi,ZI-grid_offset[ZZ],
2271 ncpddc[ZZ],sh0[ZZ],sh1[ZZ],&dz0,&dz1,dcz2);
2277 for (ty=-shp[YY]; ty<=shp[YY]; ty++)
2279 YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
2280 /* Calculate range of cells in Y direction that have the shift ty */
2283 ygi = (int)(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
2287 ygi = cell_y + ty*Ny;
2290 get_dx(Ny,gridy,rl2,ygi,YI,&dy0,&dy1,dcy2);
2292 get_dx_dd(Ny,gridy,rl2,ygi,YI-grid_offset[YY],
2293 ncpddc[YY],sh0[YY],sh1[YY],&dy0,&dy1,dcy2);
2299 for (tx=-shp[XX]; tx<=shp[XX]; tx++)
2301 XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
2302 /* Calculate range of cells in X direction that have the shift tx */
2305 xgi = (int)(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
2309 xgi = cell_x + tx*Nx;
2312 get_dx(Nx,gridx,rl2,xgi*Nx,XI,&dx0,&dx1,dcx2);
2314 get_dx_dd(Nx,gridx,rl2,xgi,XI-grid_offset[XX],
2315 ncpddc[XX],sh0[XX],sh1[XX],&dx0,&dx1,dcx2);
2321 /* Adress: an explicit cg that has a weigthing function of 0 is excluded
2322 * from the neigbour list as it will not interact */
2323 if (fr->adress_type != eAdressOff){
2324 if (md->wf[cgs->index[icg]]==0 && egp_explicit(fr, igid)){
2328 /* Get shift vector */
2329 shift=XYZ2IS(tx,ty,tz);
2331 range_check(shift,0,SHIFTS);
2333 for(nn=0; (nn<ngid); nn++)
2340 fprintf(log,"shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
2341 shift,dx0,dx1,dy0,dy1,dz0,dz1);
2342 fprintf(log,"cgcm: %8.3f %8.3f %8.3f\n",cgcm[icg][XX],
2343 cgcm[icg][YY],cgcm[icg][ZZ]);
2344 fprintf(log,"xi: %8.3f %8.3f %8.3f\n",XI,YI,ZI);
2346 for (dx=dx0; (dx<=dx1); dx++)
2348 tmp1 = rl2 - dcx2[dx];
2349 for (dy=dy0; (dy<=dy1); dy++)
2351 tmp2 = tmp1 - dcy2[dy];
2354 for (dz=dz0; (dz<=dz1); dz++) {
2355 if (tmp2 > dcz2[dz]) {
2356 /* Find grid-cell cj in which possible neighbours are */
2357 cj = xyz2ci(Ny,Nz,dx,dy,dz);
2359 /* Check out how many cgs (nrj) there in this cell */
2362 /* Find the offset in the cg list */
2365 /* Check if all j's are out of range so we
2366 * can skip the whole cell.
2367 * Should save some time, especially with DD.
2370 (grida[cgj0] >= max_jcg &&
2371 (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
2377 for (j=0; (j<nrj); j++)
2379 jjcg = grida[cgj0+j];
2381 /* check whether this guy is in range! */
2382 if ((jjcg >= jcg0 && jjcg < jcg1) ||
2385 r2=calc_dx2(XI,YI,ZI,cgcm[jjcg]);
2387 /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
2388 jgid = GET_CGINFO_GID(cginfo[jjcg]);
2389 /* check energy group exclusions */
2390 if (!(i_egp_flags[jgid] & EGP_EXCL))
2394 if (nsr[jgid] >= MAX_CG)
2396 /* Add to short-range list */
2397 put_in_list(bHaveVdW,ngid,md,icg,jgid,
2398 nsr[jgid],nl_sr[jgid],
2399 cgs->index,/* cgsatoms, */ bexcl,
2400 shift,fr,FALSE,TRUE,TRUE,fr->solvent_opt);
2403 nl_sr[jgid][nsr[jgid]++]=jjcg;
2407 if (nlr_ljc[jgid] >= MAX_CG)
2409 /* Add to LJ+coulomb long-range list */
2410 put_in_list(bHaveVdW,ngid,md,icg,jgid,
2411 nlr_ljc[jgid],nl_lr_ljc[jgid],top->cgs.index,
2412 bexcl,shift,fr,TRUE,TRUE,TRUE,fr->solvent_opt);
2415 nl_lr_ljc[jgid][nlr_ljc[jgid]++]=jjcg;
2419 if (nlr_one[jgid] >= MAX_CG)
2421 /* Add to long-range list with only coul, or only LJ */
2422 put_in_list(bHaveVdW,ngid,md,icg,jgid,
2423 nlr_one[jgid],nl_lr_one[jgid],top->cgs.index,
2424 bexcl,shift,fr,TRUE,rvdw_lt_rcoul,rcoul_lt_rvdw,fr->solvent_opt);
2427 nl_lr_one[jgid][nlr_one[jgid]++]=jjcg;
2439 /* CHECK whether there is anything left in the buffers */
2440 for(nn=0; (nn<ngid); nn++)
2444 put_in_list(bHaveVdW,ngid,md,icg,nn,nsr[nn],nl_sr[nn],
2445 cgs->index, /* cgsatoms, */ bexcl,
2446 shift,fr,FALSE,TRUE,TRUE,fr->solvent_opt);
2449 if (nlr_ljc[nn] > 0)
2451 put_in_list(bHaveVdW,ngid,md,icg,nn,nlr_ljc[nn],
2452 nl_lr_ljc[nn],top->cgs.index,
2453 bexcl,shift,fr,TRUE,TRUE,TRUE,fr->solvent_opt);
2456 if (nlr_one[nn] > 0)
2458 put_in_list(bHaveVdW,ngid,md,icg,nn,nlr_one[nn],
2459 nl_lr_one[nn],top->cgs.index,
2460 bexcl,shift,fr,TRUE,rvdw_lt_rcoul,rcoul_lt_rvdw,fr->solvent_opt);
2466 /* setexcl(nri,i_atoms,&top->atoms.excl,FALSE,bexcl); */
2467 setexcl(cgs->index[icg],cgs->index[icg+1],&top->excls,FALSE,bexcl);
2469 /* No need to perform any left-over force calculations anymore (as we used to do here)
2470 * since we now save the proper long-range lists for later evaluation.
2475 /* Close neighbourlists */
2476 close_neighbor_lists(fr,bMakeQMMMnblist);
2481 void ns_realloc_natoms(gmx_ns_t *ns,int natoms)
2485 if (natoms > ns->nra_alloc)
2487 ns->nra_alloc = over_alloc_dd(natoms);
2488 srenew(ns->bexcl,ns->nra_alloc);
2489 for(i=0; i<ns->nra_alloc; i++)
2496 void init_ns(FILE *fplog,const t_commrec *cr,
2497 gmx_ns_t *ns,t_forcerec *fr,
2498 const gmx_mtop_t *mtop,
2501 int mt,icg,nr_in_cg,maxcg,i,j,jcg,ngid,ncg;
2505 /* Compute largest charge groups size (# atoms) */
2507 for(mt=0; mt<mtop->nmoltype; mt++) {
2508 cgs = &mtop->moltype[mt].cgs;
2509 for (icg=0; (icg < cgs->nr); icg++)
2511 nr_in_cg=max(nr_in_cg,(int)(cgs->index[icg+1]-cgs->index[icg]));
2515 /* Verify whether largest charge group is <= max cg.
2516 * This is determined by the type of the local exclusion type
2517 * Exclusions are stored in bits. (If the type is not large
2518 * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
2520 maxcg = sizeof(t_excl)*8;
2521 if (nr_in_cg > maxcg)
2523 gmx_fatal(FARGS,"Max #atoms in a charge group: %d > %d\n",
2527 ngid = mtop->groups.grps[egcENER].nr;
2528 snew(ns->bExcludeAlleg,ngid);
2529 for(i=0; i<ngid; i++) {
2530 ns->bExcludeAlleg[i] = TRUE;
2531 for(j=0; j<ngid; j++)
2533 if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
2535 ns->bExcludeAlleg[i] = FALSE;
2542 ns->grid = init_grid(fplog,fr);
2543 init_nsgrid_lists(fr,ngid,ns);
2548 snew(ns->ns_buf,ngid);
2549 for(i=0; (i<ngid); i++)
2551 snew(ns->ns_buf[i],SHIFTS);
2553 ncg = ncg_mtop(mtop);
2554 snew(ns->simple_aaj,2*ncg);
2555 for(jcg=0; (jcg<ncg); jcg++)
2557 ns->simple_aaj[jcg] = jcg;
2558 ns->simple_aaj[jcg+ncg] = jcg;
2562 /* Create array that determines whether or not atoms have VdW */
2563 snew(ns->bHaveVdW,fr->ntype);
2564 for(i=0; (i<fr->ntype); i++)
2566 for(j=0; (j<fr->ntype); j++)
2568 ns->bHaveVdW[i] = (ns->bHaveVdW[i] ||
2570 ((BHAMA(fr->nbfp,fr->ntype,i,j) != 0) ||
2571 (BHAMB(fr->nbfp,fr->ntype,i,j) != 0) ||
2572 (BHAMC(fr->nbfp,fr->ntype,i,j) != 0)) :
2573 ((C6(fr->nbfp,fr->ntype,i,j) != 0) ||
2574 (C12(fr->nbfp,fr->ntype,i,j) != 0))));
2578 pr_bvec(debug,0,"bHaveVdW",ns->bHaveVdW,fr->ntype,TRUE);
2582 if (!DOMAINDECOMP(cr))
2584 /* This could be reduced with particle decomposition */
2585 ns_realloc_natoms(ns,mtop->natoms);
2588 ns->nblist_initialized=FALSE;
2590 /* nbr list debug dump */
2592 char *ptr=getenv("GMX_DUMP_NL");
2595 ns->dump_nl=strtol(ptr,NULL,10);
2598 fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
2609 int search_neighbours(FILE *log,t_forcerec *fr,
2610 rvec x[],matrix box,
2611 gmx_localtop_t *top,
2612 gmx_groups_t *groups,
2614 t_nrnb *nrnb,t_mdatoms *md,
2615 real *lambda,real *dvdlambda,
2616 gmx_grppairener_t *grppener,
2618 gmx_bool bDoLongRangeNS,
2619 gmx_bool bPadListsForKernels)
2621 t_block *cgs=&(top->cgs);
2622 rvec box_size,grid_x0,grid_x1;
2624 real min_size,grid_dens;
2628 gmx_bool *i_egp_flags;
2629 int cg_start,cg_end,start,end;
2632 gmx_domdec_zones_t *dd_zones;
2633 put_in_list_t *put_in_list;
2637 /* Set some local variables */
2639 ngid = groups->grps[egcENER].nr;
2641 for(m=0; (m<DIM); m++)
2643 box_size[m] = box[m][m];
2646 if (fr->ePBC != epbcNONE)
2648 if (sqr(fr->rlistlong) >= max_cutoff2(fr->ePBC,box))
2650 gmx_fatal(FARGS,"One of the box vectors has become shorter than twice the cut-off length or box_yy-|box_zy| or box_zz has become smaller than the cut-off.");
2654 min_size = min(box_size[XX],min(box_size[YY],box_size[ZZ]));
2655 if (2*fr->rlistlong >= min_size)
2656 gmx_fatal(FARGS,"One of the box diagonal elements has become smaller than twice the cut-off length.");
2660 if (DOMAINDECOMP(cr))
2662 ns_realloc_natoms(ns,cgs->index[cgs->nr]);
2666 /* Reset the neighbourlists */
2667 reset_neighbor_lists(fr,TRUE,TRUE);
2669 if (bGrid && bFillGrid)
2673 if (DOMAINDECOMP(cr))
2675 dd_zones = domdec_zones(cr->dd);
2681 get_nsgrid_boundaries(grid->nboundeddim,box,NULL,NULL,NULL,NULL,
2682 cgs->nr,fr->cg_cm,grid_x0,grid_x1,&grid_dens);
2684 grid_first(log,grid,NULL,NULL,fr->ePBC,box,grid_x0,grid_x1,
2685 fr->rlistlong,grid_dens);
2689 /* Don't know why this all is... (DvdS 3/99) */
2695 end = (cgs->nr+1)/2;
2698 if (DOMAINDECOMP(cr))
2701 fill_grid(log,dd_zones,grid,end,-1,end,fr->cg_cm);
2703 grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
2707 fill_grid(log,NULL,grid,cgs->nr,fr->cg0,fr->hcg,fr->cg_cm);
2708 grid->icg0 = fr->cg0;
2709 grid->icg1 = fr->hcg;
2717 calc_elemnr(log,grid,start,end,cgs->nr);
2719 grid_last(log,grid,start,end,cgs->nr);
2723 check_grid(debug,grid);
2724 print_grid(debug,grid);
2729 /* Set the grid cell index for the test particle only.
2730 * The cell to cg index is not corrected, but that does not matter.
2732 fill_grid(log,NULL,ns->grid,fr->hcg,fr->hcg-1,fr->hcg,fr->cg_cm);
2736 if (fr->adress_type == eAdressOff){
2737 if (!fr->ns.bCGlist)
2739 put_in_list = put_in_list_at;
2743 put_in_list = put_in_list_cg;
2746 put_in_list = put_in_list_adress;
2753 nsearch = nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2754 grid,x,ns->bexcl,ns->bExcludeAlleg,
2755 nrnb,md,lambda,dvdlambda,grppener,
2756 put_in_list,ns->bHaveVdW,
2757 bDoLongRangeNS,FALSE);
2759 /* neighbour searching withouth QMMM! QM atoms have zero charge in
2760 * the classical calculation. The charge-charge interaction
2761 * between QM and MM atoms is handled in the QMMM core calculation
2762 * (see QMMM.c). The VDW however, we'd like to compute classically
2763 * and the QM MM atom pairs have just been put in the
2764 * corresponding neighbourlists. in case of QMMM we still need to
2765 * fill a special QMMM neighbourlist that contains all neighbours
2766 * of the QM atoms. If bQMMM is true, this list will now be made:
2768 if (fr->bQMMM && fr->qr->QMMMscheme!=eQMMMschemeoniom)
2770 nsearch += nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2771 grid,x,ns->bexcl,ns->bExcludeAlleg,
2772 nrnb,md,lambda,dvdlambda,grppener,
2773 put_in_list_qmmm,ns->bHaveVdW,
2774 bDoLongRangeNS,TRUE);
2779 nsearch = ns_simple_core(fr,top,md,box,box_size,
2780 ns->bexcl,ns->simple_aaj,
2781 ngid,ns->ns_buf,put_in_list,ns->bHaveVdW);
2789 inc_nrnb(nrnb,eNR_NS,nsearch);
2790 /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
2795 int natoms_beyond_ns_buffer(t_inputrec *ir,t_forcerec *fr,t_block *cgs,
2796 matrix scale_tot,rvec *x)
2798 int cg0,cg1,cg,a0,a1,a,i,j;
2799 real rint,hbuf2,scale;
2801 gmx_bool bIsotropic;
2806 rint = max(ir->rcoulomb,ir->rvdw);
2807 if (ir->rlist < rint)
2809 gmx_fatal(FARGS,"The neighbor search buffer has negative size: %f nm",
2817 if (!EI_DYNAMICS(ir->eI) || !DYNAMIC_BOX(*ir))
2819 hbuf2 = sqr(0.5*(ir->rlist - rint));
2820 for(cg=cg0; cg<cg1; cg++)
2822 a0 = cgs->index[cg];
2823 a1 = cgs->index[cg+1];
2824 for(a=a0; a<a1; a++)
2826 if (distance2(cg_cm[cg],x[a]) > hbuf2)
2836 scale = scale_tot[0][0];
2837 for(i=1; i<DIM; i++)
2839 /* With anisotropic scaling, the original spherical ns volumes become
2840 * ellipsoids. To avoid costly transformations we use the minimum
2841 * eigenvalue of the scaling matrix for determining the buffer size.
2842 * Since the lower half is 0, the eigenvalues are the diagonal elements.
2844 scale = min(scale,scale_tot[i][i]);
2845 if (scale_tot[i][i] != scale_tot[i-1][i-1])
2851 if (scale_tot[i][j] != 0)
2857 hbuf2 = sqr(0.5*(scale*ir->rlist - rint));
2860 for(cg=cg0; cg<cg1; cg++)
2862 svmul(scale,cg_cm[cg],cgsc);
2863 a0 = cgs->index[cg];
2864 a1 = cgs->index[cg+1];
2865 for(a=a0; a<a1; a++)
2867 if (distance2(cgsc,x[a]) > hbuf2)
2876 /* Anistropic scaling */
2877 for(cg=cg0; cg<cg1; cg++)
2879 /* Since scale_tot contains the transpose of the scaling matrix,
2880 * we need to multiply with the transpose.
2882 tmvmul_ur0(scale_tot,cg_cm[cg],cgsc);
2883 a0 = cgs->index[cg];
2884 a1 = cgs->index[cg+1];
2885 for(a=a0; a<a1; a++)
2887 if (distance2(cgsc,x[a]) > hbuf2)