Merge branch 'master' of git://git.gromacs.org/gromacs
[gromacs/adressmacs.git] / src / mdlib / ns.c
blobca0f9803f4f345399e8c068887310e6844074775
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
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.
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.
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.
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.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * GROwing Monsters And Cloning Shrimps
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #ifdef GMX_THREAD_SHM_FDECOMP
41 #include <pthread.h>
42 #endif
44 #include <math.h>
45 #include <string.h>
46 #include "sysstuff.h"
47 #include "smalloc.h"
48 #include "macros.h"
49 #include "maths.h"
50 #include "vec.h"
51 #include "network.h"
52 #include "nsgrid.h"
53 #include "force.h"
54 #include "nonbonded.h"
55 #include "ns.h"
56 #include "pbc.h"
57 #include "names.h"
58 #include "gmx_fatal.h"
59 #include "nrnb.h"
60 #include "txtdump.h"
61 #include "mtop_util.h"
63 #include "domdec.h"
64 #include "adress.h"
67 /*
68 * E X C L U S I O N H A N D L I N G
71 #ifdef DEBUG
72 static void SETEXCL_(t_excl e[],atom_id i,atom_id j)
73 { e[j] = e[j] | (1<<i); }
74 static void RMEXCL_(t_excl e[],atom_id i,atom_id j)
75 { e[j]=e[j] & ~(1<<i); }
76 static gmx_bool ISEXCL_(t_excl e[],atom_id i,atom_id j)
77 { return (gmx_bool)(e[j] & (1<<i)); }
78 static gmx_bool NOTEXCL_(t_excl e[],atom_id i,atom_id j)
79 { return !(ISEXCL(e,i,j)); }
80 #else
81 #define SETEXCL(e,i,j) (e)[((atom_id) (j))] |= (1<<((atom_id) (i)))
82 #define RMEXCL(e,i,j) (e)[((atom_id) (j))] &= (~(1<<((atom_id) (i))))
83 #define ISEXCL(e,i,j) (gmx_bool) ((e)[((atom_id) (j))] & (1<<((atom_id) (i))))
84 #define NOTEXCL(e,i,j) !(ISEXCL(e,i,j))
85 #endif
87 /************************************************
89 * U T I L I T I E S F O R N S
91 ************************************************/
93 static void reallocate_nblist(t_nblist *nl)
95 if (gmx_debug_at)
97 fprintf(debug,"reallocating neigborlist il_code=%d, maxnri=%d\n",
98 nl->il_code,nl->maxnri);
100 srenew(nl->iinr, nl->maxnri);
101 if (nl->enlist == enlistCG_CG)
103 srenew(nl->iinr_end,nl->maxnri);
105 srenew(nl->gid, nl->maxnri);
106 srenew(nl->shift, nl->maxnri);
107 srenew(nl->jindex, nl->maxnri+1);
110 /* ivdw/icoul are used to determine the type of interaction, so we
111 * can set an innerloop index here. The obvious choice for this would have
112 * been the vdwtype/coultype values in the forcerecord, but unfortunately
113 * those types are braindead - for instance both Buckingham and normal
114 * Lennard-Jones use the same value (evdwCUT), and a separate gmx_boolean variable
115 * to determine which interaction is used. There is further no special value
116 * for 'no interaction'. For backward compatibility with old TPR files we won't
117 * change this in the 3.x series, so when calling this routine you should use:
119 * icoul=0 no coulomb interaction
120 * icoul=1 cutoff standard coulomb
121 * icoul=2 reaction-field coulomb
122 * icoul=3 tabulated coulomb
124 * ivdw=0 no vdw interaction
125 * ivdw=1 standard L-J interaction
126 * ivdw=2 Buckingham
127 * ivdw=3 tabulated vdw.
129 * Kind of ugly, but it works.
131 static void init_nblist(t_nblist *nl_sr,t_nblist *nl_lr,
132 int maxsr,int maxlr,
133 int ivdw, int icoul,
134 gmx_bool bfree, int enlist)
136 t_nblist *nl;
137 int homenr;
138 int i,nn;
140 int inloop[20] =
142 eNR_NBKERNEL_NONE,
143 eNR_NBKERNEL010,
144 eNR_NBKERNEL020,
145 eNR_NBKERNEL030,
146 eNR_NBKERNEL100,
147 eNR_NBKERNEL110,
148 eNR_NBKERNEL120,
149 eNR_NBKERNEL130,
150 eNR_NBKERNEL200,
151 eNR_NBKERNEL210,
152 eNR_NBKERNEL220,
153 eNR_NBKERNEL230,
154 eNR_NBKERNEL300,
155 eNR_NBKERNEL310,
156 eNR_NBKERNEL320,
157 eNR_NBKERNEL330,
158 eNR_NBKERNEL400,
159 eNR_NBKERNEL410,
160 eNR_NBKERNEL_NONE,
161 eNR_NBKERNEL430
164 for(i=0; (i<2); i++)
166 nl = (i == 0) ? nl_sr : nl_lr;
167 homenr = (i == 0) ? maxsr : maxlr;
169 if (nl == NULL)
171 continue;
174 /* Set coul/vdw in neighborlist, and for the normal loops we determine
175 * an index of which one to call.
177 nl->ivdw = ivdw;
178 nl->icoul = icoul;
179 nl->free_energy = bfree;
181 if (bfree)
183 nl->enlist = enlistATOM_ATOM;
184 nl->il_code = eNR_NBKERNEL_FREE_ENERGY;
186 else
188 nl->enlist = enlist;
190 nn = inloop[4*icoul + ivdw];
192 /* solvent loops follow directly after the corresponding
193 * ordinary loops, in the order:
195 * SPC, SPC-SPC, TIP4p, TIP4p-TIP4p
198 switch (enlist) {
199 case enlistATOM_ATOM:
200 case enlistCG_CG:
201 break;
202 case enlistSPC_ATOM: nn += 1; break;
203 case enlistSPC_SPC: nn += 2; break;
204 case enlistTIP4P_ATOM: nn += 3; break;
205 case enlistTIP4P_TIP4P: nn += 4; break;
208 nl->il_code = nn;
211 if (debug)
212 fprintf(debug,"Initiating neighbourlist type %d for %s interactions,\nwith %d SR, %d LR atoms.\n",
213 nl->il_code,ENLISTTYPE(enlist),maxsr,maxlr);
215 /* maxnri is influenced by the number of shifts (maximum is 8)
216 * and the number of energy groups.
217 * If it is not enough, nl memory will be reallocated during the run.
218 * 4 seems to be a reasonable factor, which only causes reallocation
219 * during runs with tiny and many energygroups.
221 nl->maxnri = homenr*4;
222 nl->maxnrj = 0;
223 nl->maxlen = 0;
224 nl->nri = -1;
225 nl->nrj = 0;
226 nl->iinr = NULL;
227 nl->gid = NULL;
228 nl->shift = NULL;
229 nl->jindex = NULL;
230 reallocate_nblist(nl);
231 nl->jindex[0] = 0;
232 #ifdef GMX_THREAD_SHM_FDECOMP
233 nl->counter = 0;
234 snew(nl->mtx,1);
235 pthread_mutex_init(nl->mtx,NULL);
236 #endif
240 void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
242 /* Make maxlr tunable! (does not seem to be a big difference though)
243 * This parameter determines the number of i particles in a long range
244 * neighbourlist. Too few means many function calls, too many means
245 * cache trashing.
247 int maxsr,maxsr_wat,maxlr,maxlr_wat;
248 int icoul,icoulf,ivdw;
249 int solvent;
250 int enlist_def,enlist_w,enlist_ww;
251 int i;
252 t_nblists *nbl;
254 /* maxsr = homenr-fr->nWatMol*3; */
255 maxsr = homenr;
257 if (maxsr < 0)
259 gmx_fatal(FARGS,"%s, %d: Negative number of short range atoms.\n"
260 "Call your Gromacs dealer for assistance.",__FILE__,__LINE__);
262 /* This is just for initial allocation, so we do not reallocate
263 * all the nlist arrays many times in a row.
264 * The numbers seem very accurate, but they are uncritical.
266 maxsr_wat = min(fr->nWatMol,(homenr+2)/3);
267 if (fr->bTwinRange)
269 maxlr = 50;
270 maxlr_wat = min(maxsr_wat,maxlr);
272 else
274 maxlr = maxlr_wat = 0;
277 /* Determine the values for icoul/ivdw. */
278 /* Start with GB */
279 if(fr->bGB)
281 icoul=4;
283 else if (fr->bcoultab)
285 icoul = 3;
287 else if (EEL_RF(fr->eeltype))
289 icoul = 2;
291 else
293 icoul = 1;
296 if (fr->bvdwtab)
298 ivdw = 3;
300 else if (fr->bBHAM)
302 ivdw = 2;
304 else
306 ivdw = 1;
309 fr->ns.bCGlist = (getenv("GMX_NBLISTCG") != 0);
310 if (!fr->ns.bCGlist)
312 enlist_def = enlistATOM_ATOM;
314 else
316 enlist_def = enlistCG_CG;
317 if (log != NULL)
319 fprintf(log,"\nUsing charge-group - charge-group neighbor lists and kernels\n\n");
321 if (!fr->bExcl_IntraCGAll_InterCGNone)
323 gmx_fatal(FARGS,"The charge-group - charge-group force loops only support systems with all intra-cg interactions excluded and no inter-cg exclusions, this is not the case for this system.");
327 if (fr->solvent_opt == esolTIP4P) {
328 enlist_w = enlistTIP4P_ATOM;
329 enlist_ww = enlistTIP4P_TIP4P;
330 } else {
331 enlist_w = enlistSPC_ATOM;
332 enlist_ww = enlistSPC_SPC;
335 for(i=0; i<fr->nnblists; i++)
337 nbl = &(fr->nblists[i]);
338 init_nblist(&nbl->nlist_sr[eNL_VDWQQ],&nbl->nlist_lr[eNL_VDWQQ],
339 maxsr,maxlr,ivdw,icoul,FALSE,enlist_def);
340 init_nblist(&nbl->nlist_sr[eNL_VDW],&nbl->nlist_lr[eNL_VDW],
341 maxsr,maxlr,ivdw,0,FALSE,enlist_def);
342 init_nblist(&nbl->nlist_sr[eNL_QQ],&nbl->nlist_lr[eNL_QQ],
343 maxsr,maxlr,0,icoul,FALSE,enlist_def);
344 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATER],&nbl->nlist_lr[eNL_VDWQQ_WATER],
345 maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_w);
346 init_nblist(&nbl->nlist_sr[eNL_QQ_WATER],&nbl->nlist_lr[eNL_QQ_WATER],
347 maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_w);
348 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATERWATER],&nbl->nlist_lr[eNL_VDWQQ_WATERWATER],
349 maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_ww);
350 init_nblist(&nbl->nlist_sr[eNL_QQ_WATERWATER],&nbl->nlist_lr[eNL_QQ_WATERWATER],
351 maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_ww);
353 if (fr->efep != efepNO)
355 if (fr->bEwald)
357 icoulf = 5;
359 else
361 icoulf = icoul;
364 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_FREE],&nbl->nlist_lr[eNL_VDWQQ_FREE],
365 maxsr,maxlr,ivdw,icoulf,TRUE,enlistATOM_ATOM);
366 init_nblist(&nbl->nlist_sr[eNL_VDW_FREE],&nbl->nlist_lr[eNL_VDW_FREE],
367 maxsr,maxlr,ivdw,0,TRUE,enlistATOM_ATOM);
368 init_nblist(&nbl->nlist_sr[eNL_QQ_FREE],&nbl->nlist_lr[eNL_QQ_FREE],
369 maxsr,maxlr,0,icoulf,TRUE,enlistATOM_ATOM);
372 /* QMMM MM list */
373 if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
375 init_nblist(&fr->QMMMlist,NULL,
376 maxsr,maxlr,0,icoul,FALSE,enlistATOM_ATOM);
379 fr->ns.nblist_initialized=TRUE;
382 static void reset_nblist(t_nblist *nl)
384 nl->nri = -1;
385 nl->nrj = 0;
386 nl->maxlen = 0;
387 if (nl->jindex)
389 nl->jindex[0] = 0;
393 static void reset_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL)
395 int n,i;
397 if (bLR)
399 reset_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
401 else
403 for(n=0; n<fr->nnblists; n++)
405 for(i=0; i<eNL_NR; i++)
407 reset_nblist(&(fr->nblists[n].nlist_sr[i]));
410 if (fr->bQMMM)
412 /* only reset the short-range nblist */
413 reset_nblist(&(fr->QMMMlist));
421 static inline void new_i_nblist(t_nblist *nlist,
422 gmx_bool bLR,atom_id i_atom,int shift,int gid)
424 int i,k,nri,nshift;
426 nri = nlist->nri;
428 /* Check whether we have to increase the i counter */
429 if ((nri == -1) ||
430 (nlist->iinr[nri] != i_atom) ||
431 (nlist->shift[nri] != shift) ||
432 (nlist->gid[nri] != gid))
434 /* This is something else. Now see if any entries have
435 * been added in the list of the previous atom.
437 if ((nri == -1) ||
438 ((nlist->jindex[nri+1] > nlist->jindex[nri]) &&
439 (nlist->gid[nri] != -1)))
441 /* If so increase the counter */
442 nlist->nri++;
443 nri++;
444 if (nlist->nri >= nlist->maxnri)
446 nlist->maxnri += over_alloc_large(nlist->nri);
447 reallocate_nblist(nlist);
450 /* Set the number of neighbours and the atom number */
451 nlist->jindex[nri+1] = nlist->jindex[nri];
452 nlist->iinr[nri] = i_atom;
453 nlist->gid[nri] = gid;
454 nlist->shift[nri] = shift;
458 static inline void close_i_nblist(t_nblist *nlist)
460 int nri = nlist->nri;
461 int len;
463 if (nri >= 0)
465 nlist->jindex[nri+1] = nlist->nrj;
467 len=nlist->nrj - nlist->jindex[nri];
469 /* nlist length for water i molecules is treated statically
470 * in the innerloops
472 if (len > nlist->maxlen)
474 nlist->maxlen = len;
479 static inline void close_nblist(t_nblist *nlist)
481 /* Only close this nblist when it has been initialized.
482 * Avoid the creation of i-lists with no j-particles.
484 if (nlist->nrj == 0)
486 /* Some assembly kernels do not support empty lists,
487 * make sure here that we don't generate any empty lists.
488 * With the current ns code this branch is taken in two cases:
489 * No i-particles at all: nri=-1 here
490 * There are i-particles, but no j-particles; nri=0 here
492 nlist->nri = 0;
494 else
496 /* Close list number nri by incrementing the count */
497 nlist->nri++;
501 static inline void close_neighbor_list(t_forcerec *fr,gmx_bool bLR,int nls,int eNL,
502 gmx_bool bMakeQMMMnblist)
504 int n,i;
506 if (bMakeQMMMnblist) {
507 if (!bLR)
509 close_nblist(&(fr->QMMMlist));
512 else
514 if (bLR)
516 close_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
518 else
520 for(n=0; n<fr->nnblists; n++)
522 for(i=0; (i<eNL_NR); i++)
524 close_nblist(&(fr->nblists[n].nlist_sr[i]));
531 static inline void add_j_to_nblist(t_nblist *nlist,atom_id j_atom,gmx_bool bLR)
533 int nrj=nlist->nrj;
535 if (nlist->nrj >= nlist->maxnrj)
537 nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
538 if (gmx_debug_at)
539 fprintf(debug,"Increasing %s nblist %s j size to %d\n",
540 bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
542 srenew(nlist->jjnr,nlist->maxnrj);
545 nlist->jjnr[nrj] = j_atom;
546 nlist->nrj ++;
549 static inline void add_j_to_nblist_cg(t_nblist *nlist,
550 atom_id j_start,int j_end,
551 t_excl *bexcl,gmx_bool bLR)
553 int nrj=nlist->nrj;
554 int j;
556 if (nlist->nrj >= nlist->maxnrj)
558 nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
559 if (gmx_debug_at)
560 fprintf(debug,"Increasing %s nblist %s j size to %d\n",
561 bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
563 srenew(nlist->jjnr ,nlist->maxnrj);
564 srenew(nlist->jjnr_end,nlist->maxnrj);
565 srenew(nlist->excl ,nlist->maxnrj*MAX_CGCGSIZE);
568 nlist->jjnr[nrj] = j_start;
569 nlist->jjnr_end[nrj] = j_end;
571 if (j_end - j_start > MAX_CGCGSIZE)
573 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);
576 /* Set the exclusions */
577 for(j=j_start; j<j_end; j++)
579 nlist->excl[nrj*MAX_CGCGSIZE + j - j_start] = bexcl[j];
582 nlist->nrj ++;
585 typedef void
586 put_in_list_t(gmx_bool bHaveVdW[],
587 int ngid,
588 t_mdatoms * md,
589 int icg,
590 int jgid,
591 int nj,
592 atom_id jjcg[],
593 atom_id index[],
594 t_excl bExcl[],
595 int shift,
596 t_forcerec * fr,
597 gmx_bool bLR,
598 gmx_bool bDoVdW,
599 gmx_bool bDoCoul);
601 static void
602 put_in_list_at(gmx_bool bHaveVdW[],
603 int ngid,
604 t_mdatoms * md,
605 int icg,
606 int jgid,
607 int nj,
608 atom_id jjcg[],
609 atom_id index[],
610 t_excl bExcl[],
611 int shift,
612 t_forcerec * fr,
613 gmx_bool bLR,
614 gmx_bool bDoVdW,
615 gmx_bool bDoCoul)
617 /* The a[] index has been removed,
618 * to put it back in i_atom should be a[i0] and jj should be a[jj].
620 t_nblist * vdwc;
621 t_nblist * vdw;
622 t_nblist * coul;
623 t_nblist * vdwc_free = NULL;
624 t_nblist * vdw_free = NULL;
625 t_nblist * coul_free = NULL;
626 t_nblist * vdwc_ww = NULL;
627 t_nblist * coul_ww = NULL;
629 int i,j,jcg,igid,gid,nbl_ind,ind_ij;
630 atom_id jj,jj0,jj1,i_atom;
631 int i0,nicg,len;
633 int *cginfo;
634 int *type,*typeB;
635 real *charge,*chargeB;
636 real qi,qiB,qq,rlj;
637 gmx_bool bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
638 gmx_bool bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
639 int iwater,jwater;
640 t_nblist *nlist;
642 /* Copy some pointers */
643 cginfo = fr->cginfo;
644 charge = md->chargeA;
645 chargeB = md->chargeB;
646 type = md->typeA;
647 typeB = md->typeB;
648 bPert = md->bPerturbed;
650 /* Get atom range */
651 i0 = index[icg];
652 nicg = index[icg+1]-i0;
654 /* Get the i charge group info */
655 igid = GET_CGINFO_GID(cginfo[icg]);
656 iwater = GET_CGINFO_SOLOPT(cginfo[icg]);
658 bFreeEnergy = FALSE;
659 if (md->nPerturbed)
661 /* Check if any of the particles involved are perturbed.
662 * If not we can do the cheaper normal put_in_list
663 * and use more solvent optimization.
665 for(i=0; i<nicg; i++)
667 bFreeEnergy |= bPert[i0+i];
669 /* Loop over the j charge groups */
670 for(j=0; (j<nj && !bFreeEnergy); j++)
672 jcg = jjcg[j];
673 jj0 = index[jcg];
674 jj1 = index[jcg+1];
675 /* Finally loop over the atoms in the j-charge group */
676 for(jj=jj0; jj<jj1; jj++)
678 bFreeEnergy |= bPert[jj];
683 /* Unpack pointers to neighbourlist structs */
684 if (fr->nnblists == 1)
686 nbl_ind = 0;
688 else
690 nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
692 if (bLR)
694 nlist = fr->nblists[nbl_ind].nlist_lr;
696 else
698 nlist = fr->nblists[nbl_ind].nlist_sr;
701 if (iwater != esolNO)
703 vdwc = &nlist[eNL_VDWQQ_WATER];
704 vdw = &nlist[eNL_VDW];
705 coul = &nlist[eNL_QQ_WATER];
706 #ifndef DISABLE_WATERWATER_NLIST
707 vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
708 coul_ww = &nlist[eNL_QQ_WATERWATER];
709 #endif
711 else
713 vdwc = &nlist[eNL_VDWQQ];
714 vdw = &nlist[eNL_VDW];
715 coul = &nlist[eNL_QQ];
718 if (!bFreeEnergy)
720 if (iwater != esolNO)
722 /* Loop over the atoms in the i charge group */
723 i_atom = i0;
724 gid = GID(igid,jgid,ngid);
725 /* Create new i_atom for each energy group */
726 if (bDoCoul && bDoVdW)
728 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
729 #ifndef DISABLE_WATERWATER_NLIST
730 new_i_nblist(vdwc_ww,bLR,i_atom,shift,gid);
731 #endif
733 if (bDoVdW)
735 new_i_nblist(vdw,bLR,i_atom,shift,gid);
737 if (bDoCoul)
739 new_i_nblist(coul,bLR,i_atom,shift,gid);
740 #ifndef DISABLE_WATERWATER_NLIST
741 new_i_nblist(coul_ww,bLR,i_atom,shift,gid);
742 #endif
744 /* Loop over the j charge groups */
745 for(j=0; (j<nj); j++)
747 jcg=jjcg[j];
749 if (jcg == icg)
751 continue;
754 jj0 = index[jcg];
755 jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
757 if (iwater == esolSPC && jwater == esolSPC)
759 /* Interaction between two SPC molecules */
760 if (!bDoCoul)
762 /* VdW only - only first atoms in each water interact */
763 add_j_to_nblist(vdw,jj0,bLR);
765 else
767 #ifdef DISABLE_WATERWATER_NLIST
768 /* Add entries for the three atoms - only do VdW if we need to */
769 if (!bDoVdW)
771 add_j_to_nblist(coul,jj0,bLR);
773 else
775 add_j_to_nblist(vdwc,jj0,bLR);
777 add_j_to_nblist(coul,jj0+1,bLR);
778 add_j_to_nblist(coul,jj0+2,bLR);
779 #else
780 /* One entry for the entire water-water interaction */
781 if (!bDoVdW)
783 add_j_to_nblist(coul_ww,jj0,bLR);
785 else
787 add_j_to_nblist(vdwc_ww,jj0,bLR);
789 #endif
792 else if (iwater == esolTIP4P && jwater == esolTIP4P)
794 /* Interaction between two TIP4p molecules */
795 if (!bDoCoul)
797 /* VdW only - only first atoms in each water interact */
798 add_j_to_nblist(vdw,jj0,bLR);
800 else
802 #ifdef DISABLE_WATERWATER_NLIST
803 /* Add entries for the four atoms - only do VdW if we need to */
804 if (bDoVdW)
806 add_j_to_nblist(vdw,jj0,bLR);
808 add_j_to_nblist(coul,jj0+1,bLR);
809 add_j_to_nblist(coul,jj0+2,bLR);
810 add_j_to_nblist(coul,jj0+3,bLR);
811 #else
812 /* One entry for the entire water-water interaction */
813 if (!bDoVdW)
815 add_j_to_nblist(coul_ww,jj0,bLR);
817 else
819 add_j_to_nblist(vdwc_ww,jj0,bLR);
821 #endif
824 else
826 /* j charge group is not water, but i is.
827 * Add entries to the water-other_atom lists; the geometry of the water
828 * molecule doesn't matter - that is taken care of in the nonbonded kernel,
829 * so we don't care if it is SPC or TIP4P...
832 jj1 = index[jcg+1];
834 if (!bDoVdW)
836 for(jj=jj0; (jj<jj1); jj++)
838 if (charge[jj] != 0)
840 add_j_to_nblist(coul,jj,bLR);
844 else if (!bDoCoul)
846 for(jj=jj0; (jj<jj1); jj++)
848 if (bHaveVdW[type[jj]])
850 add_j_to_nblist(vdw,jj,bLR);
854 else
856 /* _charge_ _groups_ interact with both coulomb and LJ */
857 /* Check which atoms we should add to the lists! */
858 for(jj=jj0; (jj<jj1); jj++)
860 if (bHaveVdW[type[jj]])
862 if (charge[jj] != 0)
864 add_j_to_nblist(vdwc,jj,bLR);
866 else
868 add_j_to_nblist(vdw,jj,bLR);
871 else if (charge[jj] != 0)
873 add_j_to_nblist(coul,jj,bLR);
879 close_i_nblist(vdw);
880 close_i_nblist(coul);
881 close_i_nblist(vdwc);
882 #ifndef DISABLE_WATERWATER_NLIST
883 close_i_nblist(coul_ww);
884 close_i_nblist(vdwc_ww);
885 #endif
887 else
889 /* no solvent as i charge group */
890 /* Loop over the atoms in the i charge group */
891 for(i=0; i<nicg; i++)
893 i_atom = i0+i;
894 gid = GID(igid,jgid,ngid);
895 qi = charge[i_atom];
897 /* Create new i_atom for each energy group */
898 if (bDoVdW && bDoCoul)
900 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
902 if (bDoVdW)
904 new_i_nblist(vdw,bLR,i_atom,shift,gid);
906 if (bDoCoul)
908 new_i_nblist(coul,bLR,i_atom,shift,gid);
910 bDoVdW_i = (bDoVdW && bHaveVdW[type[i_atom]]);
911 bDoCoul_i = (bDoCoul && qi!=0);
913 if (bDoVdW_i || bDoCoul_i)
915 /* Loop over the j charge groups */
916 for(j=0; (j<nj); j++)
918 jcg=jjcg[j];
920 /* Check for large charge groups */
921 if (jcg == icg)
923 jj0 = i0 + i + 1;
925 else
927 jj0 = index[jcg];
930 jj1=index[jcg+1];
931 /* Finally loop over the atoms in the j-charge group */
932 for(jj=jj0; jj<jj1; jj++)
934 bNotEx = NOTEXCL(bExcl,i,jj);
936 if (bNotEx)
938 if (!bDoVdW_i)
940 if (charge[jj] != 0)
942 add_j_to_nblist(coul,jj,bLR);
945 else if (!bDoCoul_i)
947 if (bHaveVdW[type[jj]])
949 add_j_to_nblist(vdw,jj,bLR);
952 else
954 if (bHaveVdW[type[jj]])
956 if (charge[jj] != 0)
958 add_j_to_nblist(vdwc,jj,bLR);
960 else
962 add_j_to_nblist(vdw,jj,bLR);
965 else if (charge[jj] != 0)
967 add_j_to_nblist(coul,jj,bLR);
974 close_i_nblist(vdw);
975 close_i_nblist(coul);
976 close_i_nblist(vdwc);
980 else
982 /* we are doing free energy */
983 vdwc_free = &nlist[eNL_VDWQQ_FREE];
984 vdw_free = &nlist[eNL_VDW_FREE];
985 coul_free = &nlist[eNL_QQ_FREE];
986 /* Loop over the atoms in the i charge group */
987 for(i=0; i<nicg; i++)
989 i_atom = i0+i;
990 gid = GID(igid,jgid,ngid);
991 qi = charge[i_atom];
992 qiB = chargeB[i_atom];
994 /* Create new i_atom for each energy group */
995 if (bDoVdW && bDoCoul)
996 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
997 if (bDoVdW)
998 new_i_nblist(vdw,bLR,i_atom,shift,gid);
999 if (bDoCoul)
1000 new_i_nblist(coul,bLR,i_atom,shift,gid);
1002 new_i_nblist(vdw_free,bLR,i_atom,shift,gid);
1003 new_i_nblist(coul_free,bLR,i_atom,shift,gid);
1004 new_i_nblist(vdwc_free,bLR,i_atom,shift,gid);
1006 bDoVdW_i = (bDoVdW &&
1007 (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
1008 bDoCoul_i = (bDoCoul && (qi!=0 || qiB!=0));
1009 /* For TIP4P the first atom does not have a charge,
1010 * but the last three do. So we should still put an atom
1011 * without LJ but with charge in the water-atom neighborlist
1012 * for a TIP4p i charge group.
1013 * For SPC type water the first atom has LJ and charge,
1014 * so there is no such problem.
1016 if (iwater == esolNO)
1018 bDoCoul_i_sol = bDoCoul_i;
1020 else
1022 bDoCoul_i_sol = bDoCoul;
1025 if (bDoVdW_i || bDoCoul_i_sol)
1027 /* Loop over the j charge groups */
1028 for(j=0; (j<nj); j++)
1030 jcg=jjcg[j];
1032 /* Check for large charge groups */
1033 if (jcg == icg)
1035 jj0 = i0 + i + 1;
1037 else
1039 jj0 = index[jcg];
1042 jj1=index[jcg+1];
1043 /* Finally loop over the atoms in the j-charge group */
1044 bFree = bPert[i_atom];
1045 for(jj=jj0; (jj<jj1); jj++)
1047 bFreeJ = bFree || bPert[jj];
1048 /* Complicated if, because the water H's should also
1049 * see perturbed j-particles
1051 if (iwater==esolNO || i==0 || bFreeJ)
1053 bNotEx = NOTEXCL(bExcl,i,jj);
1055 if (bNotEx)
1057 if (bFreeJ)
1059 if (!bDoVdW_i)
1061 if (charge[jj]!=0 || chargeB[jj]!=0)
1063 add_j_to_nblist(coul_free,jj,bLR);
1066 else if (!bDoCoul_i)
1068 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1070 add_j_to_nblist(vdw_free,jj,bLR);
1073 else
1075 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1077 if (charge[jj]!=0 || chargeB[jj]!=0)
1079 add_j_to_nblist(vdwc_free,jj,bLR);
1081 else
1083 add_j_to_nblist(vdw_free,jj,bLR);
1086 else if (charge[jj]!=0 || chargeB[jj]!=0)
1087 add_j_to_nblist(coul_free,jj,bLR);
1090 else if (!bDoVdW_i)
1092 /* This is done whether or not bWater is set */
1093 if (charge[jj] != 0)
1095 add_j_to_nblist(coul,jj,bLR);
1098 else if (!bDoCoul_i_sol)
1100 if (bHaveVdW[type[jj]])
1102 add_j_to_nblist(vdw,jj,bLR);
1105 else
1107 if (bHaveVdW[type[jj]])
1109 if (charge[jj] != 0)
1111 add_j_to_nblist(vdwc,jj,bLR);
1113 else
1115 add_j_to_nblist(vdw,jj,bLR);
1118 else if (charge[jj] != 0)
1120 add_j_to_nblist(coul,jj,bLR);
1128 close_i_nblist(vdw);
1129 close_i_nblist(coul);
1130 close_i_nblist(vdwc);
1131 close_i_nblist(vdw_free);
1132 close_i_nblist(coul_free);
1133 close_i_nblist(vdwc_free);
1138 static void
1139 put_in_list_qmmm(gmx_bool bHaveVdW[],
1140 int ngid,
1141 t_mdatoms * md,
1142 int icg,
1143 int jgid,
1144 int nj,
1145 atom_id jjcg[],
1146 atom_id index[],
1147 t_excl bExcl[],
1148 int shift,
1149 t_forcerec * fr,
1150 gmx_bool bLR,
1151 gmx_bool bDoVdW,
1152 gmx_bool bDoCoul)
1154 t_nblist * coul;
1155 int i,j,jcg,igid,gid;
1156 atom_id jj,jj0,jj1,i_atom;
1157 int i0,nicg;
1158 gmx_bool bNotEx;
1160 /* Get atom range */
1161 i0 = index[icg];
1162 nicg = index[icg+1]-i0;
1164 /* Get the i charge group info */
1165 igid = GET_CGINFO_GID(fr->cginfo[icg]);
1167 coul = &fr->QMMMlist;
1169 /* Loop over atoms in the ith charge group */
1170 for (i=0;i<nicg;i++)
1172 i_atom = i0+i;
1173 gid = GID(igid,jgid,ngid);
1174 /* Create new i_atom for each energy group */
1175 new_i_nblist(coul,bLR,i_atom,shift,gid);
1177 /* Loop over the j charge groups */
1178 for (j=0;j<nj;j++)
1180 jcg=jjcg[j];
1182 /* Charge groups cannot have QM and MM atoms simultaneously */
1183 if (jcg!=icg)
1185 jj0 = index[jcg];
1186 jj1 = index[jcg+1];
1187 /* Finally loop over the atoms in the j-charge group */
1188 for(jj=jj0; jj<jj1; jj++)
1190 bNotEx = NOTEXCL(bExcl,i,jj);
1191 if(bNotEx)
1192 add_j_to_nblist(coul,jj,bLR);
1196 close_i_nblist(coul);
1200 static void
1201 put_in_list_cg(gmx_bool bHaveVdW[],
1202 int ngid,
1203 t_mdatoms * md,
1204 int icg,
1205 int jgid,
1206 int nj,
1207 atom_id jjcg[],
1208 atom_id index[],
1209 t_excl bExcl[],
1210 int shift,
1211 t_forcerec * fr,
1212 gmx_bool bLR,
1213 gmx_bool bDoVdW,
1214 gmx_bool bDoCoul)
1216 int cginfo;
1217 int igid,gid,nbl_ind;
1218 t_nblist * vdwc;
1219 int j,jcg;
1221 cginfo = fr->cginfo[icg];
1223 igid = GET_CGINFO_GID(cginfo);
1224 gid = GID(igid,jgid,ngid);
1226 /* Unpack pointers to neighbourlist structs */
1227 if (fr->nnblists == 1)
1229 nbl_ind = 0;
1231 else
1233 nbl_ind = fr->gid2nblists[gid];
1235 if (bLR)
1237 vdwc = &fr->nblists[nbl_ind].nlist_lr[eNL_VDWQQ];
1239 else
1241 vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
1244 /* Make a new neighbor list for charge group icg.
1245 * Currently simply one neighbor list is made with LJ and Coulomb.
1246 * If required, zero interactions could be removed here
1247 * or in the force loop.
1249 new_i_nblist(vdwc,bLR,index[icg],shift,gid);
1250 vdwc->iinr_end[vdwc->nri] = index[icg+1];
1252 for(j=0; (j<nj); j++)
1254 jcg = jjcg[j];
1255 /* Skip the icg-icg pairs if all self interactions are excluded */
1256 if (!(jcg == icg && GET_CGINFO_EXCL_INTRA(cginfo)))
1258 /* Here we add the j charge group jcg to the list,
1259 * exclusions are also added to the list.
1261 add_j_to_nblist_cg(vdwc,index[jcg],index[jcg+1],bExcl,bLR);
1265 close_i_nblist(vdwc);
1268 static void setexcl(atom_id start,atom_id end,t_blocka *excl,gmx_bool b,
1269 t_excl bexcl[])
1271 atom_id i,k;
1273 if (b)
1275 for(i=start; i<end; i++)
1277 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1279 SETEXCL(bexcl,i-start,excl->a[k]);
1283 else
1285 for(i=start; i<end; i++)
1287 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1289 RMEXCL(bexcl,i-start,excl->a[k]);
1295 int calc_naaj(int icg,int cgtot)
1297 int naaj;
1299 if ((cgtot % 2) == 1)
1301 /* Odd number of charge groups, easy */
1302 naaj = 1 + (cgtot/2);
1304 else if ((cgtot % 4) == 0)
1306 /* Multiple of four is hard */
1307 if (icg < cgtot/2)
1309 if ((icg % 2) == 0)
1311 naaj=1+(cgtot/2);
1313 else
1315 naaj=cgtot/2;
1318 else
1320 if ((icg % 2) == 1)
1322 naaj=1+(cgtot/2);
1324 else
1326 naaj=cgtot/2;
1330 else
1332 /* cgtot/2 = odd */
1333 if ((icg % 2) == 0)
1335 naaj=1+(cgtot/2);
1337 else
1339 naaj=cgtot/2;
1342 #ifdef DEBUG
1343 fprintf(log,"naaj=%d\n",naaj);
1344 #endif
1346 return naaj;
1349 /************************************************
1351 * S I M P L E C O R E S T U F F
1353 ************************************************/
1355 static real calc_image_tric(rvec xi,rvec xj,matrix box,
1356 rvec b_inv,int *shift)
1358 /* This code assumes that the cut-off is smaller than
1359 * a half times the smallest diagonal element of the box.
1361 const real h25=2.5;
1362 real dx,dy,dz;
1363 real r2;
1364 int tx,ty,tz;
1366 /* Compute diff vector */
1367 dz = xj[ZZ] - xi[ZZ];
1368 dy = xj[YY] - xi[YY];
1369 dx = xj[XX] - xi[XX];
1371 /* Perform NINT operation, using trunc operation, therefore
1372 * we first add 2.5 then subtract 2 again
1374 tz = dz*b_inv[ZZ] + h25;
1375 tz -= 2;
1376 dz -= tz*box[ZZ][ZZ];
1377 dy -= tz*box[ZZ][YY];
1378 dx -= tz*box[ZZ][XX];
1380 ty = dy*b_inv[YY] + h25;
1381 ty -= 2;
1382 dy -= ty*box[YY][YY];
1383 dx -= ty*box[YY][XX];
1385 tx = dx*b_inv[XX]+h25;
1386 tx -= 2;
1387 dx -= tx*box[XX][XX];
1389 /* Distance squared */
1390 r2 = (dx*dx) + (dy*dy) + (dz*dz);
1392 *shift = XYZ2IS(tx,ty,tz);
1394 return r2;
1397 static real calc_image_rect(rvec xi,rvec xj,rvec box_size,
1398 rvec b_inv,int *shift)
1400 const real h15=1.5;
1401 real ddx,ddy,ddz;
1402 real dx,dy,dz;
1403 real r2;
1404 int tx,ty,tz;
1406 /* Compute diff vector */
1407 dx = xj[XX] - xi[XX];
1408 dy = xj[YY] - xi[YY];
1409 dz = xj[ZZ] - xi[ZZ];
1411 /* Perform NINT operation, using trunc operation, therefore
1412 * we first add 1.5 then subtract 1 again
1414 tx = dx*b_inv[XX] + h15;
1415 ty = dy*b_inv[YY] + h15;
1416 tz = dz*b_inv[ZZ] + h15;
1417 tx--;
1418 ty--;
1419 tz--;
1421 /* Correct diff vector for translation */
1422 ddx = tx*box_size[XX] - dx;
1423 ddy = ty*box_size[YY] - dy;
1424 ddz = tz*box_size[ZZ] - dz;
1426 /* Distance squared */
1427 r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
1429 *shift = XYZ2IS(tx,ty,tz);
1431 return r2;
1434 static void add_simple(t_ns_buf *nsbuf,int nrj,atom_id cg_j,
1435 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1436 int icg,int jgid,t_block *cgs,t_excl bexcl[],
1437 int shift,t_forcerec *fr,put_in_list_t *put_in_list)
1439 if (nsbuf->nj + nrj > MAX_CG)
1441 put_in_list(bHaveVdW,ngid,md,icg,jgid,nsbuf->ncg,nsbuf->jcg,
1442 cgs->index,bexcl,shift,fr,FALSE,TRUE,TRUE);
1443 /* Reset buffer contents */
1444 nsbuf->ncg = nsbuf->nj = 0;
1446 nsbuf->jcg[nsbuf->ncg++] = cg_j;
1447 nsbuf->nj += nrj;
1450 static void ns_inner_tric(rvec x[],int icg,int *i_egp_flags,
1451 int njcg,atom_id jcg[],
1452 matrix box,rvec b_inv,real rcut2,
1453 t_block *cgs,t_ns_buf **ns_buf,
1454 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1455 t_excl bexcl[],t_forcerec *fr,
1456 put_in_list_t *put_in_list)
1458 int shift;
1459 int j,nrj,jgid;
1460 int *cginfo=fr->cginfo;
1461 atom_id cg_j,*cgindex;
1462 t_ns_buf *nsbuf;
1464 cgindex = cgs->index;
1465 shift = CENTRAL;
1466 for(j=0; (j<njcg); j++)
1468 cg_j = jcg[j];
1469 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1470 if (calc_image_tric(x[icg],x[cg_j],box,b_inv,&shift) < rcut2)
1472 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1473 if (!(i_egp_flags[jgid] & EGP_EXCL))
1475 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1476 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
1477 put_in_list);
1483 static void ns_inner_rect(rvec x[],int icg,int *i_egp_flags,
1484 int njcg,atom_id jcg[],
1485 gmx_bool bBox,rvec box_size,rvec b_inv,real rcut2,
1486 t_block *cgs,t_ns_buf **ns_buf,
1487 gmx_bool bHaveVdW[],int ngid,t_mdatoms *md,
1488 t_excl bexcl[],t_forcerec *fr,
1489 put_in_list_t *put_in_list)
1491 int shift;
1492 int j,nrj,jgid;
1493 int *cginfo=fr->cginfo;
1494 atom_id cg_j,*cgindex;
1495 t_ns_buf *nsbuf;
1497 cgindex = cgs->index;
1498 if (bBox)
1500 shift = CENTRAL;
1501 for(j=0; (j<njcg); j++)
1503 cg_j = jcg[j];
1504 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1505 if (calc_image_rect(x[icg],x[cg_j],box_size,b_inv,&shift) < rcut2)
1507 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1508 if (!(i_egp_flags[jgid] & EGP_EXCL))
1510 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1511 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr,
1512 put_in_list);
1517 else
1519 for(j=0; (j<njcg); j++)
1521 cg_j = jcg[j];
1522 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1523 if ((rcut2 == 0) || (distance2(x[icg],x[cg_j]) < rcut2)) {
1524 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1525 if (!(i_egp_flags[jgid] & EGP_EXCL))
1527 add_simple(&ns_buf[jgid][CENTRAL],nrj,cg_j,
1528 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,CENTRAL,fr,
1529 put_in_list);
1536 /* ns_simple_core needs to be adapted for QMMM still 2005 */
1538 static int ns_simple_core(t_forcerec *fr,
1539 gmx_localtop_t *top,
1540 t_mdatoms *md,
1541 matrix box,rvec box_size,
1542 t_excl bexcl[],atom_id *aaj,
1543 int ngid,t_ns_buf **ns_buf,
1544 put_in_list_t *put_in_list,gmx_bool bHaveVdW[])
1546 int naaj,k;
1547 real rlist2;
1548 int nsearch,icg,jcg,igid,i0,nri,nn;
1549 int *cginfo;
1550 t_ns_buf *nsbuf;
1551 /* atom_id *i_atoms; */
1552 t_block *cgs=&(top->cgs);
1553 t_blocka *excl=&(top->excls);
1554 rvec b_inv;
1555 int m;
1556 gmx_bool bBox,bTriclinic;
1557 int *i_egp_flags;
1559 rlist2 = sqr(fr->rlist);
1561 bBox = (fr->ePBC != epbcNONE);
1562 if (bBox)
1564 for(m=0; (m<DIM); m++)
1566 b_inv[m] = divide_err(1.0,box_size[m]);
1568 bTriclinic = TRICLINIC(box);
1570 else
1572 bTriclinic = FALSE;
1575 cginfo = fr->cginfo;
1577 nsearch=0;
1578 for (icg=fr->cg0; (icg<fr->hcg); icg++)
1581 i0 = cgs->index[icg];
1582 nri = cgs->index[icg+1]-i0;
1583 i_atoms = &(cgs->a[i0]);
1584 i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
1585 setexcl(nri,i_atoms,excl,TRUE,bexcl);
1587 igid = GET_CGINFO_GID(cginfo[icg]);
1588 i_egp_flags = fr->egp_flags + ngid*igid;
1589 setexcl(cgs->index[icg],cgs->index[icg+1],excl,TRUE,bexcl);
1591 naaj=calc_naaj(icg,cgs->nr);
1592 if (bTriclinic)
1594 ns_inner_tric(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1595 box,b_inv,rlist2,cgs,ns_buf,
1596 bHaveVdW,ngid,md,bexcl,fr,put_in_list);
1598 else
1600 ns_inner_rect(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1601 bBox,box_size,b_inv,rlist2,cgs,ns_buf,
1602 bHaveVdW,ngid,md,bexcl,fr,put_in_list);
1604 nsearch += naaj;
1606 for(nn=0; (nn<ngid); nn++)
1608 for(k=0; (k<SHIFTS); k++)
1610 nsbuf = &(ns_buf[nn][k]);
1611 if (nsbuf->ncg > 0)
1613 put_in_list(bHaveVdW,ngid,md,icg,nn,nsbuf->ncg,nsbuf->jcg,
1614 cgs->index,bexcl,k,fr,FALSE,TRUE,TRUE);
1615 nsbuf->ncg=nsbuf->nj=0;
1619 /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
1620 setexcl(cgs->index[icg],cgs->index[icg+1],excl,FALSE,bexcl);
1622 close_neighbor_list(fr,FALSE,-1,-1,FALSE);
1624 return nsearch;
1627 /************************************************
1629 * N S 5 G R I D S T U F F
1631 ************************************************/
1633 static inline void get_dx(int Nx,real gridx,real rc2,int xgi,real x,
1634 int *dx0,int *dx1,real *dcx2)
1636 real dcx,tmp;
1637 int xgi0,xgi1,i;
1639 if (xgi < 0)
1641 *dx0 = 0;
1642 xgi0 = -1;
1643 *dx1 = -1;
1644 xgi1 = 0;
1646 else if (xgi >= Nx)
1648 *dx0 = Nx;
1649 xgi0 = Nx-1;
1650 *dx1 = Nx-1;
1651 xgi1 = Nx;
1653 else
1655 dcx2[xgi] = 0;
1656 *dx0 = xgi;
1657 xgi0 = xgi-1;
1658 *dx1 = xgi;
1659 xgi1 = xgi+1;
1662 for(i=xgi0; i>=0; i--)
1664 dcx = (i+1)*gridx-x;
1665 tmp = dcx*dcx;
1666 if (tmp >= rc2)
1667 break;
1668 *dx0 = i;
1669 dcx2[i] = tmp;
1671 for(i=xgi1; i<Nx; i++)
1673 dcx = i*gridx-x;
1674 tmp = dcx*dcx;
1675 if (tmp >= rc2)
1677 break;
1679 *dx1 = i;
1680 dcx2[i] = tmp;
1684 static inline void get_dx_dd(int Nx,real gridx,real rc2,int xgi,real x,
1685 int ncpddc,int shift_min,int shift_max,
1686 int *g0,int *g1,real *dcx2)
1688 real dcx,tmp;
1689 int g_min,g_max,shift_home;
1691 if (xgi < 0)
1693 g_min = 0;
1694 g_max = Nx - 1;
1695 *g0 = 0;
1696 *g1 = -1;
1698 else if (xgi >= Nx)
1700 g_min = 0;
1701 g_max = Nx - 1;
1702 *g0 = Nx;
1703 *g1 = Nx - 1;
1705 else
1707 if (ncpddc == 0)
1709 g_min = 0;
1710 g_max = Nx - 1;
1712 else
1714 if (xgi < ncpddc)
1716 shift_home = 0;
1718 else
1720 shift_home = -1;
1722 g_min = (shift_min == shift_home ? 0 : ncpddc);
1723 g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
1725 if (shift_min > 0)
1727 *g0 = g_min;
1728 *g1 = g_min - 1;
1730 else if (shift_max < 0)
1732 *g0 = g_max + 1;
1733 *g1 = g_max;
1735 else
1737 *g0 = xgi;
1738 *g1 = xgi;
1739 dcx2[xgi] = 0;
1743 while (*g0 > g_min)
1745 /* Check one grid cell down */
1746 dcx = ((*g0 - 1) + 1)*gridx - x;
1747 tmp = dcx*dcx;
1748 if (tmp >= rc2)
1750 break;
1752 (*g0)--;
1753 dcx2[*g0] = tmp;
1756 while (*g1 < g_max)
1758 /* Check one grid cell up */
1759 dcx = (*g1 + 1)*gridx - x;
1760 tmp = dcx*dcx;
1761 if (tmp >= rc2)
1763 break;
1765 (*g1)++;
1766 dcx2[*g1] = tmp;
1771 #define sqr(x) ((x)*(x))
1772 #define calc_dx2(XI,YI,ZI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]) + sqr(ZI-y[ZZ]))
1773 #define calc_cyl_dx2(XI,YI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]))
1774 /****************************************************
1776 * F A S T N E I G H B O R S E A R C H I N G
1778 * Optimized neighboursearching routine using grid
1779 * at least 1x1x1, see GROMACS manual
1781 ****************************************************/
1783 static void do_longrange(t_commrec *cr,gmx_localtop_t *top,t_forcerec *fr,
1784 int ngid,t_mdatoms *md,int icg,
1785 int jgid,int nlr,
1786 atom_id lr[],t_excl bexcl[],int shift,
1787 rvec x[],rvec box_size,t_nrnb *nrnb,
1788 real lambda,real *dvdlambda,
1789 gmx_grppairener_t *grppener,
1790 gmx_bool bDoVdW,gmx_bool bDoCoul,
1791 gmx_bool bEvaluateNow,put_in_list_t *put_in_list,
1792 gmx_bool bHaveVdW[],
1793 gmx_bool bDoForces,rvec *f)
1795 int n,i;
1796 t_nblist *nl;
1798 for(n=0; n<fr->nnblists; n++)
1800 for(i=0; (i<eNL_NR); i++)
1802 nl = &fr->nblists[n].nlist_lr[i];
1803 if ((nl->nri > nl->maxnri-32) || bEvaluateNow)
1805 close_neighbor_list(fr,TRUE,n,i,FALSE);
1806 /* Evaluate the energies and forces */
1807 do_nonbonded(cr,fr,x,f,md,NULL,
1808 grppener->ener[fr->bBHAM ? egBHAMLR : egLJLR],
1809 grppener->ener[egCOULLR],
1810 grppener->ener[egGB],box_size,
1811 nrnb,lambda,dvdlambda,n,i,
1812 GMX_DONB_LR | GMX_DONB_FORCES);
1814 reset_neighbor_list(fr,TRUE,n,i);
1819 if (!bEvaluateNow)
1821 /* Put the long range particles in a list */
1822 /* do_longrange is never called for QMMM */
1823 put_in_list(bHaveVdW,ngid,md,icg,jgid,nlr,lr,top->cgs.index,
1824 bexcl,shift,fr,TRUE,bDoVdW,bDoCoul);
1828 static void get_cutoff2(t_forcerec *fr,gmx_bool bDoLongRange,
1829 real *rvdw2,real *rcoul2,
1830 real *rs2,real *rm2,real *rl2)
1832 *rs2 = sqr(fr->rlist);
1833 if (bDoLongRange && fr->bTwinRange)
1835 /* The VdW and elec. LR cut-off's could be different,
1836 * so we can not simply set them to rlistlong.
1838 if (EVDW_MIGHT_BE_ZERO_AT_CUTOFF(fr->vdwtype) &&
1839 fr->rvdw > fr->rlist)
1841 *rvdw2 = sqr(fr->rlistlong);
1843 else
1845 *rvdw2 = sqr(fr->rvdw);
1847 if (EEL_MIGHT_BE_ZERO_AT_CUTOFF(fr->eeltype) &&
1848 fr->rcoulomb > fr->rlist)
1850 *rcoul2 = sqr(fr->rlistlong);
1852 else
1854 *rcoul2 = sqr(fr->rcoulomb);
1857 else
1859 /* Workaround for a gcc -O3 or -ffast-math problem */
1860 *rvdw2 = *rs2;
1861 *rcoul2 = *rs2;
1863 *rm2 = min(*rvdw2,*rcoul2);
1864 *rl2 = max(*rvdw2,*rcoul2);
1867 static void init_nsgrid_lists(t_forcerec *fr,int ngid,gmx_ns_t *ns)
1869 real rvdw2,rcoul2,rs2,rm2,rl2;
1870 int j;
1872 get_cutoff2(fr,TRUE,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
1874 /* Short range buffers */
1875 snew(ns->nl_sr,ngid);
1876 /* Counters */
1877 snew(ns->nsr,ngid);
1878 snew(ns->nlr_ljc,ngid);
1879 snew(ns->nlr_one,ngid);
1881 if (rm2 > rs2)
1883 /* Long range VdW and Coul buffers */
1884 snew(ns->nl_lr_ljc,ngid);
1886 if (rl2 > rm2)
1888 /* Long range VdW or Coul only buffers */
1889 snew(ns->nl_lr_one,ngid);
1891 for(j=0; (j<ngid); j++) {
1892 snew(ns->nl_sr[j],MAX_CG);
1893 if (rm2 > rs2)
1895 snew(ns->nl_lr_ljc[j],MAX_CG);
1897 if (rl2 > rm2)
1899 snew(ns->nl_lr_one[j],MAX_CG);
1902 if (debug)
1904 fprintf(debug,
1905 "ns5_core: rs2 = %g, rm2 = %g, rl2 = %g (nm^2)\n",
1906 rs2,rm2,rl2);
1910 static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
1911 matrix box,rvec box_size,int ngid,
1912 gmx_localtop_t *top,
1913 t_grid *grid,rvec x[],
1914 t_excl bexcl[],gmx_bool *bExcludeAlleg,
1915 t_nrnb *nrnb,t_mdatoms *md,
1916 real lambda,real *dvdlambda,
1917 gmx_grppairener_t *grppener,
1918 put_in_list_t *put_in_list,
1919 gmx_bool bHaveVdW[],
1920 gmx_bool bDoLongRange,gmx_bool bDoForces,rvec *f,
1921 gmx_bool bMakeQMMMnblist)
1923 gmx_ns_t *ns;
1924 atom_id **nl_lr_ljc,**nl_lr_one,**nl_sr;
1925 int *nlr_ljc,*nlr_one,*nsr;
1926 gmx_domdec_t *dd=NULL;
1927 t_block *cgs=&(top->cgs);
1928 int *cginfo=fr->cginfo;
1929 /* atom_id *i_atoms,*cgsindex=cgs->index; */
1930 ivec sh0,sh1,shp;
1931 int cell_x,cell_y,cell_z;
1932 int d,tx,ty,tz,dx,dy,dz,cj;
1933 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
1934 int zsh_ty,zsh_tx,ysh_tx;
1935 #endif
1936 int dx0,dx1,dy0,dy1,dz0,dz1;
1937 int Nx,Ny,Nz,shift=-1,j,nrj,nns,nn=-1;
1938 real gridx,gridy,gridz,grid_x,grid_y,grid_z;
1939 real *dcx2,*dcy2,*dcz2;
1940 int zgi,ygi,xgi;
1941 int cg0,cg1,icg=-1,cgsnr,i0,igid,nri,naaj,max_jcg;
1942 int jcg0,jcg1,jjcg,cgj0,jgid;
1943 int *grida,*gridnra,*gridind;
1944 gmx_bool rvdw_lt_rcoul,rcoul_lt_rvdw;
1945 rvec xi,*cgcm,grid_offset;
1946 real r2,rs2,rvdw2,rcoul2,rm2,rl2,XI,YI,ZI,dcx,dcy,dcz,tmp1,tmp2;
1947 int *i_egp_flags;
1948 gmx_bool bDomDec,bTriclinicX,bTriclinicY;
1949 ivec ncpddc;
1951 ns = &fr->ns;
1953 bDomDec = DOMAINDECOMP(cr);
1954 if (bDomDec)
1956 dd = cr->dd;
1959 bTriclinicX = ((YY < grid->npbcdim &&
1960 (!bDomDec || dd->nc[YY]==1) && box[YY][XX] != 0) ||
1961 (ZZ < grid->npbcdim &&
1962 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][XX] != 0));
1963 bTriclinicY = (ZZ < grid->npbcdim &&
1964 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][YY] != 0);
1966 cgsnr = cgs->nr;
1968 get_cutoff2(fr,bDoLongRange,&rvdw2,&rcoul2,&rs2,&rm2,&rl2);
1970 rvdw_lt_rcoul = (rvdw2 >= rcoul2);
1971 rcoul_lt_rvdw = (rcoul2 >= rvdw2);
1973 if (bMakeQMMMnblist)
1975 rm2 = rl2;
1976 rs2 = rl2;
1979 nl_sr = ns->nl_sr;
1980 nsr = ns->nsr;
1981 nl_lr_ljc = ns->nl_lr_ljc;
1982 nl_lr_one = ns->nl_lr_one;
1983 nlr_ljc = ns->nlr_ljc;
1984 nlr_one = ns->nlr_one;
1986 /* Unpack arrays */
1987 cgcm = fr->cg_cm;
1988 Nx = grid->n[XX];
1989 Ny = grid->n[YY];
1990 Nz = grid->n[ZZ];
1991 grida = grid->a;
1992 gridind = grid->index;
1993 gridnra = grid->nra;
1994 nns = 0;
1996 gridx = grid->cell_size[XX];
1997 gridy = grid->cell_size[YY];
1998 gridz = grid->cell_size[ZZ];
1999 grid_x = 1/gridx;
2000 grid_y = 1/gridy;
2001 grid_z = 1/gridz;
2002 copy_rvec(grid->cell_offset,grid_offset);
2003 copy_ivec(grid->ncpddc,ncpddc);
2004 dcx2 = grid->dcx2;
2005 dcy2 = grid->dcy2;
2006 dcz2 = grid->dcz2;
2008 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
2009 zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
2010 zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
2011 ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
2012 if (zsh_tx!=0 && ysh_tx!=0)
2014 /* This could happen due to rounding, when both ratios are 0.5 */
2015 ysh_tx = 0;
2017 #endif
2019 debug_gmx();
2021 if (fr->n_tpi)
2023 /* We only want a list for the test particle */
2024 cg0 = cgsnr - 1;
2026 else
2028 cg0 = grid->icg0;
2030 cg1 = grid->icg1;
2032 /* Set the shift range */
2033 for(d=0; d<DIM; d++)
2035 sh0[d] = -1;
2036 sh1[d] = 1;
2037 /* Check if we need periodicity shifts.
2038 * Without PBC or with domain decomposition we don't need them.
2040 if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
2042 shp[d] = 0;
2044 else
2046 if (d == XX &&
2047 box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
2049 shp[d] = 2;
2051 else
2053 shp[d] = 1;
2058 /* Loop over charge groups */
2059 for(icg=cg0; (icg < cg1); icg++)
2061 igid = GET_CGINFO_GID(cginfo[icg]);
2062 /* Skip this charge group if all energy groups are excluded! */
2063 if (bExcludeAlleg[igid])
2065 continue;
2068 i0 = cgs->index[icg];
2070 if (bMakeQMMMnblist)
2072 /* Skip this charge group if it is not a QM atom while making a
2073 * QM/MM neighbourlist
2075 if (md->bQM[i0]==FALSE)
2077 continue; /* MM particle, go to next particle */
2080 /* Compute the number of charge groups that fall within the control
2081 * of this one (icg)
2083 naaj = calc_naaj(icg,cgsnr);
2084 jcg0 = icg;
2085 jcg1 = icg + naaj;
2086 max_jcg = cgsnr;
2088 else
2090 /* make a normal neighbourlist */
2092 if (bDomDec)
2094 /* Get the j charge-group and dd cell shift ranges */
2095 dd_get_ns_ranges(cr->dd,icg,&jcg0,&jcg1,sh0,sh1);
2096 max_jcg = 0;
2098 else
2100 /* Compute the number of charge groups that fall within the control
2101 * of this one (icg)
2103 naaj = calc_naaj(icg,cgsnr);
2104 jcg0 = icg;
2105 jcg1 = icg + naaj;
2107 if (fr->n_tpi)
2109 /* The i-particle is awlways the test particle,
2110 * so we want all j-particles
2112 max_jcg = cgsnr - 1;
2114 else
2116 max_jcg = jcg1 - cgsnr;
2121 i_egp_flags = fr->egp_flags + igid*ngid;
2123 /* Set the exclusions for the atoms in charge group icg using a bitmask */
2124 setexcl(i0,cgs->index[icg+1],&top->excls,TRUE,bexcl);
2126 ci2xyz(grid,icg,&cell_x,&cell_y,&cell_z);
2128 /* Changed iicg to icg, DvdS 990115
2129 * (but see consistency check above, DvdS 990330)
2131 #ifdef NS5DB
2132 fprintf(log,"icg=%5d, naaj=%5d, cell %d %d %d\n",
2133 icg,naaj,cell_x,cell_y,cell_z);
2134 #endif
2135 /* Loop over shift vectors in three dimensions */
2136 for (tz=-shp[ZZ]; tz<=shp[ZZ]; tz++)
2138 ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
2139 /* Calculate range of cells in Z direction that have the shift tz */
2140 zgi = cell_z + tz*Nz;
2141 #define FAST_DD_NS
2142 #ifndef FAST_DD_NS
2143 get_dx(Nz,gridz,rl2,zgi,ZI,&dz0,&dz1,dcz2);
2144 #else
2145 get_dx_dd(Nz,gridz,rl2,zgi,ZI-grid_offset[ZZ],
2146 ncpddc[ZZ],sh0[ZZ],sh1[ZZ],&dz0,&dz1,dcz2);
2147 #endif
2148 if (dz0 > dz1)
2150 continue;
2152 for (ty=-shp[YY]; ty<=shp[YY]; ty++)
2154 YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
2155 /* Calculate range of cells in Y direction that have the shift ty */
2156 if (bTriclinicY)
2158 ygi = (int)(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
2160 else
2162 ygi = cell_y + ty*Ny;
2164 #ifndef FAST_DD_NS
2165 get_dx(Ny,gridy,rl2,ygi,YI,&dy0,&dy1,dcy2);
2166 #else
2167 get_dx_dd(Ny,gridy,rl2,ygi,YI-grid_offset[YY],
2168 ncpddc[YY],sh0[YY],sh1[YY],&dy0,&dy1,dcy2);
2169 #endif
2170 if (dy0 > dy1)
2172 continue;
2174 for (tx=-shp[XX]; tx<=shp[XX]; tx++)
2176 XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
2177 /* Calculate range of cells in X direction that have the shift tx */
2178 if (bTriclinicX)
2180 xgi = (int)(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
2182 else
2184 xgi = cell_x + tx*Nx;
2186 #ifndef FAST_DD_NS
2187 get_dx(Nx,gridx,rl2,xgi*Nx,XI,&dx0,&dx1,dcx2);
2188 #else
2189 get_dx_dd(Nx,gridx,rl2,xgi,XI-grid_offset[XX],
2190 ncpddc[XX],sh0[XX],sh1[XX],&dx0,&dx1,dcx2);
2191 #endif
2192 if (dx0 > dx1)
2194 continue;
2196 /* Adress: an explicit cg that has a weigthing function of 0 is excluded
2197 * from the neigbour list as it will not interact */
2198 if (fr->adress_type != eAdressOff){
2199 if (md->wf[cgs->index[icg]]==0 && egp_explicit(fr, igid)){
2200 continue;
2203 /* Get shift vector */
2204 shift=XYZ2IS(tx,ty,tz);
2205 #ifdef NS5DB
2206 range_check(shift,0,SHIFTS);
2207 #endif
2208 for(nn=0; (nn<ngid); nn++)
2210 nsr[nn] = 0;
2211 nlr_ljc[nn] = 0;
2212 nlr_one[nn] = 0;
2214 #ifdef NS5DB
2215 fprintf(log,"shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
2216 shift,dx0,dx1,dy0,dy1,dz0,dz1);
2217 fprintf(log,"cgcm: %8.3f %8.3f %8.3f\n",cgcm[icg][XX],
2218 cgcm[icg][YY],cgcm[icg][ZZ]);
2219 fprintf(log,"xi: %8.3f %8.3f %8.3f\n",XI,YI,ZI);
2220 #endif
2221 for (dx=dx0; (dx<=dx1); dx++)
2223 tmp1 = rl2 - dcx2[dx];
2224 for (dy=dy0; (dy<=dy1); dy++)
2226 tmp2 = tmp1 - dcy2[dy];
2227 if (tmp2 > 0)
2229 for (dz=dz0; (dz<=dz1); dz++) {
2230 if (tmp2 > dcz2[dz]) {
2231 /* Find grid-cell cj in which possible neighbours are */
2232 cj = xyz2ci(Ny,Nz,dx,dy,dz);
2234 /* Check out how many cgs (nrj) there in this cell */
2235 nrj = gridnra[cj];
2237 /* Find the offset in the cg list */
2238 cgj0 = gridind[cj];
2240 /* Check if all j's are out of range so we
2241 * can skip the whole cell.
2242 * Should save some time, especially with DD.
2244 if (nrj == 0 ||
2245 (grida[cgj0] >= max_jcg &&
2246 (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
2248 continue;
2251 /* Loop over cgs */
2252 for (j=0; (j<nrj); j++)
2254 jjcg = grida[cgj0+j];
2256 /* check whether this guy is in range! */
2257 if ((jjcg >= jcg0 && jjcg < jcg1) ||
2258 (jjcg < max_jcg))
2260 r2=calc_dx2(XI,YI,ZI,cgcm[jjcg]);
2261 if (r2 < rl2) {
2262 /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
2263 jgid = GET_CGINFO_GID(cginfo[jjcg]);
2264 /* check energy group exclusions */
2265 if (!(i_egp_flags[jgid] & EGP_EXCL))
2267 if (r2 < rs2)
2269 if (nsr[jgid] >= MAX_CG)
2271 put_in_list(bHaveVdW,ngid,md,icg,jgid,
2272 nsr[jgid],nl_sr[jgid],
2273 cgs->index,/* cgsatoms, */ bexcl,
2274 shift,fr,FALSE,TRUE,TRUE);
2275 nsr[jgid]=0;
2277 nl_sr[jgid][nsr[jgid]++]=jjcg;
2279 else if (r2 < rm2)
2281 if (nlr_ljc[jgid] >= MAX_CG)
2283 do_longrange(cr,top,fr,ngid,md,icg,jgid,
2284 nlr_ljc[jgid],
2285 nl_lr_ljc[jgid],bexcl,shift,x,
2286 box_size,nrnb,
2287 lambda,dvdlambda,
2288 grppener,
2289 TRUE,TRUE,FALSE,
2290 put_in_list,
2291 bHaveVdW,
2292 bDoForces,f);
2293 nlr_ljc[jgid]=0;
2295 nl_lr_ljc[jgid][nlr_ljc[jgid]++]=jjcg;
2297 else
2299 if (nlr_one[jgid] >= MAX_CG) {
2300 do_longrange(cr,top,fr,ngid,md,icg,jgid,
2301 nlr_one[jgid],
2302 nl_lr_one[jgid],bexcl,shift,x,
2303 box_size,nrnb,
2304 lambda,dvdlambda,
2305 grppener,
2306 rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
2307 put_in_list,
2308 bHaveVdW,
2309 bDoForces,f);
2310 nlr_one[jgid]=0;
2312 nl_lr_one[jgid][nlr_one[jgid]++]=jjcg;
2316 nns++;
2324 /* CHECK whether there is anything left in the buffers */
2325 for(nn=0; (nn<ngid); nn++)
2327 if (nsr[nn] > 0)
2329 put_in_list(bHaveVdW,ngid,md,icg,nn,nsr[nn],nl_sr[nn],
2330 cgs->index, /* cgsatoms, */ bexcl,
2331 shift,fr,FALSE,TRUE,TRUE);
2334 if (nlr_ljc[nn] > 0)
2336 do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_ljc[nn],
2337 nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
2338 lambda,dvdlambda,grppener,TRUE,TRUE,FALSE,
2339 put_in_list,bHaveVdW,bDoForces,f);
2342 if (nlr_one[nn] > 0)
2344 do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_one[nn],
2345 nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
2346 lambda,dvdlambda,grppener,
2347 rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
2348 put_in_list,bHaveVdW,bDoForces,f);
2354 /* setexcl(nri,i_atoms,&top->atoms.excl,FALSE,bexcl); */
2355 setexcl(cgs->index[icg],cgs->index[icg+1],&top->excls,FALSE,bexcl);
2357 /* Perform any left over force calculations */
2358 for (nn=0; (nn<ngid); nn++)
2360 if (rm2 > rs2)
2362 do_longrange(cr,top,fr,0,md,icg,nn,nlr_ljc[nn],
2363 nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
2364 lambda,dvdlambda,grppener,
2365 TRUE,TRUE,TRUE,put_in_list,bHaveVdW,bDoForces,f);
2367 if (rl2 > rm2) {
2368 do_longrange(cr,top,fr,0,md,icg,nn,nlr_one[nn],
2369 nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
2370 lambda,dvdlambda,grppener,
2371 rvdw_lt_rcoul,rcoul_lt_rvdw,
2372 TRUE,put_in_list,bHaveVdW,bDoForces,f);
2375 debug_gmx();
2377 /* Close off short range neighbourlists */
2378 close_neighbor_list(fr,FALSE,-1,-1,bMakeQMMMnblist);
2380 return nns;
2383 void ns_realloc_natoms(gmx_ns_t *ns,int natoms)
2385 int i;
2387 if (natoms > ns->nra_alloc)
2389 ns->nra_alloc = over_alloc_dd(natoms);
2390 srenew(ns->bexcl,ns->nra_alloc);
2391 for(i=0; i<ns->nra_alloc; i++)
2393 ns->bexcl[i] = 0;
2398 void init_ns(FILE *fplog,const t_commrec *cr,
2399 gmx_ns_t *ns,t_forcerec *fr,
2400 const gmx_mtop_t *mtop,
2401 matrix box)
2403 int mt,icg,nr_in_cg,maxcg,i,j,jcg,ngid,ncg;
2404 t_block *cgs;
2405 char *ptr;
2407 /* Compute largest charge groups size (# atoms) */
2408 nr_in_cg=1;
2409 for(mt=0; mt<mtop->nmoltype; mt++) {
2410 cgs = &mtop->moltype[mt].cgs;
2411 for (icg=0; (icg < cgs->nr); icg++)
2413 nr_in_cg=max(nr_in_cg,(int)(cgs->index[icg+1]-cgs->index[icg]));
2417 /* Verify whether largest charge group is <= max cg.
2418 * This is determined by the type of the local exclusion type
2419 * Exclusions are stored in bits. (If the type is not large
2420 * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
2422 maxcg = sizeof(t_excl)*8;
2423 if (nr_in_cg > maxcg)
2425 gmx_fatal(FARGS,"Max #atoms in a charge group: %d > %d\n",
2426 nr_in_cg,maxcg);
2429 ngid = mtop->groups.grps[egcENER].nr;
2430 snew(ns->bExcludeAlleg,ngid);
2431 for(i=0; i<ngid; i++) {
2432 ns->bExcludeAlleg[i] = TRUE;
2433 for(j=0; j<ngid; j++)
2435 if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
2437 ns->bExcludeAlleg[i] = FALSE;
2442 if (fr->bGrid) {
2443 /* Grid search */
2444 ns->grid = init_grid(fplog,fr);
2445 init_nsgrid_lists(fr,ngid,ns);
2447 else
2449 /* Simple search */
2450 snew(ns->ns_buf,ngid);
2451 for(i=0; (i<ngid); i++)
2453 snew(ns->ns_buf[i],SHIFTS);
2455 ncg = ncg_mtop(mtop);
2456 snew(ns->simple_aaj,2*ncg);
2457 for(jcg=0; (jcg<ncg); jcg++)
2459 ns->simple_aaj[jcg] = jcg;
2460 ns->simple_aaj[jcg+ncg] = jcg;
2464 /* Create array that determines whether or not atoms have VdW */
2465 snew(ns->bHaveVdW,fr->ntype);
2466 for(i=0; (i<fr->ntype); i++)
2468 for(j=0; (j<fr->ntype); j++)
2470 ns->bHaveVdW[i] = (ns->bHaveVdW[i] ||
2471 (fr->bBHAM ?
2472 ((BHAMA(fr->nbfp,fr->ntype,i,j) != 0) ||
2473 (BHAMB(fr->nbfp,fr->ntype,i,j) != 0) ||
2474 (BHAMC(fr->nbfp,fr->ntype,i,j) != 0)) :
2475 ((C6(fr->nbfp,fr->ntype,i,j) != 0) ||
2476 (C12(fr->nbfp,fr->ntype,i,j) != 0))));
2479 if (debug)
2480 pr_bvec(debug,0,"bHaveVdW",ns->bHaveVdW,fr->ntype,TRUE);
2482 ns->nra_alloc = 0;
2483 ns->bexcl = NULL;
2484 if (!DOMAINDECOMP(cr))
2486 /* This could be reduced with particle decomposition */
2487 ns_realloc_natoms(ns,mtop->natoms);
2490 ns->nblist_initialized=FALSE;
2492 /* nbr list debug dump */
2494 char *ptr=getenv("GMX_DUMP_NL");
2495 if (ptr)
2497 ns->dump_nl=strtol(ptr,NULL,10);
2498 if (fplog)
2500 fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
2503 else
2505 ns->dump_nl=0;
2511 int search_neighbours(FILE *log,t_forcerec *fr,
2512 rvec x[],matrix box,
2513 gmx_localtop_t *top,
2514 gmx_groups_t *groups,
2515 t_commrec *cr,
2516 t_nrnb *nrnb,t_mdatoms *md,
2517 real lambda,real *dvdlambda,
2518 gmx_grppairener_t *grppener,
2519 gmx_bool bFillGrid,
2520 gmx_bool bDoLongRange,
2521 gmx_bool bDoForces,rvec *f)
2523 t_block *cgs=&(top->cgs);
2524 rvec box_size,grid_x0,grid_x1;
2525 int i,j,m,ngid;
2526 real min_size,grid_dens;
2527 int nsearch;
2528 gmx_bool bGrid;
2529 char *ptr;
2530 gmx_bool *i_egp_flags;
2531 int cg_start,cg_end,start,end;
2532 gmx_ns_t *ns;
2533 t_grid *grid;
2534 gmx_domdec_zones_t *dd_zones;
2535 put_in_list_t *put_in_list;
2537 ns = &fr->ns;
2539 /* Set some local variables */
2540 bGrid = fr->bGrid;
2541 ngid = groups->grps[egcENER].nr;
2543 for(m=0; (m<DIM); m++)
2545 box_size[m] = box[m][m];
2548 if (fr->ePBC != epbcNONE)
2550 if (sqr(fr->rlistlong) >= max_cutoff2(fr->ePBC,box))
2552 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.");
2554 if (!bGrid)
2556 min_size = min(box_size[XX],min(box_size[YY],box_size[ZZ]));
2557 if (2*fr->rlistlong >= min_size)
2558 gmx_fatal(FARGS,"One of the box diagonal elements has become smaller than twice the cut-off length.");
2562 if (DOMAINDECOMP(cr))
2564 ns_realloc_natoms(ns,cgs->index[cgs->nr]);
2566 debug_gmx();
2568 /* Reset the neighbourlists */
2569 reset_neighbor_list(fr,FALSE,-1,-1);
2571 if (bGrid && bFillGrid)
2574 grid = ns->grid;
2575 if (DOMAINDECOMP(cr))
2577 dd_zones = domdec_zones(cr->dd);
2579 else
2581 dd_zones = NULL;
2583 get_nsgrid_boundaries(grid,NULL,box,NULL,NULL,NULL,
2584 cgs->nr,fr->cg_cm,grid_x0,grid_x1,&grid_dens);
2586 grid_first(log,grid,NULL,NULL,fr->ePBC,box,grid_x0,grid_x1,
2587 fr->rlistlong,grid_dens);
2589 debug_gmx();
2591 /* Don't know why this all is... (DvdS 3/99) */
2592 #ifndef SEGV
2593 start = 0;
2594 end = cgs->nr;
2595 #else
2596 start = fr->cg0;
2597 end = (cgs->nr+1)/2;
2598 #endif
2600 if (DOMAINDECOMP(cr))
2602 end = cgs->nr;
2603 fill_grid(log,dd_zones,grid,end,-1,end,fr->cg_cm);
2604 grid->icg0 = 0;
2605 grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
2607 else
2609 fill_grid(log,NULL,grid,cgs->nr,fr->cg0,fr->hcg,fr->cg_cm);
2610 grid->icg0 = fr->cg0;
2611 grid->icg1 = fr->hcg;
2612 debug_gmx();
2614 if (PARTDECOMP(cr))
2615 mv_grid(cr,grid);
2616 debug_gmx();
2619 calc_elemnr(log,grid,start,end,cgs->nr);
2620 calc_ptrs(grid);
2621 grid_last(log,grid,start,end,cgs->nr);
2623 if (gmx_debug_at)
2625 check_grid(debug,grid);
2626 print_grid(debug,grid);
2629 else if (fr->n_tpi)
2631 /* Set the grid cell index for the test particle only.
2632 * The cell to cg index is not corrected, but that does not matter.
2634 fill_grid(log,NULL,ns->grid,fr->hcg,fr->hcg-1,fr->hcg,fr->cg_cm);
2636 debug_gmx();
2638 if (!fr->ns.bCGlist)
2640 put_in_list = put_in_list_at;
2642 else
2644 put_in_list = put_in_list_cg;
2647 /* Do the core! */
2648 if (bGrid)
2650 grid = ns->grid;
2651 nsearch = nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2652 grid,x,ns->bexcl,ns->bExcludeAlleg,
2653 nrnb,md,lambda,dvdlambda,grppener,
2654 put_in_list,ns->bHaveVdW,
2655 bDoLongRange,bDoForces,f,
2656 FALSE);
2658 /* neighbour searching withouth QMMM! QM atoms have zero charge in
2659 * the classical calculation. The charge-charge interaction
2660 * between QM and MM atoms is handled in the QMMM core calculation
2661 * (see QMMM.c). The VDW however, we'd like to compute classically
2662 * and the QM MM atom pairs have just been put in the
2663 * corresponding neighbourlists. in case of QMMM we still need to
2664 * fill a special QMMM neighbourlist that contains all neighbours
2665 * of the QM atoms. If bQMMM is true, this list will now be made:
2667 if (fr->bQMMM && fr->qr->QMMMscheme!=eQMMMschemeoniom)
2669 nsearch += nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2670 grid,x,ns->bexcl,ns->bExcludeAlleg,
2671 nrnb,md,lambda,dvdlambda,grppener,
2672 put_in_list_qmmm,ns->bHaveVdW,
2673 bDoLongRange,bDoForces,f,
2674 TRUE);
2677 else
2679 nsearch = ns_simple_core(fr,top,md,box,box_size,
2680 ns->bexcl,ns->simple_aaj,
2681 ngid,ns->ns_buf,put_in_list,ns->bHaveVdW);
2683 debug_gmx();
2685 #ifdef DEBUG
2686 pr_nsblock(log);
2687 #endif
2689 inc_nrnb(nrnb,eNR_NS,nsearch);
2690 /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
2692 return nsearch;
2695 int natoms_beyond_ns_buffer(t_inputrec *ir,t_forcerec *fr,t_block *cgs,
2696 matrix scale_tot,rvec *x)
2698 int cg0,cg1,cg,a0,a1,a,i,j;
2699 real rint,hbuf2,scale;
2700 rvec *cg_cm,cgsc;
2701 gmx_bool bIsotropic;
2702 int nBeyond;
2704 nBeyond = 0;
2706 rint = max(ir->rcoulomb,ir->rvdw);
2707 if (ir->rlist < rint)
2709 gmx_fatal(FARGS,"The neighbor search buffer has negative size: %f nm",
2710 ir->rlist - rint);
2712 cg_cm = fr->cg_cm;
2714 cg0 = fr->cg0;
2715 cg1 = fr->hcg;
2717 if (!EI_DYNAMICS(ir->eI) || !DYNAMIC_BOX(*ir))
2719 hbuf2 = sqr(0.5*(ir->rlist - rint));
2720 for(cg=cg0; cg<cg1; cg++)
2722 a0 = cgs->index[cg];
2723 a1 = cgs->index[cg+1];
2724 for(a=a0; a<a1; a++)
2726 if (distance2(cg_cm[cg],x[a]) > hbuf2)
2728 nBeyond++;
2733 else
2735 bIsotropic = TRUE;
2736 scale = scale_tot[0][0];
2737 for(i=1; i<DIM; i++)
2739 /* With anisotropic scaling, the original spherical ns volumes become
2740 * ellipsoids. To avoid costly transformations we use the minimum
2741 * eigenvalue of the scaling matrix for determining the buffer size.
2742 * Since the lower half is 0, the eigenvalues are the diagonal elements.
2744 scale = min(scale,scale_tot[i][i]);
2745 if (scale_tot[i][i] != scale_tot[i-1][i-1])
2747 bIsotropic = FALSE;
2749 for(j=0; j<i; j++)
2751 if (scale_tot[i][j] != 0)
2753 bIsotropic = FALSE;
2757 hbuf2 = sqr(0.5*(scale*ir->rlist - rint));
2758 if (bIsotropic)
2760 for(cg=cg0; cg<cg1; cg++)
2762 svmul(scale,cg_cm[cg],cgsc);
2763 a0 = cgs->index[cg];
2764 a1 = cgs->index[cg+1];
2765 for(a=a0; a<a1; a++)
2767 if (distance2(cgsc,x[a]) > hbuf2)
2769 nBeyond++;
2774 else
2776 /* Anistropic scaling */
2777 for(cg=cg0; cg<cg1; cg++)
2779 /* Since scale_tot contains the transpose of the scaling matrix,
2780 * we need to multiply with the transpose.
2782 tmvmul_ur0(scale_tot,cg_cm[cg],cgsc);
2783 a0 = cgs->index[cg];
2784 a1 = cgs->index[cg+1];
2785 for(a=a0; a<a1; a++)
2787 if (distance2(cgsc,x[a]) > hbuf2)
2789 nBeyond++;
2796 return nBeyond;