Initial all-vs-all kernels. Single precision SSE working.
[gromacs.git] / src / mdlib / ns.c
blobfce5b41cd62362eac8c7fb03bcced07493dc0f7e
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"
66 /* Uncomment the define below to use the generic charge group - charge group
67 * inner loops (in src/gmxlib/nonbonded/nb_generic_cg.c).
68 * All intra charge-group interaction should be excluded.
69 * There should be no inter charge group exclusions.
70 * There can be no perturbed LJ types or charges.
71 * mdrun currently does NOT check for this.
73 /* #define GMX_CG_INNERLOOP */
76 /*
77 * E X C L U S I O N H A N D L I N G
80 #ifdef DEBUG
81 static void SETEXCL_(t_excl e[],atom_id i,atom_id j)
82 { e[j] = e[j] | (1<<i); }
83 static void RMEXCL_(t_excl e[],atom_id i,atom_id j)
84 { e[j]=e[j] & ~(1<<i); }
85 static bool ISEXCL_(t_excl e[],atom_id i,atom_id j)
86 { return (bool)(e[j] & (1<<i)); }
87 static bool NOTEXCL_(t_excl e[],atom_id i,atom_id j)
88 { return !(ISEXCL(e,i,j)); }
89 #else
90 #define SETEXCL(e,i,j) (e)[((atom_id) (j))] |= (1<<((atom_id) (i)))
91 #define RMEXCL(e,i,j) (e)[((atom_id) (j))] &= (~(1<<((atom_id) (i))))
92 #define ISEXCL(e,i,j) (bool) ((e)[((atom_id) (j))] & (1<<((atom_id) (i))))
93 #define NOTEXCL(e,i,j) !(ISEXCL(e,i,j))
94 #endif
96 /************************************************
98 * U T I L I T I E S F O R N S
100 ************************************************/
102 static void reallocate_nblist(t_nblist *nl)
104 if (gmx_debug_at)
106 fprintf(debug,"reallocating neigborlist il_code=%d, maxnri=%d\n",
107 nl->il_code,nl->maxnri);
109 srenew(nl->iinr, nl->maxnri);
110 if (nl->enlist == enlistCG_CG)
112 srenew(nl->iinr_end,nl->maxnri);
114 srenew(nl->gid, nl->maxnri);
115 srenew(nl->shift, nl->maxnri);
116 srenew(nl->jindex, nl->maxnri+1);
119 /* ivdw/icoul are used to determine the type of interaction, so we
120 * can set an innerloop index here. The obvious choice for this would have
121 * been the vdwtype/coultype values in the forcerecord, but unfortunately
122 * those types are braindead - for instance both Buckingham and normal
123 * Lennard-Jones use the same value (evdwCUT), and a separate boolean variable
124 * to determine which interaction is used. There is further no special value
125 * for 'no interaction'. For backward compatibility with old TPR files we won't
126 * change this in the 3.x series, so when calling this routine you should use:
128 * icoul=0 no coulomb interaction
129 * icoul=1 cutoff standard coulomb
130 * icoul=2 reaction-field coulomb
131 * icoul=3 tabulated coulomb
133 * ivdw=0 no vdw interaction
134 * ivdw=1 standard L-J interaction
135 * ivdw=2 Buckingham
136 * ivdw=3 tabulated vdw.
138 * Kind of ugly, but it works.
140 static void init_nblist(t_nblist *nl_sr,t_nblist *nl_lr,
141 int maxsr,int maxlr,
142 int ivdw, int icoul,
143 bool bfree, int enlist)
145 t_nblist *nl;
146 int homenr;
147 int i,nn;
149 int inloop[20] =
151 eNR_NBKERNEL_NONE,
152 eNR_NBKERNEL010,
153 eNR_NBKERNEL020,
154 eNR_NBKERNEL030,
155 eNR_NBKERNEL100,
156 eNR_NBKERNEL110,
157 eNR_NBKERNEL120,
158 eNR_NBKERNEL130,
159 eNR_NBKERNEL200,
160 eNR_NBKERNEL210,
161 eNR_NBKERNEL220,
162 eNR_NBKERNEL230,
163 eNR_NBKERNEL300,
164 eNR_NBKERNEL310,
165 eNR_NBKERNEL320,
166 eNR_NBKERNEL330,
167 eNR_NBKERNEL400,
168 eNR_NBKERNEL410,
169 eNR_NBKERNEL_NONE,
170 eNR_NBKERNEL430
173 for(i=0; (i<2); i++)
175 nl = (i == 0) ? nl_sr : nl_lr;
176 homenr = (i == 0) ? maxsr : maxlr;
178 /* Set coul/vdw in neighborlist, and for the normal loops we determine
179 * an index of which one to call.
181 nl->ivdw = ivdw;
182 nl->icoul = icoul;
183 nl->free_energy = bfree;
185 if (bfree)
187 nl->enlist = enlistATOM_ATOM;
188 nl->il_code = eNR_NBKERNEL_FREE_ENERGY;
190 else
192 nl->enlist = enlist;
194 nn = inloop[4*icoul + ivdw];
196 /* solvent loops follow directly after the corresponding
197 * ordinary loops, in the order:
199 * SPC, SPC-SPC, TIP4p, TIP4p-TIP4p
202 switch (enlist) {
203 case enlistATOM_ATOM:
204 #ifdef GMX_CG_INNERLOOP
205 nl->enlist = enlistCG_CG;
206 #endif
207 break;
208 case enlistSPC_ATOM: nn += 1; break;
209 case enlistSPC_SPC: nn += 2; break;
210 case enlistTIP4P_ATOM: nn += 3; break;
211 case enlistTIP4P_TIP4P: nn += 4; break;
214 nl->il_code = nn;
217 if (debug)
218 fprintf(debug,"Initiating neighbourlist type %d for %s interactions,\nwith %d SR, %d LR atoms.\n",
219 nl->il_code,ENLISTTYPE(enlist),maxsr,maxlr);
221 /* maxnri is influenced by the number of shifts (maximum is 8)
222 * and the number of energy groups.
223 * If it is not enough, nl memory will be reallocated during the run.
224 * 4 seems to be a reasonable factor, which only causes reallocation
225 * during runs with tiny and many energygroups.
227 nl->maxnri = homenr*4;
228 nl->maxnrj = 0;
229 nl->maxlen = 0;
230 nl->nri = -1;
231 nl->nrj = 0;
232 nl->iinr = NULL;
233 nl->gid = NULL;
234 nl->shift = NULL;
235 nl->jindex = NULL;
236 reallocate_nblist(nl);
237 nl->jindex[0] = 0;
238 #ifdef GMX_THREAD_SHM_FDECOMP
239 nl->counter = 0;
240 snew(nl->mtx,1);
241 pthread_mutex_init(nl->mtx,NULL);
242 #endif
246 void init_neighbor_list(FILE *log,t_forcerec *fr,int homenr)
248 /* Make maxlr tunable! (does not seem to be a big difference though)
249 * This parameter determines the number of i particles in a long range
250 * neighbourlist. Too few means many function calls, too many means
251 * cache trashing.
253 int maxsr,maxsr_wat,maxlr,maxlr_wat;
254 int icoul,icoulf,ivdw;
255 int solvent;
256 int enlist_w,enlist_ww;
257 int i;
258 t_nblists *nbl;
260 /* maxsr = homenr-fr->nWatMol*3; */
261 maxsr = homenr;
263 if (maxsr < 0)
265 gmx_fatal(FARGS,"%s, %d: Negative number of short range atoms.\n"
266 "Call your Gromacs dealer for assistance.",__FILE__,__LINE__);
268 /* This is just for initial allocation, so we do not reallocate
269 * all the nlist arrays many times in a row.
270 * The numbers seem very accurate, but they are uncritical.
272 maxsr_wat = min(fr->nWatMol,(homenr+2)/3);
273 if (fr->bTwinRange)
275 maxlr = 50;
276 maxlr_wat = min(maxsr_wat,maxlr);
278 else
280 maxlr = maxlr_wat = 0;
283 /* Determine the values for icoul/ivdw. */
284 /* Start with GB */
285 if(fr->bGB)
287 icoul=4;
289 else if (fr->bcoultab)
291 icoul = 3;
293 else if (EEL_RF(fr->eeltype))
295 icoul = 2;
297 else
299 icoul = 1;
302 if (fr->bvdwtab)
304 ivdw = 3;
306 else if (fr->bBHAM)
308 ivdw = 2;
310 else
312 ivdw = 1;
315 if (fr->solvent_opt == esolTIP4P) {
316 enlist_w = enlistTIP4P_ATOM;
317 enlist_ww = enlistTIP4P_TIP4P;
318 } else {
319 enlist_w = enlistSPC_ATOM;
320 enlist_ww = enlistSPC_SPC;
323 for(i=0; i<fr->nnblists; i++)
325 nbl = &(fr->nblists[i]);
326 init_nblist(&nbl->nlist_sr[eNL_VDWQQ],&nbl->nlist_lr[eNL_VDWQQ],
327 maxsr,maxlr,ivdw,icoul,FALSE,enlistATOM_ATOM);
328 init_nblist(&nbl->nlist_sr[eNL_VDW],&nbl->nlist_lr[eNL_VDW],
329 maxsr,maxlr,ivdw,0,FALSE,enlistATOM_ATOM);
330 init_nblist(&nbl->nlist_sr[eNL_QQ],&nbl->nlist_lr[eNL_QQ],
331 maxsr,maxlr,0,icoul,FALSE,enlistATOM_ATOM);
332 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATER],&nbl->nlist_lr[eNL_VDWQQ_WATER],
333 maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_w);
334 init_nblist(&nbl->nlist_sr[eNL_QQ_WATER],&nbl->nlist_lr[eNL_QQ_WATER],
335 maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_w);
336 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_WATERWATER],&nbl->nlist_lr[eNL_VDWQQ_WATERWATER],
337 maxsr_wat,maxlr_wat,ivdw,icoul, FALSE,enlist_ww);
338 init_nblist(&nbl->nlist_sr[eNL_QQ_WATERWATER],&nbl->nlist_lr[eNL_QQ_WATERWATER],
339 maxsr_wat,maxlr_wat,0,icoul, FALSE,enlist_ww);
341 if (fr->efep != efepNO)
343 if (fr->bEwald)
345 icoulf = 5;
347 else
349 icoulf = icoul;
352 init_nblist(&nbl->nlist_sr[eNL_VDWQQ_FREE],&nbl->nlist_lr[eNL_VDWQQ_FREE],
353 maxsr,maxlr,ivdw,icoulf,TRUE,enlistATOM_ATOM);
354 init_nblist(&nbl->nlist_sr[eNL_VDW_FREE],&nbl->nlist_lr[eNL_VDW_FREE],
355 maxsr,maxlr,ivdw,0,TRUE,enlistATOM_ATOM);
356 init_nblist(&nbl->nlist_sr[eNL_QQ_FREE],&nbl->nlist_lr[eNL_QQ_FREE],
357 maxsr,maxlr,0,icoulf,TRUE,enlistATOM_ATOM);
360 /* QMMM MM list */
361 if (fr->bQMMM && fr->qr->QMMMscheme != eQMMMschemeoniom)
363 init_nblist(&fr->QMMMlist_sr,&fr->QMMMlist_lr,
364 maxsr,maxlr,0,icoul,FALSE,enlistATOM_ATOM);
367 fr->ns.nblist_initialized=TRUE;
370 static void reset_nblist(t_nblist *nl)
372 nl->nri = -1;
373 nl->nrj = 0;
374 nl->maxlen = 0;
375 if (nl->jindex)
377 nl->jindex[0] = 0;
381 static void reset_neighbor_list(t_forcerec *fr,bool bLR,int nls,int eNL)
383 int n,i;
385 if (bLR)
387 reset_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
389 else
391 for(n=0; n<fr->nnblists; n++)
393 for(i=0; i<eNL_NR; i++)
395 reset_nblist(&(fr->nblists[n].nlist_sr[i]));
398 if (fr->bQMMM)
400 /* only reset the short-range nblist */
401 reset_nblist(&(fr->QMMMlist_sr));
409 static inline void new_i_nblist(t_nblist *nlist,
410 bool bLR,atom_id i_atom,int shift,int gid)
412 int i,k,nri,nshift;
414 nri = nlist->nri;
416 /* Check whether we have to increase the i counter */
417 if ((nri == -1) ||
418 (nlist->iinr[nri] != i_atom) ||
419 (nlist->shift[nri] != shift) ||
420 (nlist->gid[nri] != gid))
422 /* This is something else. Now see if any entries have
423 * been added in the list of the previous atom.
425 if ((nri == -1) ||
426 ((nlist->jindex[nri+1] > nlist->jindex[nri]) &&
427 (nlist->gid[nri] != -1)))
429 /* If so increase the counter */
430 nlist->nri++;
431 nri++;
432 if (nlist->nri >= nlist->maxnri)
434 nlist->maxnri += over_alloc_large(nlist->nri);
435 reallocate_nblist(nlist);
438 /* Set the number of neighbours and the atom number */
439 nlist->jindex[nri+1] = nlist->jindex[nri];
440 nlist->iinr[nri] = i_atom;
441 nlist->gid[nri] = gid;
442 nlist->shift[nri] = shift;
446 static inline void close_i_nblist(t_nblist *nlist)
448 int nri = nlist->nri;
449 int len;
451 if (nri >= 0)
453 nlist->jindex[nri+1] = nlist->nrj;
455 len=nlist->nrj - nlist->jindex[nri];
457 /* nlist length for water i molecules is treated statically
458 * in the innerloops
460 if (len > nlist->maxlen)
462 nlist->maxlen = len;
467 static inline void close_nblist(t_nblist *nlist)
469 /* Only close this nblist when it has been initialized */
470 if (nlist->jindex)
472 nlist->nri++;
476 static inline void close_neighbor_list(t_forcerec *fr,bool bLR,int nls,int eNL,
477 bool bMakeQMMMnblist)
479 int n,i;
481 if (bMakeQMMMnblist) {
482 if (bLR)
484 close_nblist(&(fr->QMMMlist_lr));
486 else
488 close_nblist(&(fr->QMMMlist_sr));
491 else
493 if (bLR)
495 close_nblist(&(fr->nblists[nls].nlist_lr[eNL]));
497 else
499 for(n=0; n<fr->nnblists; n++)
501 for(i=0; (i<eNL_NR); i++)
503 close_nblist(&(fr->nblists[n].nlist_sr[i]));
510 static inline void add_j_to_nblist(t_nblist *nlist,atom_id j_atom,bool bLR)
512 int nrj=nlist->nrj;
514 if (nlist->nrj >= nlist->maxnrj)
516 nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
517 if (gmx_debug_at)
518 fprintf(debug,"Increasing %s nblist %s j size to %d\n",
519 bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
521 srenew(nlist->jjnr,nlist->maxnrj);
524 nlist->jjnr[nrj] = j_atom;
525 nlist->nrj ++;
528 static inline void add_j_to_nblist_cg(t_nblist *nlist,
529 atom_id j_start,int j_end,bool bLR)
531 int nrj=nlist->nrj;
533 if (nlist->nrj >= nlist->maxnrj)
535 nlist->maxnrj = over_alloc_small(nlist->nrj + 1);
536 if (gmx_debug_at)
537 fprintf(debug,"Increasing %s nblist %s j size to %d\n",
538 bLR ? "LR" : "SR",nrnb_str(nlist->il_code),nlist->maxnrj);
540 srenew(nlist->jjnr ,nlist->maxnrj);
541 srenew(nlist->jjnr_end,nlist->maxnrj);
544 nlist->jjnr[nrj] = j_start;
545 nlist->jjnr_end[nrj] = j_end;
546 nlist->nrj ++;
549 #ifndef GMX_CG_INNERLOOP
550 static inline void
551 put_in_list(bool bHaveVdW[],
552 int ngid,
553 t_mdatoms * md,
554 int icg,
555 int jgid,
556 int nj,
557 atom_id jjcg[],
558 atom_id index[],
559 t_excl bExcl[],
560 int shift,
561 t_forcerec * fr,
562 bool bLR,
563 bool bDoVdW,
564 bool bDoCoul,
565 bool bQMMM)
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].
570 t_nblist * vdwc;
571 t_nblist * vdw;
572 t_nblist * coul;
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;
581 int i0,nicg,len;
583 int *cginfo;
584 int *type,*typeB;
585 real *charge,*chargeB;
586 real qi,qiB,qq,rlj;
587 bool bFreeEnergy,bFree,bFreeJ,bNotEx,*bPert;
588 bool bDoVdW_i,bDoCoul_i,bDoCoul_i_sol;
589 int iwater,jwater;
590 t_nblist *nlist;
592 /* Copy some pointers */
593 cginfo = fr->cginfo;
594 charge = md->chargeA;
595 chargeB = md->chargeB;
596 type = md->typeA;
597 typeB = md->typeB;
598 bPert = md->bPerturbed;
600 /* Get atom range */
601 i0 = index[icg];
602 nicg = index[icg+1]-i0;
604 /* Get the i charge group info */
605 igid = GET_CGINFO_GID(cginfo[icg]);
606 iwater = GET_CGINFO_SOLOPT(cginfo[icg]);
608 bFreeEnergy = FALSE;
609 if (md->nPerturbed)
611 /* Check if any of the particles involved are perturbed.
612 * If not we can do the cheaper normal put_in_list
613 * and use more solvent optimization.
615 for(i=0; i<nicg; i++)
617 bFreeEnergy |= bPert[i0+i];
619 /* Loop over the j charge groups */
620 for(j=0; (j<nj && !bFreeEnergy); j++)
622 jcg = jjcg[j];
623 jj0 = index[jcg];
624 jj1 = index[jcg+1];
625 /* Finally loop over the atoms in the j-charge group */
626 for(jj=jj0; jj<jj1; jj++)
628 bFreeEnergy |= bPert[jj];
633 /* Unpack pointers to neighbourlist structs */
634 if (fr->nnblists == 1)
636 nbl_ind = 0;
638 else
640 nbl_ind = fr->gid2nblists[GID(igid,jgid,ngid)];
642 if (bLR)
644 nlist = fr->nblists[nbl_ind].nlist_lr;
646 else
648 nlist = fr->nblists[nbl_ind].nlist_sr;
651 if (iwater != esolNO)
653 vdwc = &nlist[eNL_VDWQQ_WATER];
654 vdw = &nlist[eNL_VDW];
655 coul = &nlist[eNL_QQ_WATER];
656 #ifndef DISABLE_WATERWATER_NLIST
657 vdwc_ww = &nlist[eNL_VDWQQ_WATERWATER];
658 coul_ww = &nlist[eNL_QQ_WATERWATER];
659 #endif
661 else if (bQMMM)
663 vdwc = NULL;
664 vdw = NULL;
665 coul = (bLR) ? &fr->QMMMlist_lr : &fr->QMMMlist_sr;
667 else
669 vdwc = &nlist[eNL_VDWQQ];
670 vdw = &nlist[eNL_VDW];
671 coul = &nlist[eNL_QQ];
674 if (!bFreeEnergy)
676 if (iwater != esolNO)
678 /* Loop over the atoms in the i charge group */
679 i_atom = i0;
680 gid = GID(igid,jgid,ngid);
681 /* Create new i_atom for each energy group */
682 if (bDoCoul && bDoVdW)
684 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
685 #ifndef DISABLE_WATERWATER_NLIST
686 new_i_nblist(vdwc_ww,bLR,i_atom,shift,gid);
687 #endif
689 if (bDoVdW)
691 new_i_nblist(vdw,bLR,i_atom,shift,gid);
693 if (bDoCoul)
695 new_i_nblist(coul,bLR,i_atom,shift,gid);
696 #ifndef DISABLE_WATERWATER_NLIST
697 new_i_nblist(coul_ww,bLR,i_atom,shift,gid);
698 #endif
700 /* Loop over the j charge groups */
701 for(j=0; (j<nj); j++)
703 jcg=jjcg[j];
705 if (jcg == icg)
707 continue;
710 jj0 = index[jcg];
711 jwater = GET_CGINFO_SOLOPT(cginfo[jcg]);
713 if (iwater == esolSPC && jwater == esolSPC)
715 /* Interaction between two SPC molecules */
716 if (!bDoCoul)
718 /* VdW only - only first atoms in each water interact */
719 add_j_to_nblist(vdw,jj0,bLR);
721 else
723 #ifdef DISABLE_WATERWATER_NLIST
724 /* Add entries for the three atoms - only do VdW if we need to */
725 if (!bDoVdW)
727 add_j_to_nblist(coul,jj0,bLR);
729 else
731 add_j_to_nblist(vdwc,jj0,bLR);
733 add_j_to_nblist(coul,jj0+1,bLR);
734 add_j_to_nblist(coul,jj0+2,bLR);
735 #else
736 /* One entry for the entire water-water interaction */
737 if (!bDoVdW)
739 add_j_to_nblist(coul_ww,jj0,bLR);
741 else
743 add_j_to_nblist(vdwc_ww,jj0,bLR);
745 #endif
748 else if (iwater == esolTIP4P && jwater == esolTIP4P)
750 /* Interaction between two TIP4p molecules */
751 if (!bDoCoul)
753 /* VdW only - only first atoms in each water interact */
754 add_j_to_nblist(vdw,jj0,bLR);
756 else
758 #ifdef DISABLE_WATERWATER_NLIST
759 /* Add entries for the four atoms - only do VdW if we need to */
760 if (bDoVdW)
762 add_j_to_nblist(vdw,jj0,bLR);
764 add_j_to_nblist(coul,jj0+1,bLR);
765 add_j_to_nblist(coul,jj0+2,bLR);
766 add_j_to_nblist(coul,jj0+3,bLR);
767 #else
768 /* One entry for the entire water-water interaction */
769 if (!bDoVdW)
771 add_j_to_nblist(coul_ww,jj0,bLR);
773 else
775 add_j_to_nblist(vdwc_ww,jj0,bLR);
777 #endif
780 else
782 /* j charge group is not water, but i is.
783 * Add entries to the water-other_atom lists; the geometry of the water
784 * molecule doesn't matter - that is taken care of in the nonbonded kernel,
785 * so we don't care if it is SPC or TIP4P...
788 jj1 = index[jcg+1];
790 if (!bDoVdW)
792 for(jj=jj0; (jj<jj1); jj++)
794 if (charge[jj] != 0)
796 add_j_to_nblist(coul,jj,bLR);
800 else if (!bDoCoul)
802 for(jj=jj0; (jj<jj1); jj++)
804 if (bHaveVdW[type[jj]])
806 add_j_to_nblist(vdw,jj,bLR);
810 else
812 /* _charge_ _groups_ interact with both coulomb and LJ */
813 /* Check which atoms we should add to the lists! */
814 for(jj=jj0; (jj<jj1); jj++)
816 if (bHaveVdW[type[jj]])
818 if (charge[jj] != 0)
820 add_j_to_nblist(vdwc,jj,bLR);
822 else
824 add_j_to_nblist(vdw,jj,bLR);
827 else if (charge[jj] != 0)
829 add_j_to_nblist(coul,jj,bLR);
835 close_i_nblist(vdw);
836 close_i_nblist(coul);
837 close_i_nblist(vdwc);
838 #ifndef DISABLE_WATERWATER_NLIST
839 close_i_nblist(coul_ww);
840 close_i_nblist(vdwc_ww);
841 #endif
843 else if (bQMMM)
845 /* QMMM atoms as i charge groups */
846 if (!bLR)
848 /* Loop over atoms in the ith charge group */
849 for (i=0;i<nicg;i++)
851 i_atom = i0+i;
852 gid = GID(igid,jgid,ngid);
853 /* Create new i_atom for each energy group */
854 new_i_nblist(coul,bLR,i_atom,shift,gid);
856 /* Loop over the j charge groups */
857 for (j=0;j<nj;j++)
859 jcg=jjcg[j];
861 /* Charge groups cannot have QM and MM atoms simultaneously */
862 if (jcg!=icg)
864 jj0 = index[jcg];
865 jj1 = index[jcg+1];
866 /* Finally loop over the atoms in the j-charge group */
867 for(jj=jj0; jj<jj1; jj++)
869 bNotEx = NOTEXCL(bExcl,i,jj);
870 if(bNotEx)
871 add_j_to_nblist(coul,jj,bLR);
875 close_i_nblist(coul);
879 else
881 /* no solvent as i charge group */
882 /* Loop over the atoms in the i charge group */
883 for(i=0; i<nicg; i++)
885 i_atom = i0+i;
886 gid = GID(igid,jgid,ngid);
887 qi = charge[i_atom];
889 /* Create new i_atom for each energy group */
890 if (bDoVdW && bDoCoul)
892 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
894 if (bDoVdW)
896 new_i_nblist(vdw,bLR,i_atom,shift,gid);
898 if (bDoCoul)
900 new_i_nblist(coul,bLR,i_atom,shift,gid);
902 bDoVdW_i = (bDoVdW && bHaveVdW[type[i_atom]]);
903 bDoCoul_i = (bDoCoul && qi!=0);
905 if (bDoVdW_i || bDoCoul_i)
907 /* Loop over the j charge groups */
908 for(j=0; (j<nj); j++)
910 jcg=jjcg[j];
912 /* Check for large charge groups */
913 if (jcg == icg)
915 jj0 = i0 + i + 1;
917 else
919 jj0 = index[jcg];
922 jj1=index[jcg+1];
923 /* Finally loop over the atoms in the j-charge group */
924 for(jj=jj0; jj<jj1; jj++)
926 bNotEx = NOTEXCL(bExcl,i,jj);
928 if (bNotEx)
930 if (!bDoVdW_i)
932 if (charge[jj] != 0)
934 add_j_to_nblist(coul,jj,bLR);
937 else if (!bDoCoul_i)
939 if (bHaveVdW[type[jj]])
941 add_j_to_nblist(vdw,jj,bLR);
944 else
946 if (bHaveVdW[type[jj]])
948 if (charge[jj] != 0)
950 add_j_to_nblist(vdwc,jj,bLR);
952 else
954 add_j_to_nblist(vdw,jj,bLR);
957 else if (charge[jj] != 0)
959 add_j_to_nblist(coul,jj,bLR);
966 close_i_nblist(vdw);
967 close_i_nblist(coul);
968 close_i_nblist(vdwc);
972 else
974 /* we are doing free energy */
975 vdwc_free = &nlist[eNL_VDWQQ_FREE];
976 vdw_free = &nlist[eNL_VDW_FREE];
977 coul_free = &nlist[eNL_QQ_FREE];
978 /* Loop over the atoms in the i charge group */
979 for(i=0; i<nicg; i++)
981 i_atom = i0+i;
982 gid = GID(igid,jgid,ngid);
983 qi = charge[i_atom];
984 qiB = chargeB[i_atom];
986 /* Create new i_atom for each energy group */
987 if (bDoVdW && bDoCoul)
988 new_i_nblist(vdwc,bLR,i_atom,shift,gid);
989 if (bDoVdW)
990 new_i_nblist(vdw,bLR,i_atom,shift,gid);
991 if (bDoCoul)
992 new_i_nblist(coul,bLR,i_atom,shift,gid);
994 new_i_nblist(vdw_free,bLR,i_atom,shift,gid);
995 new_i_nblist(coul_free,bLR,i_atom,shift,gid);
996 new_i_nblist(vdwc_free,bLR,i_atom,shift,gid);
998 bDoVdW_i = (bDoVdW &&
999 (bHaveVdW[type[i_atom]] || bHaveVdW[typeB[i_atom]]));
1000 bDoCoul_i = (bDoCoul && (qi!=0 || qiB!=0));
1001 /* For TIP4P the first atom does not have a charge,
1002 * but the last three do. So we should still put an atom
1003 * without LJ but with charge in the water-atom neighborlist
1004 * for a TIP4p i charge group.
1005 * For SPC type water the first atom has LJ and charge,
1006 * so there is no such problem.
1008 if (iwater == esolNO)
1010 bDoCoul_i_sol = bDoCoul_i;
1012 else
1014 bDoCoul_i_sol = bDoCoul;
1017 if (bDoVdW_i || bDoCoul_i_sol)
1019 /* Loop over the j charge groups */
1020 for(j=0; (j<nj); j++)
1022 jcg=jjcg[j];
1024 /* Check for large charge groups */
1025 if (jcg == icg)
1027 jj0 = i0 + i + 1;
1029 else
1031 jj0 = index[jcg];
1034 jj1=index[jcg+1];
1035 /* Finally loop over the atoms in the j-charge group */
1036 bFree = bPert[i_atom];
1037 for(jj=jj0; (jj<jj1); jj++)
1039 bFreeJ = bFree || bPert[jj];
1040 /* Complicated if, because the water H's should also
1041 * see perturbed j-particles
1043 if (iwater==esolNO || i==0 || bFreeJ)
1045 bNotEx = NOTEXCL(bExcl,i,jj);
1047 if (bNotEx)
1049 if (bFreeJ)
1051 if (!bDoVdW_i)
1053 if (charge[jj]!=0 || chargeB[jj]!=0)
1055 add_j_to_nblist(coul_free,jj,bLR);
1058 else if (!bDoCoul_i)
1060 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1062 add_j_to_nblist(vdw_free,jj,bLR);
1065 else
1067 if (bHaveVdW[type[jj]] || bHaveVdW[typeB[jj]])
1069 if (charge[jj]!=0 || chargeB[jj]!=0)
1071 add_j_to_nblist(vdwc_free,jj,bLR);
1073 else
1075 add_j_to_nblist(vdw_free,jj,bLR);
1078 else if (charge[jj]!=0 || chargeB[jj]!=0)
1079 add_j_to_nblist(coul_free,jj,bLR);
1082 else if (!bDoVdW_i)
1084 /* This is done whether or not bWater is set */
1085 if (charge[jj] != 0)
1087 add_j_to_nblist(coul,jj,bLR);
1090 else if (!bDoCoul_i_sol)
1092 if (bHaveVdW[type[jj]])
1094 add_j_to_nblist(vdw,jj,bLR);
1097 else
1099 if (bHaveVdW[type[jj]])
1101 if (charge[jj] != 0)
1103 add_j_to_nblist(vdwc,jj,bLR);
1105 else
1107 add_j_to_nblist(vdw,jj,bLR);
1110 else if (charge[jj] != 0)
1112 add_j_to_nblist(coul,jj,bLR);
1120 close_i_nblist(vdw);
1121 close_i_nblist(coul);
1122 close_i_nblist(vdwc);
1123 close_i_nblist(vdw_free);
1124 close_i_nblist(coul_free);
1125 close_i_nblist(vdwc_free);
1129 #endif
1131 #ifdef GMX_CG_INNERLOOP
1132 static inline void
1133 put_in_list(bool bHaveVdW[],
1134 int ngid,
1135 t_mdatoms * md,
1136 int icg,
1137 int jgid,
1138 int nj,
1139 atom_id jjcg[],
1140 atom_id index[],
1141 t_excl bExcl[],
1142 int shift,
1143 t_forcerec * fr,
1144 bool bLR,
1145 bool bDoVdW,
1146 bool bDoCoul,
1147 bool bQMMM)
1149 int igid,gid,nbl_ind;
1150 t_nblist * vdwc;
1151 int j,jcg;
1153 igid = GET_CGINFO_GID(fr->cginfo[icg]);
1154 gid = GID(igid,jgid,ngid);
1156 /* Unpack pointers to neighbourlist structs */
1157 if (fr->nnblists == 1)
1159 nbl_ind = 0;
1161 else
1163 nbl_ind = fr->gid2nblists[gid];
1165 if (bLR)
1167 vdwc = &fr->nblists[nbl_ind].nlist_lr[eNL_VDWQQ];
1169 else
1171 vdwc = &fr->nblists[nbl_ind].nlist_sr[eNL_VDWQQ];
1174 /* Make a new neighbor list for charge group icg.
1175 * Currently simply one neighbor list is made with LJ and Coulomb.
1176 * If required, zerp interactions could be removed here
1177 * or in the force loop.
1179 new_i_nblist(vdwc,bLR,index[icg],shift,gid);
1180 vdwc->iinr_end[vdwc->nri] = index[icg+1];
1182 for(j=0; (j<nj); j++)
1184 jcg = jjcg[j];
1185 if (jcg != icg)
1187 /* Here we simply add the j charge group jcg to the list
1188 * without checking exclusions, LJ interactions or charges.
1190 add_j_to_nblist_cg(vdwc,index[jcg],index[jcg+1],bLR);
1194 close_i_nblist(vdwc);
1196 #endif
1198 static void setexcl(atom_id start,atom_id end,t_blocka *excl,bool b,
1199 t_excl bexcl[])
1201 atom_id i,k;
1203 if (b)
1205 for(i=start; i<end; i++)
1207 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1209 SETEXCL(bexcl,i-start,excl->a[k]);
1213 else
1215 for(i=start; i<end; i++)
1217 for(k=excl->index[i]; k<excl->index[i+1]; k++)
1219 RMEXCL(bexcl,i-start,excl->a[k]);
1225 int calc_naaj(int icg,int cgtot)
1227 int naaj;
1229 if ((cgtot % 2) == 1)
1231 /* Odd number of charge groups, easy */
1232 naaj = 1 + (cgtot/2);
1234 else if ((cgtot % 4) == 0)
1236 /* Multiple of four is hard */
1237 if (icg < cgtot/2)
1239 if ((icg % 2) == 0)
1241 naaj=1+(cgtot/2);
1243 else
1245 naaj=cgtot/2;
1248 else
1250 if ((icg % 2) == 1)
1252 naaj=1+(cgtot/2);
1254 else
1256 naaj=cgtot/2;
1260 else
1262 /* cgtot/2 = odd */
1263 if ((icg % 2) == 0)
1265 naaj=1+(cgtot/2);
1267 else
1269 naaj=cgtot/2;
1272 #ifdef DEBUG
1273 fprintf(log,"naaj=%d\n",naaj);
1274 #endif
1276 return naaj;
1279 /************************************************
1281 * S I M P L E C O R E S T U F F
1283 ************************************************/
1285 static real calc_image_tric(rvec xi,rvec xj,matrix box,
1286 rvec b_inv,int *shift)
1288 /* This code assumes that the cut-off is smaller than
1289 * a half times the smallest diagonal element of the box.
1291 const real h25=2.5;
1292 real dx,dy,dz;
1293 real r2;
1294 int tx,ty,tz;
1296 /* Compute diff vector */
1297 dz = xj[ZZ] - xi[ZZ];
1298 dy = xj[YY] - xi[YY];
1299 dx = xj[XX] - xi[XX];
1301 /* Perform NINT operation, using trunc operation, therefore
1302 * we first add 2.5 then subtract 2 again
1304 tz = dz*b_inv[ZZ] + h25;
1305 tz -= 2;
1306 dz -= tz*box[ZZ][ZZ];
1307 dy -= tz*box[ZZ][YY];
1308 dx -= tz*box[ZZ][XX];
1310 ty = dy*b_inv[YY] + h25;
1311 ty -= 2;
1312 dy -= ty*box[YY][YY];
1313 dx -= ty*box[YY][XX];
1315 tx = dx*b_inv[XX]+h25;
1316 tx -= 2;
1317 dx -= tx*box[XX][XX];
1319 /* Distance squared */
1320 r2 = (dx*dx) + (dy*dy) + (dz*dz);
1322 *shift = XYZ2IS(tx,ty,tz);
1324 return r2;
1327 static real calc_image_rect(rvec xi,rvec xj,rvec box_size,
1328 rvec b_inv,int *shift)
1330 const real h15=1.5;
1331 real ddx,ddy,ddz;
1332 real dx,dy,dz;
1333 real r2;
1334 int tx,ty,tz;
1336 /* Compute diff vector */
1337 dx = xj[XX] - xi[XX];
1338 dy = xj[YY] - xi[YY];
1339 dz = xj[ZZ] - xi[ZZ];
1341 /* Perform NINT operation, using trunc operation, therefore
1342 * we first add 1.5 then subtract 1 again
1344 tx = dx*b_inv[XX] + h15;
1345 ty = dy*b_inv[YY] + h15;
1346 tz = dz*b_inv[ZZ] + h15;
1347 tx--;
1348 ty--;
1349 tz--;
1351 /* Correct diff vector for translation */
1352 ddx = tx*box_size[XX] - dx;
1353 ddy = ty*box_size[YY] - dy;
1354 ddz = tz*box_size[ZZ] - dz;
1356 /* Distance squared */
1357 r2 = (ddx*ddx) + (ddy*ddy) + (ddz*ddz);
1359 *shift = XYZ2IS(tx,ty,tz);
1361 return r2;
1364 static void add_simple(t_ns_buf *nsbuf,int nrj,atom_id cg_j,
1365 bool bHaveVdW[],int ngid,t_mdatoms *md,
1366 int icg,int jgid,t_block *cgs,t_excl bexcl[],
1367 int shift,t_forcerec *fr)
1369 if (nsbuf->nj + nrj > MAX_CG)
1371 put_in_list(bHaveVdW,ngid,md,icg,jgid,nsbuf->ncg,nsbuf->jcg,
1372 cgs->index,bexcl,shift,fr,FALSE,TRUE,TRUE,FALSE);
1373 /* Reset buffer contents */
1374 nsbuf->ncg = nsbuf->nj = 0;
1376 nsbuf->jcg[nsbuf->ncg++] = cg_j;
1377 nsbuf->nj += nrj;
1380 static void ns_inner_tric(rvec x[],int icg,int *i_egp_flags,
1381 int njcg,atom_id jcg[],
1382 matrix box,rvec b_inv,real rcut2,
1383 t_block *cgs,t_ns_buf **ns_buf,
1384 bool bHaveVdW[],int ngid,t_mdatoms *md,
1385 t_excl bexcl[],t_forcerec *fr)
1387 int shift;
1388 int j,nrj,jgid;
1389 int *cginfo=fr->cginfo;
1390 atom_id cg_j,*cgindex;
1391 t_ns_buf *nsbuf;
1393 cgindex = cgs->index;
1394 shift = CENTRAL;
1395 for(j=0; (j<njcg); j++)
1397 cg_j = jcg[j];
1398 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1399 if (calc_image_tric(x[icg],x[cg_j],box,b_inv,&shift) < rcut2)
1401 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1402 if (!(i_egp_flags[jgid] & EGP_EXCL))
1404 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1405 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr);
1411 static void ns_inner_rect(rvec x[],int icg,int *i_egp_flags,
1412 int njcg,atom_id jcg[],
1413 bool bBox,rvec box_size,rvec b_inv,real rcut2,
1414 t_block *cgs,t_ns_buf **ns_buf,
1415 bool bHaveVdW[],int ngid,t_mdatoms *md,
1416 t_excl bexcl[],t_forcerec *fr)
1418 int shift;
1419 int j,nrj,jgid;
1420 int *cginfo=fr->cginfo;
1421 atom_id cg_j,*cgindex;
1422 t_ns_buf *nsbuf;
1424 cgindex = cgs->index;
1425 if (bBox)
1427 shift = CENTRAL;
1428 for(j=0; (j<njcg); j++)
1430 cg_j = jcg[j];
1431 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1432 if (calc_image_rect(x[icg],x[cg_j],box_size,b_inv,&shift) < rcut2)
1434 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1435 if (!(i_egp_flags[jgid] & EGP_EXCL))
1437 add_simple(&ns_buf[jgid][shift],nrj,cg_j,
1438 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,shift,fr);
1443 else
1445 for(j=0; (j<njcg); j++)
1447 cg_j = jcg[j];
1448 nrj = cgindex[cg_j+1]-cgindex[cg_j];
1449 if ((rcut2 == 0) || (distance2(x[icg],x[cg_j]) < rcut2)) {
1450 jgid = GET_CGINFO_GID(cginfo[cg_j]);
1451 if (!(i_egp_flags[jgid] & EGP_EXCL))
1453 add_simple(&ns_buf[jgid][CENTRAL],nrj,cg_j,
1454 bHaveVdW,ngid,md,icg,jgid,cgs,bexcl,CENTRAL,fr);
1461 /* ns_simple_core needs to be adapted for QMMM still 2005 */
1463 static int ns_simple_core(t_forcerec *fr,
1464 gmx_localtop_t *top,
1465 t_mdatoms *md,
1466 matrix box,rvec box_size,
1467 t_excl bexcl[],atom_id *aaj,
1468 int ngid,t_ns_buf **ns_buf,
1469 bool bHaveVdW[])
1471 int naaj,k;
1472 real rlist2;
1473 int nsearch,icg,jcg,igid,i0,nri,nn;
1474 int *cginfo;
1475 t_ns_buf *nsbuf;
1476 /* atom_id *i_atoms; */
1477 t_block *cgs=&(top->cgs);
1478 t_blocka *excl=&(top->excls);
1479 rvec b_inv;
1480 int m;
1481 bool bBox,bTriclinic;
1482 int *i_egp_flags;
1484 rlist2 = sqr(fr->rlist);
1486 bBox = (fr->ePBC != epbcNONE);
1487 if (bBox)
1489 for(m=0; (m<DIM); m++)
1491 b_inv[m] = divide(1.0,box_size[m]);
1493 bTriclinic = TRICLINIC(box);
1495 else
1497 bTriclinic = FALSE;
1500 cginfo = fr->cginfo;
1502 nsearch=0;
1503 for (icg=fr->cg0; (icg<fr->hcg); icg++)
1506 i0 = cgs->index[icg];
1507 nri = cgs->index[icg+1]-i0;
1508 i_atoms = &(cgs->a[i0]);
1509 i_eg_excl = fr->eg_excl + ngid*md->cENER[*i_atoms];
1510 setexcl(nri,i_atoms,excl,TRUE,bexcl);
1512 igid = GET_CGINFO_GID(cginfo[icg]);
1513 i_egp_flags = fr->egp_flags + ngid*igid;
1514 setexcl(cgs->index[icg],cgs->index[icg+1],excl,TRUE,bexcl);
1516 naaj=calc_naaj(icg,cgs->nr);
1517 if (bTriclinic)
1519 ns_inner_tric(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1520 box,b_inv,rlist2,cgs,ns_buf,
1521 bHaveVdW,ngid,md,bexcl,fr);
1523 else
1525 ns_inner_rect(fr->cg_cm,icg,i_egp_flags,naaj,&(aaj[icg]),
1526 bBox,box_size,b_inv,rlist2,cgs,ns_buf,
1527 bHaveVdW,ngid,md,bexcl,fr);
1529 nsearch += naaj;
1531 for(nn=0; (nn<ngid); nn++)
1533 for(k=0; (k<SHIFTS); k++)
1535 nsbuf = &(ns_buf[nn][k]);
1536 if (nsbuf->ncg > 0)
1538 put_in_list(bHaveVdW,ngid,md,icg,nn,nsbuf->ncg,nsbuf->jcg,
1539 cgs->index,bexcl,k,fr,FALSE,TRUE,TRUE,FALSE);
1540 nsbuf->ncg=nsbuf->nj=0;
1544 /* setexcl(nri,i_atoms,excl,FALSE,bexcl); */
1545 setexcl(cgs->index[icg],cgs->index[icg+1],excl,FALSE,bexcl);
1547 close_neighbor_list(fr,FALSE,-1,-1,FALSE);
1549 return nsearch;
1552 /************************************************
1554 * N S 5 G R I D S T U F F
1556 ************************************************/
1558 static inline void get_dx(int Nx,real gridx,real rc2,int xgi,real x,
1559 int *dx0,int *dx1,real *dcx2)
1561 real dcx,tmp;
1562 int xgi0,xgi1,i;
1564 if (xgi < 0)
1566 *dx0 = 0;
1567 xgi0 = -1;
1568 *dx1 = -1;
1569 xgi1 = 0;
1571 else if (xgi >= Nx)
1573 *dx0 = Nx;
1574 xgi0 = Nx-1;
1575 *dx1 = Nx-1;
1576 xgi1 = Nx;
1578 else
1580 dcx2[xgi] = 0;
1581 *dx0 = xgi;
1582 xgi0 = xgi-1;
1583 *dx1 = xgi;
1584 xgi1 = xgi+1;
1587 for(i=xgi0; i>=0; i--)
1589 dcx = (i+1)*gridx-x;
1590 tmp = dcx*dcx;
1591 if (tmp >= rc2)
1592 break;
1593 *dx0 = i;
1594 dcx2[i] = tmp;
1596 for(i=xgi1; i<Nx; i++)
1598 dcx = i*gridx-x;
1599 tmp = dcx*dcx;
1600 if (tmp >= rc2)
1602 break;
1604 *dx1 = i;
1605 dcx2[i] = tmp;
1609 static inline void get_dx_dd(int Nx,real gridx,real rc2,int xgi,real x,
1610 int ncpddc,int shift_min,int shift_max,
1611 int *g0,int *g1,real *dcx2)
1613 real dcx,tmp;
1614 int g_min,g_max,shift_home;
1616 if (xgi < 0)
1618 g_min = 0;
1619 g_max = Nx - 1;
1620 *g0 = 0;
1621 *g1 = -1;
1623 else if (xgi >= Nx)
1625 g_min = 0;
1626 g_max = Nx - 1;
1627 *g0 = Nx;
1628 *g1 = Nx - 1;
1630 else
1632 if (ncpddc == 0)
1634 g_min = 0;
1635 g_max = Nx - 1;
1637 else
1639 if (xgi < ncpddc)
1641 shift_home = 0;
1643 else
1645 shift_home = -1;
1647 g_min = (shift_min == shift_home ? 0 : ncpddc);
1648 g_max = (shift_max == shift_home ? ncpddc - 1 : Nx - 1);
1650 if (shift_min > 0)
1652 *g0 = g_min;
1653 *g1 = g_min - 1;
1655 else if (shift_max < 0)
1657 *g0 = g_max + 1;
1658 *g1 = g_max;
1660 else
1662 *g0 = xgi;
1663 *g1 = xgi;
1664 dcx2[xgi] = 0;
1668 while (*g0 > g_min)
1670 /* Check one grid cell down */
1671 dcx = ((*g0 - 1) + 1)*gridx - x;
1672 tmp = dcx*dcx;
1673 if (tmp >= rc2)
1675 break;
1677 (*g0)--;
1678 dcx2[*g0] = tmp;
1681 while (*g1 < g_max)
1683 /* Check one grid cell up */
1684 dcx = (*g1 + 1)*gridx - x;
1685 tmp = dcx*dcx;
1686 if (tmp >= rc2)
1688 break;
1690 (*g1)++;
1691 dcx2[*g1] = tmp;
1696 #define sqr(x) ((x)*(x))
1697 #define calc_dx2(XI,YI,ZI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]) + sqr(ZI-y[ZZ]))
1698 #define calc_cyl_dx2(XI,YI,y) (sqr(XI-y[XX]) + sqr(YI-y[YY]))
1699 /****************************************************
1701 * F A S T N E I G H B O R S E A R C H I N G
1703 * Optimized neighboursearching routine using grid
1704 * at least 1x1x1, see GROMACS manual
1706 ****************************************************/
1708 static void do_longrange(t_commrec *cr,gmx_localtop_t *top,t_forcerec *fr,
1709 int ngid,t_mdatoms *md,int icg,
1710 int jgid,int nlr,
1711 atom_id lr[],t_excl bexcl[],int shift,
1712 rvec x[],rvec box_size,t_nrnb *nrnb,
1713 real lambda,real *dvdlambda,
1714 gmx_grppairener_t *grppener,
1715 bool bDoVdW,bool bDoCoul,
1716 bool bEvaluateNow,bool bHaveVdW[],
1717 bool bDoForces,rvec *f)
1719 int n,i;
1720 t_nblist *nl;
1722 for(n=0; n<fr->nnblists; n++)
1724 for(i=0; (i<eNL_NR); i++)
1726 nl = &fr->nblists[n].nlist_lr[i];
1727 if ((nl->nri > nl->maxnri-32) || bEvaluateNow)
1729 close_neighbor_list(fr,TRUE,n,i,FALSE);
1730 /* Evaluate the energies and forces */
1731 do_nonbonded(cr,fr,x,f,md,NULL,
1732 grppener->ener[fr->bBHAM ? egBHAMLR : egLJLR],
1733 grppener->ener[egCOULLR],
1734 grppener->ener[egGB],box_size,
1735 nrnb,lambda,dvdlambda,n,i,
1736 GMX_DONB_LR | GMX_DONB_FORCES);
1738 reset_neighbor_list(fr,TRUE,n,i);
1743 if (!bEvaluateNow)
1745 /* Put the long range particles in a list */
1746 /* Since do_longrange is never called for QMMM, bQMMM is FALSE */
1747 put_in_list(bHaveVdW,ngid,md,icg,jgid,nlr,lr,top->cgs.index,
1748 bexcl,shift,fr,TRUE,bDoVdW,bDoCoul,FALSE);
1752 static int nsgrid_core(FILE *log,t_commrec *cr,t_forcerec *fr,
1753 matrix box,rvec box_size,int ngid,
1754 gmx_localtop_t *top,
1755 t_grid *grid,rvec x[],
1756 t_excl bexcl[],bool *bExcludeAlleg,
1757 t_nrnb *nrnb,t_mdatoms *md,
1758 real lambda,real *dvdlambda,
1759 gmx_grppairener_t *grppener,
1760 bool bHaveVdW[],
1761 bool bDoLongRange,bool bDoForces,rvec *f,
1762 bool bMakeQMMMnblist)
1764 gmx_ns_t *ns;
1765 atom_id **nl_lr_ljc,**nl_lr_one,**nl_sr;
1766 int *nlr_ljc,*nlr_one,*nsr;
1767 gmx_domdec_t *dd=NULL;
1768 t_block *cgs=&(top->cgs);
1769 int *cginfo=fr->cginfo;
1770 /* atom_id *i_atoms,*cgsindex=cgs->index; */
1771 ivec sh0,sh1,shp;
1772 int cell_x,cell_y,cell_z;
1773 int d,tx,ty,tz,dx,dy,dz,cj;
1774 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
1775 int zsh_ty,zsh_tx,ysh_tx;
1776 #endif
1777 int dx0,dx1,dy0,dy1,dz0,dz1;
1778 int Nx,Ny,Nz,shift=-1,j,nrj,nns,nn=-1;
1779 real gridx,gridy,gridz,grid_x,grid_y,grid_z;
1780 real *dcx2,*dcy2,*dcz2;
1781 int zgi,ygi,xgi;
1782 int cg0,cg1,icg=-1,cgsnr,i0,igid,nri,naaj,max_jcg;
1783 int jcg0,jcg1,jjcg,cgj0,jgid;
1784 int *grida,*gridnra,*gridind;
1785 bool rvdw_lt_rcoul,rcoul_lt_rvdw;
1786 rvec xi,*cgcm,grid_offset;
1787 real r2,rs2,rvdw2,rcoul2,rm2,rl2,XI,YI,ZI,dcx,dcy,dcz,tmp1,tmp2;
1788 int *i_egp_flags;
1789 bool bDomDec,bTriclinicX,bTriclinicY;
1790 ivec ncpddc;
1792 ns = &fr->ns;
1794 bDomDec = DOMAINDECOMP(cr);
1795 if (bDomDec)
1797 dd = cr->dd;
1800 bTriclinicX = ((YY < grid->npbcdim &&
1801 (!bDomDec || dd->nc[YY]==1) && box[YY][XX] != 0) ||
1802 (ZZ < grid->npbcdim &&
1803 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][XX] != 0));
1804 bTriclinicY = (ZZ < grid->npbcdim &&
1805 (!bDomDec || dd->nc[ZZ]==1) && box[ZZ][YY] != 0);
1807 cgsnr = cgs->nr;
1808 rs2 = sqr(fr->rlist);
1809 if (bDoLongRange && fr->bTwinRange)
1811 /* The VdW and elec. LR cut-off's could be different,
1812 * so we can not simply set them to rlistlong.
1814 if (EVDW_ZERO_AT_CUTOFF(fr->vdwtype) && fr->rvdw > fr->rlist)
1816 rvdw2 = sqr(fr->rlistlong);
1818 else
1820 rvdw2 = sqr(fr->rvdw);
1822 if (EEL_ZERO_AT_CUTOFF(fr->eeltype) && fr->rcoulomb > fr->rlist)
1824 rcoul2 = sqr(fr->rlistlong);
1826 else
1828 rcoul2 = sqr(fr->rcoulomb);
1831 else
1833 /* Workaround for a gcc -O3 or -ffast-math problem */
1834 rvdw2 = rs2;
1835 rcoul2 = rs2;
1837 rm2 = min(rvdw2,rcoul2);
1838 rl2 = max(rvdw2,rcoul2);
1839 rvdw_lt_rcoul = (rvdw2 >= rcoul2);
1840 rcoul_lt_rvdw = (rcoul2 >= rvdw2);
1842 if (bMakeQMMMnblist)
1844 rm2 = rl2;
1845 rs2 = rl2;
1848 if (ns->nl_sr == NULL)
1850 /* Short range buffers */
1851 snew(ns->nl_sr,ngid);
1852 /* Counters */
1853 snew(ns->nsr,ngid);
1854 snew(ns->nlr_ljc,ngid);
1855 snew(ns->nlr_one,ngid);
1857 if (rm2 > rs2)
1859 /* Long range VdW and Coul buffers */
1860 snew(ns->nl_lr_ljc,ngid);
1862 if (rl2 > rm2)
1864 /* Long range VdW or Coul only buffers */
1865 snew(ns->nl_lr_one,ngid);
1867 for(j=0; (j<ngid); j++) {
1868 snew(ns->nl_sr[j],MAX_CG);
1869 if (rm2 > rs2)
1871 snew(ns->nl_lr_ljc[j],MAX_CG);
1873 if (rl2 > rm2)
1875 snew(ns->nl_lr_one[j],MAX_CG);
1878 if (debug)
1879 fprintf(debug,
1880 "ns5_core: rs2 = %g, rvdw2 = %g, rcoul2 = %g (nm^2)\n",
1881 rs2,rvdw2,rcoul2);
1883 nl_sr = ns->nl_sr;
1884 nsr = ns->nsr;
1885 nl_lr_ljc = ns->nl_lr_ljc;
1886 nl_lr_one = ns->nl_lr_one;
1887 nlr_ljc = ns->nlr_ljc;
1888 nlr_one = ns->nlr_one;
1890 /* Unpack arrays */
1891 cgcm = fr->cg_cm;
1892 Nx = grid->n[XX];
1893 Ny = grid->n[YY];
1894 Nz = grid->n[ZZ];
1895 grida = grid->a;
1896 gridind = grid->index;
1897 gridnra = grid->nra;
1898 nns = 0;
1900 gridx = grid->cell_size[XX];
1901 gridy = grid->cell_size[YY];
1902 gridz = grid->cell_size[ZZ];
1903 grid_x = 1/gridx;
1904 grid_y = 1/gridy;
1905 grid_z = 1/gridz;
1906 copy_rvec(grid->cell_offset,grid_offset);
1907 copy_ivec(grid->ncpddc,ncpddc);
1908 dcx2 = grid->dcx2;
1909 dcy2 = grid->dcy2;
1910 dcz2 = grid->dcz2;
1912 #ifdef ALLOW_OFFDIAG_LT_HALFDIAG
1913 zsh_ty = floor(-box[ZZ][YY]/box[YY][YY]+0.5);
1914 zsh_tx = floor(-box[ZZ][XX]/box[XX][XX]+0.5);
1915 ysh_tx = floor(-box[YY][XX]/box[XX][XX]+0.5);
1916 if (zsh_tx!=0 && ysh_tx!=0)
1918 /* This could happen due to rounding, when both ratios are 0.5 */
1919 ysh_tx = 0;
1921 #endif
1923 debug_gmx();
1925 if (fr->n_tpi)
1927 /* We only want a list for the test particle */
1928 cg0 = cgsnr - 1;
1930 else
1932 cg0 = grid->icg0;
1934 cg1 = grid->icg1;
1936 /* Set the shift range */
1937 for(d=0; d<DIM; d++)
1939 sh0[d] = -1;
1940 sh1[d] = 1;
1941 /* Check if we need periodicity shifts.
1942 * Without PBC or with domain decomposition we don't need them.
1944 if (d >= ePBC2npbcdim(fr->ePBC) || (bDomDec && dd->nc[d] > 1))
1946 shp[d] = 0;
1948 else
1950 if (d == XX &&
1951 box[XX][XX] - fabs(box[YY][XX]) - fabs(box[ZZ][XX]) < sqrt(rl2))
1953 shp[d] = 2;
1955 else
1957 shp[d] = 1;
1962 /* Loop over charge groups */
1963 for(icg=cg0; (icg < cg1); icg++)
1965 igid = GET_CGINFO_GID(cginfo[icg]);
1966 /* Skip this charge group if all energy groups are excluded! */
1967 if (bExcludeAlleg[igid])
1969 continue;
1972 i0 = cgs->index[icg];
1974 if (bMakeQMMMnblist)
1976 /* Skip this charge group if it is not a QM atom while making a
1977 * QM/MM neighbourlist
1979 if (md->bQM[i0]==FALSE)
1981 continue; /* MM particle, go to next particle */
1984 /* Compute the number of charge groups that fall within the control
1985 * of this one (icg)
1987 naaj = calc_naaj(icg,cgsnr);
1988 jcg0 = icg;
1989 jcg1 = icg + naaj;
1990 max_jcg = cgsnr;
1992 else
1994 /* make a normal neighbourlist */
1996 if (bDomDec)
1998 /* Get the j charge-group and dd cell shift ranges */
1999 dd_get_ns_ranges(cr->dd,icg,&jcg0,&jcg1,sh0,sh1);
2000 max_jcg = 0;
2002 else
2004 /* Compute the number of charge groups that fall within the control
2005 * of this one (icg)
2007 naaj = calc_naaj(icg,cgsnr);
2008 jcg0 = icg;
2009 jcg1 = icg + naaj;
2011 if (fr->n_tpi)
2013 /* The i-particle is awlways the test particle,
2014 * so we want all j-particles
2016 max_jcg = cgsnr - 1;
2018 else
2020 max_jcg = jcg1 - cgsnr;
2025 i_egp_flags = fr->egp_flags + igid*ngid;
2027 /* Set the exclusions for the atoms in charge group icg using a bitmask */
2028 setexcl(i0,cgs->index[icg+1],&top->excls,TRUE,bexcl);
2030 ci2xyz(grid,icg,&cell_x,&cell_y,&cell_z);
2032 /* Changed iicg to icg, DvdS 990115
2033 * (but see consistency check above, DvdS 990330)
2035 #ifdef NS5DB
2036 fprintf(log,"icg=%5d, naaj=%5d, cell %d %d %d\n",
2037 icg,naaj,cell_x,cell_y,cell_z);
2038 #endif
2039 /* Loop over shift vectors in three dimensions */
2040 for (tz=-shp[ZZ]; tz<=shp[ZZ]; tz++)
2042 ZI = cgcm[icg][ZZ]+tz*box[ZZ][ZZ];
2043 /* Calculate range of cells in Z direction that have the shift tz */
2044 zgi = cell_z + tz*Nz;
2045 #define FAST_DD_NS
2046 #ifndef FAST_DD_NS
2047 get_dx(Nz,gridz,rl2,zgi,ZI,&dz0,&dz1,dcz2);
2048 #else
2049 get_dx_dd(Nz,gridz,rl2,zgi,ZI-grid_offset[ZZ],
2050 ncpddc[ZZ],sh0[ZZ],sh1[ZZ],&dz0,&dz1,dcz2);
2051 #endif
2052 if (dz0 > dz1)
2054 continue;
2056 for (ty=-shp[YY]; ty<=shp[YY]; ty++)
2058 YI = cgcm[icg][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
2059 /* Calculate range of cells in Y direction that have the shift ty */
2060 if (bTriclinicY)
2062 ygi = (int)(Ny + (YI - grid_offset[YY])*grid_y) - Ny;
2064 else
2066 ygi = cell_y + ty*Ny;
2068 #ifndef FAST_DD_NS
2069 get_dx(Ny,gridy,rl2,ygi,YI,&dy0,&dy1,dcy2);
2070 #else
2071 get_dx_dd(Ny,gridy,rl2,ygi,YI-grid_offset[YY],
2072 ncpddc[YY],sh0[YY],sh1[YY],&dy0,&dy1,dcy2);
2073 #endif
2074 if (dy0 > dy1)
2076 continue;
2078 for (tx=-shp[XX]; tx<=shp[XX]; tx++)
2080 XI = cgcm[icg][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
2081 /* Calculate range of cells in X direction that have the shift tx */
2082 if (bTriclinicX)
2084 xgi = (int)(Nx + (XI - grid_offset[XX])*grid_x) - Nx;
2086 else
2088 xgi = cell_x + tx*Nx;
2090 #ifndef FAST_DD_NS
2091 get_dx(Nx,gridx,rl2,xgi*Nx,XI,&dx0,&dx1,dcx2);
2092 #else
2093 get_dx_dd(Nx,gridx,rl2,xgi,XI-grid_offset[XX],
2094 ncpddc[XX],sh0[XX],sh1[XX],&dx0,&dx1,dcx2);
2095 #endif
2096 if (dx0 > dx1)
2098 continue;
2100 /* Get shift vector */
2101 shift=XYZ2IS(tx,ty,tz);
2102 #ifdef NS5DB
2103 range_check(shift,0,SHIFTS);
2104 #endif
2105 for(nn=0; (nn<ngid); nn++)
2107 nsr[nn] = 0;
2108 nlr_ljc[nn] = 0;
2109 nlr_one[nn] = 0;
2111 #ifdef NS5DB
2112 fprintf(log,"shift: %2d, dx0,1: %2d,%2d, dy0,1: %2d,%2d, dz0,1: %2d,%2d\n",
2113 shift,dx0,dx1,dy0,dy1,dz0,dz1);
2114 fprintf(log,"cgcm: %8.3f %8.3f %8.3f\n",cgcm[icg][XX],
2115 cgcm[icg][YY],cgcm[icg][ZZ]);
2116 fprintf(log,"xi: %8.3f %8.3f %8.3f\n",XI,YI,ZI);
2117 #endif
2118 for (dx=dx0; (dx<=dx1); dx++)
2120 tmp1 = rl2 - dcx2[dx];
2121 for (dy=dy0; (dy<=dy1); dy++)
2123 tmp2 = tmp1 - dcy2[dy];
2124 if (tmp2 > 0)
2126 for (dz=dz0; (dz<=dz1); dz++) {
2127 if (tmp2 > dcz2[dz]) {
2128 /* Find grid-cell cj in which possible neighbours are */
2129 cj = xyz2ci(Ny,Nz,dx,dy,dz);
2131 /* Check out how many cgs (nrj) there in this cell */
2132 nrj = gridnra[cj];
2134 /* Find the offset in the cg list */
2135 cgj0 = gridind[cj];
2137 /* Check if all j's are out of range so we
2138 * can skip the whole cell.
2139 * Should save some time, especially with DD.
2141 if (nrj == 0 ||
2142 (grida[cgj0] >= max_jcg &&
2143 (grida[cgj0] >= jcg1 || grida[cgj0+nrj-1] < jcg0)))
2145 continue;
2148 /* Loop over cgs */
2149 for (j=0; (j<nrj); j++)
2151 jjcg = grida[cgj0+j];
2153 /* check whether this guy is in range! */
2154 if ((jjcg >= jcg0 && jjcg < jcg1) ||
2155 (jjcg < max_jcg))
2157 r2=calc_dx2(XI,YI,ZI,cgcm[jjcg]);
2158 if (r2 < rl2) {
2159 /* jgid = gid[cgsatoms[cgsindex[jjcg]]]; */
2160 jgid = GET_CGINFO_GID(cginfo[jjcg]);
2161 /* check energy group exclusions */
2162 if (!(i_egp_flags[jgid] & EGP_EXCL))
2164 if (r2 < rs2)
2166 if (nsr[jgid] >= MAX_CG)
2168 put_in_list(bHaveVdW,ngid,md,icg,jgid,
2169 nsr[jgid],nl_sr[jgid],
2170 cgs->index,/* cgsatoms, */ bexcl,
2171 shift,fr,FALSE,TRUE,TRUE,
2172 bMakeQMMMnblist);
2173 nsr[jgid]=0;
2175 nl_sr[jgid][nsr[jgid]++]=jjcg;
2177 else if (r2 < rm2)
2179 if (nlr_ljc[jgid] >= MAX_CG)
2181 do_longrange(cr,top,fr,ngid,md,icg,jgid,
2182 nlr_ljc[jgid],
2183 nl_lr_ljc[jgid],bexcl,shift,x,
2184 box_size,nrnb,
2185 lambda,dvdlambda,
2186 grppener,
2187 TRUE,TRUE,FALSE,
2188 bHaveVdW,
2189 bDoForces,f);
2190 nlr_ljc[jgid]=0;
2192 nl_lr_ljc[jgid][nlr_ljc[jgid]++]=jjcg;
2194 else
2196 if (nlr_one[jgid] >= MAX_CG) {
2197 do_longrange(cr,top,fr,ngid,md,icg,jgid,
2198 nlr_one[jgid],
2199 nl_lr_one[jgid],bexcl,shift,x,
2200 box_size,nrnb,
2201 lambda,dvdlambda,
2202 grppener,
2203 rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
2204 bHaveVdW,
2205 bDoForces,f);
2206 nlr_one[jgid]=0;
2208 nl_lr_one[jgid][nlr_one[jgid]++]=jjcg;
2212 nns++;
2220 /* CHECK whether there is anything left in the buffers */
2221 for(nn=0; (nn<ngid); nn++)
2223 if (nsr[nn] > 0)
2225 put_in_list(bHaveVdW,ngid,md,icg,nn,nsr[nn],nl_sr[nn],
2226 cgs->index, /* cgsatoms, */ bexcl,
2227 shift,fr,FALSE,TRUE,TRUE,bMakeQMMMnblist);
2230 if (nlr_ljc[nn] > 0)
2232 do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_ljc[nn],
2233 nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
2234 lambda,dvdlambda,grppener,TRUE,TRUE,FALSE,
2235 bHaveVdW,bDoForces,f);
2238 if (nlr_one[nn] > 0)
2240 do_longrange(cr,top,fr,ngid,md,icg,nn,nlr_one[nn],
2241 nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
2242 lambda,dvdlambda,grppener,
2243 rvdw_lt_rcoul,rcoul_lt_rvdw,FALSE,
2244 bHaveVdW,bDoForces,f);
2250 /* setexcl(nri,i_atoms,&top->atoms.excl,FALSE,bexcl); */
2251 setexcl(cgs->index[icg],cgs->index[icg+1],&top->excls,FALSE,bexcl);
2253 /* Perform any left over force calculations */
2254 for (nn=0; (nn<ngid); nn++)
2256 if (rm2 > rs2)
2258 do_longrange(cr,top,fr,0,md,icg,nn,nlr_ljc[nn],
2259 nl_lr_ljc[nn],bexcl,shift,x,box_size,nrnb,
2260 lambda,dvdlambda,grppener,
2261 TRUE,TRUE,TRUE,bHaveVdW,bDoForces,f);
2263 if (rl2 > rm2) {
2264 do_longrange(cr,top,fr,0,md,icg,nn,nlr_one[nn],
2265 nl_lr_one[nn],bexcl,shift,x,box_size,nrnb,
2266 lambda,dvdlambda,grppener,
2267 rvdw_lt_rcoul,rcoul_lt_rvdw,
2268 TRUE,bHaveVdW,bDoForces,f);
2271 debug_gmx();
2273 /* Close off short range neighbourlists */
2274 close_neighbor_list(fr,FALSE,-1,-1,bMakeQMMMnblist);
2276 return nns;
2279 void ns_realloc_natoms(gmx_ns_t *ns,int natoms)
2281 int i;
2283 if (natoms > ns->nra_alloc)
2285 ns->nra_alloc = over_alloc_dd(natoms);
2286 srenew(ns->bexcl,ns->nra_alloc);
2287 for(i=0; i<ns->nra_alloc; i++)
2289 ns->bexcl[i] = 0;
2294 void init_ns(FILE *fplog,const t_commrec *cr,
2295 gmx_ns_t *ns,t_forcerec *fr,
2296 const gmx_mtop_t *mtop,
2297 matrix box)
2299 int mt,icg,nr_in_cg,maxcg,i,j,jcg,ngid,ncg;
2300 t_block *cgs;
2301 char *ptr;
2303 /* Compute largest charge groups size (# atoms) */
2304 nr_in_cg=1;
2305 for(mt=0; mt<mtop->nmoltype; mt++) {
2306 cgs = &mtop->moltype[mt].cgs;
2307 for (icg=0; (icg < cgs->nr); icg++)
2309 nr_in_cg=max(nr_in_cg,(int)(cgs->index[icg+1]-cgs->index[icg]));
2313 /* Verify whether largest charge group is <= max cg.
2314 * This is determined by the type of the local exclusion type
2315 * Exclusions are stored in bits. (If the type is not large
2316 * enough, enlarge it, unsigned char -> unsigned short -> unsigned long)
2318 maxcg = sizeof(t_excl)*8;
2319 if (nr_in_cg > maxcg)
2321 gmx_fatal(FARGS,"Max #atoms in a charge group: %d > %d\n",
2322 nr_in_cg,maxcg);
2325 ngid = mtop->groups.grps[egcENER].nr;
2326 snew(ns->bExcludeAlleg,ngid);
2327 for(i=0; i<ngid; i++) {
2328 ns->bExcludeAlleg[i] = TRUE;
2329 for(j=0; j<ngid; j++)
2331 if (!(fr->egp_flags[i*ngid+j] & EGP_EXCL))
2333 ns->bExcludeAlleg[i] = FALSE;
2338 if (fr->bGrid) {
2339 /* Grid search */
2340 ns->grid = init_grid(fplog,fr);
2341 /* These lists are allocated in ns5_core */
2342 ns->nl_sr = NULL;
2344 else
2346 /* Simple search */
2347 snew(ns->ns_buf,ngid);
2348 for(i=0; (i<ngid); i++)
2350 snew(ns->ns_buf[i],SHIFTS);
2352 ncg = ncg_mtop(mtop);
2353 snew(ns->simple_aaj,2*ncg);
2354 for(jcg=0; (jcg<ncg); jcg++)
2356 ns->simple_aaj[jcg] = jcg;
2357 ns->simple_aaj[jcg+ncg] = jcg;
2361 /* Create array that determines whether or not atoms have VdW */
2362 snew(ns->bHaveVdW,fr->ntype);
2363 for(i=0; (i<fr->ntype); i++)
2365 for(j=0; (j<fr->ntype); j++)
2367 ns->bHaveVdW[i] = (ns->bHaveVdW[i] ||
2368 (fr->bBHAM ?
2369 ((BHAMA(fr->nbfp,fr->ntype,i,j) != 0) ||
2370 (BHAMB(fr->nbfp,fr->ntype,i,j) != 0) ||
2371 (BHAMC(fr->nbfp,fr->ntype,i,j) != 0)) :
2372 ((C6(fr->nbfp,fr->ntype,i,j) != 0) ||
2373 (C12(fr->nbfp,fr->ntype,i,j) != 0))));
2376 if (debug)
2377 pr_bvec(debug,0,"bHaveVdW",ns->bHaveVdW,fr->ntype,TRUE);
2379 if (!DOMAINDECOMP(cr))
2381 /* This could be reduced with particle decomposition */
2382 ns_realloc_natoms(ns,mtop->natoms);
2385 ns->nblist_initialized=FALSE;
2387 /* nbr list debug dump */
2389 char *ptr=getenv("GMX_DUMP_NL");
2390 if (ptr)
2392 ns->dump_nl=strtol(ptr,NULL,0);
2393 if (fplog)
2395 fprintf(fplog, "GMX_DUMP_NL = %d", ns->dump_nl);
2398 else
2400 ns->dump_nl=0;
2406 int search_neighbours(FILE *log,t_forcerec *fr,
2407 rvec x[],matrix box,
2408 gmx_localtop_t *top,
2409 gmx_groups_t *groups,
2410 t_commrec *cr,
2411 t_nrnb *nrnb,t_mdatoms *md,
2412 real lambda,real *dvdlambda,
2413 gmx_grppairener_t *grppener,
2414 bool bFillGrid,
2415 bool bDoLongRange,
2416 bool bDoForces,rvec *f)
2418 t_block *cgs=&(top->cgs);
2419 rvec box_size,grid_x0,grid_x1;
2420 int i,j,m,ngid;
2421 real min_size,grid_dens;
2422 int nsearch;
2423 bool bGrid;
2424 char *ptr;
2425 bool *i_egp_flags;
2426 int cg_start,cg_end,start,end;
2427 gmx_ns_t *ns;
2428 t_grid *grid;
2429 gmx_domdec_zones_t *dd_zones;
2431 ns = &fr->ns;
2433 /* Set some local variables */
2434 bGrid = fr->bGrid;
2435 ngid = groups->grps[egcENER].nr;
2437 for(m=0; (m<DIM); m++)
2439 box_size[m] = box[m][m];
2442 if (fr->ePBC != epbcNONE)
2444 if (sqr(fr->rlistlong) >= max_cutoff2(fr->ePBC,box))
2446 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.");
2448 if (!bGrid)
2450 min_size = min(box_size[XX],min(box_size[YY],box_size[ZZ]));
2451 if (2*fr->rlistlong >= min_size)
2452 gmx_fatal(FARGS,"One of the box diagonal elements has become smaller than twice the cut-off length.");
2456 if (DOMAINDECOMP(cr))
2458 ns_realloc_natoms(ns,cgs->index[cgs->nr]);
2460 debug_gmx();
2462 /* Reset the neighbourlists */
2463 reset_neighbor_list(fr,FALSE,-1,-1);
2465 if (bGrid && bFillGrid)
2468 grid = ns->grid;
2469 if (DOMAINDECOMP(cr))
2471 dd_zones = domdec_zones(cr->dd);
2473 else
2475 dd_zones = NULL;
2477 get_nsgrid_boundaries(grid,NULL,box,NULL,NULL,NULL,
2478 cgs->nr,fr->cg_cm,grid_x0,grid_x1,&grid_dens);
2480 grid_first(log,grid,NULL,NULL,fr->ePBC,box,grid_x0,grid_x1,
2481 fr->rlistlong,grid_dens);
2483 debug_gmx();
2485 /* Don't know why this all is... (DvdS 3/99) */
2486 #ifndef SEGV
2487 start = 0;
2488 end = cgs->nr;
2489 #else
2490 start = fr->cg0;
2491 end = (cgs->nr+1)/2;
2492 #endif
2494 if (DOMAINDECOMP(cr))
2496 end = cgs->nr;
2497 fill_grid(log,dd_zones,grid,end,-1,end,fr->cg_cm);
2498 grid->icg0 = 0;
2499 grid->icg1 = dd_zones->izone[dd_zones->nizone-1].cg1;
2501 else
2503 fill_grid(log,NULL,grid,cgs->nr,fr->cg0,fr->hcg,fr->cg_cm);
2504 grid->icg0 = fr->cg0;
2505 grid->icg1 = fr->hcg;
2506 debug_gmx();
2508 if (PARTDECOMP(cr))
2509 mv_grid(cr,grid);
2510 debug_gmx();
2513 calc_elemnr(log,grid,start,end,cgs->nr);
2514 calc_ptrs(grid);
2515 grid_last(log,grid,start,end,cgs->nr);
2517 if (gmx_debug_at)
2519 check_grid(debug,grid);
2520 print_grid(debug,grid);
2523 else if (fr->n_tpi)
2525 /* Set the grid cell index for the test particle only.
2526 * The cell to cg index is not corrected, but that does not matter.
2528 fill_grid(log,NULL,ns->grid,fr->hcg,fr->hcg-1,fr->hcg,fr->cg_cm);
2530 debug_gmx();
2532 /* Do the core! */
2533 if (bGrid)
2535 grid = ns->grid;
2536 nsearch = nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2537 grid,x,ns->bexcl,ns->bExcludeAlleg,
2538 nrnb,md,lambda,dvdlambda,grppener,
2539 ns->bHaveVdW,
2540 bDoLongRange,bDoForces,f,
2541 FALSE);
2543 /* neighbour searching withouth QMMM! QM atoms have zero charge in
2544 * the classical calculation. The charge-charge interaction
2545 * between QM and MM atoms is handled in the QMMM core calculation
2546 * (see QMMM.c). The VDW however, we'd like to compute classically
2547 * and the QM MM atom pairs have just been put in the
2548 * corresponding neighbourlists. in case of QMMM we still need to
2549 * fill a special QMMM neighbourlist that contains all neighbours
2550 * of the QM atoms. If bQMMM is true, this list will now be made:
2552 if (fr->bQMMM && fr->qr->QMMMscheme!=eQMMMschemeoniom)
2554 nsearch += nsgrid_core(log,cr,fr,box,box_size,ngid,top,
2555 grid,x,ns->bexcl,ns->bExcludeAlleg,
2556 nrnb,md,lambda,dvdlambda,grppener,
2557 ns->bHaveVdW,
2558 bDoLongRange,bDoForces,f,
2559 TRUE);
2562 else
2564 nsearch = ns_simple_core(fr,top,md,box,box_size,
2565 ns->bexcl,ns->simple_aaj,
2566 ngid,ns->ns_buf,ns->bHaveVdW);
2568 debug_gmx();
2570 #ifdef DEBUG
2571 pr_nsblock(log);
2572 #endif
2574 inc_nrnb(nrnb,eNR_NS,nsearch);
2575 /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
2577 return nsearch;
2580 int natoms_beyond_ns_buffer(t_inputrec *ir,t_forcerec *fr,t_block *cgs,
2581 matrix scale_tot,rvec *x)
2583 int cg0,cg1,cg,a0,a1,a,i,j;
2584 real rint,hbuf2,scale;
2585 rvec *cg_cm,cgsc;
2586 bool bIsotropic;
2587 int nBeyond;
2589 nBeyond = 0;
2591 rint = max(ir->rcoulomb,ir->rvdw);
2592 if (ir->rlist < rint)
2594 gmx_fatal(FARGS,"The neighbor search buffer has negative size: %f nm",
2595 ir->rlist - rint);
2597 cg_cm = fr->cg_cm;
2599 cg0 = fr->cg0;
2600 cg1 = fr->hcg;
2602 if (!EI_DYNAMICS(ir->eI) || !DYNAMIC_BOX(*ir))
2604 hbuf2 = sqr(0.5*(ir->rlist - rint));
2605 for(cg=cg0; cg<cg1; cg++)
2607 a0 = cgs->index[cg];
2608 a1 = cgs->index[cg+1];
2609 for(a=a0; a<a1; a++)
2611 if (distance2(cg_cm[cg],x[a]) > hbuf2)
2613 nBeyond++;
2618 else
2620 bIsotropic = TRUE;
2621 scale = scale_tot[0][0];
2622 for(i=1; i<DIM; i++)
2624 /* With anisotropic scaling, the original spherical ns volumes become
2625 * ellipsoids. To avoid costly transformations we use the minimum
2626 * eigenvalue of the scaling matrix for determining the buffer size.
2627 * Since the lower half is 0, the eigenvalues are the diagonal elements.
2629 scale = min(scale,scale_tot[i][i]);
2630 if (scale_tot[i][i] != scale_tot[i-1][i-1])
2632 bIsotropic = FALSE;
2634 for(j=0; j<i; j++)
2636 if (scale_tot[i][j] != 0)
2638 bIsotropic = FALSE;
2642 hbuf2 = sqr(0.5*(scale*ir->rlist - rint));
2643 if (bIsotropic)
2645 for(cg=cg0; cg<cg1; cg++)
2647 svmul(scale,cg_cm[cg],cgsc);
2648 a0 = cgs->index[cg];
2649 a1 = cgs->index[cg+1];
2650 for(a=a0; a<a1; a++)
2652 if (distance2(cgsc,x[a]) > hbuf2)
2654 nBeyond++;
2659 else
2661 /* Anistropic scaling */
2662 for(cg=cg0; cg<cg1; cg++)
2664 /* Since scale_tot contains the transpose of the scaling matrix,
2665 * we need to multiply with the transpose.
2667 tmvmul_ur0(scale_tot,cg_cm[cg],cgsc);
2668 a0 = cgs->index[cg];
2669 a1 = cgs->index[cg+1];
2670 for(a=a0; a<a1; a++)
2672 if (distance2(cgsc,x[a]) > hbuf2)
2674 nBeyond++;
2681 return nBeyond;