1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
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
34 * GROwing Monsters And Cloning Shrimps
40 #ifdef GMX_THREAD_SHM_FDECOMP
54 #include "nonbonded.h"
58 #include "gmx_fatal.h"
61 #include "mtop_util.h"
68 * E X C L U S I O N H A N D L I N G
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
)); }
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))
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
)
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
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
,
134 gmx_bool bfree
, int enlist
)
166 nl
= (i
== 0) ? nl_sr
: nl_lr
;
167 homenr
= (i
== 0) ? maxsr
: maxlr
;
174 /* Set coul/vdw in neighborlist, and for the normal loops we determine
175 * an index of which one to call.
179 nl
->free_energy
= bfree
;
183 nl
->enlist
= enlistATOM_ATOM
;
184 nl
->il_code
= eNR_NBKERNEL_FREE_ENERGY
;
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
199 case enlistATOM_ATOM
:
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;
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;
230 reallocate_nblist(nl
);
232 #ifdef GMX_THREAD_SHM_FDECOMP
235 pthread_mutex_init(nl
->mtx
,NULL
);
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
247 int maxsr
,maxsr_wat
,maxlr
,maxlr_wat
;
248 int icoul
,icoulf
,ivdw
;
250 int enlist_def
,enlist_w
,enlist_ww
;
254 /* maxsr = homenr-fr->nWatMol*3; */
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);
270 maxlr_wat
= min(maxsr_wat
,maxlr
);
274 maxlr
= maxlr_wat
= 0;
277 /* Determine the values for icoul/ivdw. */
283 else if (fr
->bcoultab
)
287 else if (EEL_RF(fr
->eeltype
))
309 fr
->ns
.bCGlist
= (getenv("GMX_NBLISTCG") != 0);
312 enlist_def
= enlistATOM_ATOM
;
316 enlist_def
= enlistCG_CG
;
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
;
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
)
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
);
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
)
393 static void reset_neighbor_list(t_forcerec
*fr
,gmx_bool bLR
,int nls
,int eNL
)
399 reset_nblist(&(fr
->nblists
[nls
].nlist_lr
[eNL
]));
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
]));
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
)
428 /* Check whether we have to increase the i counter */
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.
438 ((nlist
->jindex
[nri
+1] > nlist
->jindex
[nri
]) &&
439 (nlist
->gid
[nri
] != -1)))
441 /* If so increase the counter */
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
;
465 nlist
->jindex
[nri
+1] = nlist
->nrj
;
467 len
=nlist
->nrj
- nlist
->jindex
[nri
];
469 /* nlist length for water i molecules is treated statically
472 if (len
> nlist
->maxlen
)
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.
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
496 /* Close list number nri by incrementing the count */
501 static inline void close_neighbor_list(t_forcerec
*fr
,gmx_bool bLR
,int nls
,int eNL
,
502 gmx_bool bMakeQMMMnblist
)
506 if (bMakeQMMMnblist
) {
509 close_nblist(&(fr
->QMMMlist
));
516 close_nblist(&(fr
->nblists
[nls
].nlist_lr
[eNL
]));
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
)
535 if (nlist
->nrj
>= nlist
->maxnrj
)
537 nlist
->maxnrj
= over_alloc_small(nlist
->nrj
+ 1);
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
;
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
)
556 if (nlist
->nrj
>= nlist
->maxnrj
)
558 nlist
->maxnrj
= over_alloc_small(nlist
->nrj
+ 1);
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
];
586 put_in_list_t(gmx_bool bHaveVdW
[],
602 put_in_list_at(gmx_bool bHaveVdW
[],
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].
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
;
635 real
*charge
,*chargeB
;
637 gmx_bool bFreeEnergy
,bFree
,bFreeJ
,bNotEx
,*bPert
;
638 gmx_bool bDoVdW_i
,bDoCoul_i
,bDoCoul_i_sol
;
642 /* Copy some pointers */
644 charge
= md
->chargeA
;
645 chargeB
= md
->chargeB
;
648 bPert
= md
->bPerturbed
;
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
]);
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
++)
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)
690 nbl_ind
= fr
->gid2nblists
[GID(igid
,jgid
,ngid
)];
694 nlist
= fr
->nblists
[nbl_ind
].nlist_lr
;
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
];
713 vdwc
= &nlist
[eNL_VDWQQ
];
714 vdw
= &nlist
[eNL_VDW
];
715 coul
= &nlist
[eNL_QQ
];
720 if (iwater
!= esolNO
)
722 /* Loop over the atoms in the i charge group */
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
);
735 new_i_nblist(vdw
,bLR
,i_atom
,shift
,gid
);
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
);
744 /* Loop over the j charge groups */
745 for(j
=0; (j
<nj
); j
++)
755 jwater
= GET_CGINFO_SOLOPT(cginfo
[jcg
]);
757 if (iwater
== esolSPC
&& jwater
== esolSPC
)
759 /* Interaction between two SPC molecules */
762 /* VdW only - only first atoms in each water interact */
763 add_j_to_nblist(vdw
,jj0
,bLR
);
767 #ifdef DISABLE_WATERWATER_NLIST
768 /* Add entries for the three atoms - only do VdW if we need to */
771 add_j_to_nblist(coul
,jj0
,bLR
);
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
);
780 /* One entry for the entire water-water interaction */
783 add_j_to_nblist(coul_ww
,jj0
,bLR
);
787 add_j_to_nblist(vdwc_ww
,jj0
,bLR
);
792 else if (iwater
== esolTIP4P
&& jwater
== esolTIP4P
)
794 /* Interaction between two TIP4p molecules */
797 /* VdW only - only first atoms in each water interact */
798 add_j_to_nblist(vdw
,jj0
,bLR
);
802 #ifdef DISABLE_WATERWATER_NLIST
803 /* Add entries for the four atoms - only do VdW if we need to */
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
);
812 /* One entry for the entire water-water interaction */
815 add_j_to_nblist(coul_ww
,jj0
,bLR
);
819 add_j_to_nblist(vdwc_ww
,jj0
,bLR
);
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...
836 for(jj
=jj0
; (jj
<jj1
); jj
++)
840 add_j_to_nblist(coul
,jj
,bLR
);
846 for(jj
=jj0
; (jj
<jj1
); jj
++)
848 if (bHaveVdW
[type
[jj
]])
850 add_j_to_nblist(vdw
,jj
,bLR
);
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
]])
864 add_j_to_nblist(vdwc
,jj
,bLR
);
868 add_j_to_nblist(vdw
,jj
,bLR
);
871 else if (charge
[jj
] != 0)
873 add_j_to_nblist(coul
,jj
,bLR
);
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
);
889 /* no solvent as i charge group */
890 /* Loop over the atoms in the i charge group */
891 for(i
=0; i
<nicg
; i
++)
894 gid
= GID(igid
,jgid
,ngid
);
897 /* Create new i_atom for each energy group */
898 if (bDoVdW
&& bDoCoul
)
900 new_i_nblist(vdwc
,bLR
,i_atom
,shift
,gid
);
904 new_i_nblist(vdw
,bLR
,i_atom
,shift
,gid
);
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
++)
920 /* Check for large charge groups */
931 /* Finally loop over the atoms in the j-charge group */
932 for(jj
=jj0
; jj
<jj1
; jj
++)
934 bNotEx
= NOTEXCL(bExcl
,i
,jj
);
942 add_j_to_nblist(coul
,jj
,bLR
);
947 if (bHaveVdW
[type
[jj
]])
949 add_j_to_nblist(vdw
,jj
,bLR
);
954 if (bHaveVdW
[type
[jj
]])
958 add_j_to_nblist(vdwc
,jj
,bLR
);
962 add_j_to_nblist(vdw
,jj
,bLR
);
965 else if (charge
[jj
] != 0)
967 add_j_to_nblist(coul
,jj
,bLR
);
975 close_i_nblist(coul
);
976 close_i_nblist(vdwc
);
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
++)
990 gid
= GID(igid
,jgid
,ngid
);
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
);
998 new_i_nblist(vdw
,bLR
,i_atom
,shift
,gid
);
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
;
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
++)
1032 /* Check for large charge groups */
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
);
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
);
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
);
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
);
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
);
1107 if (bHaveVdW
[type
[jj
]])
1109 if (charge
[jj
] != 0)
1111 add_j_to_nblist(vdwc
,jj
,bLR
);
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
);
1139 put_in_list_qmmm(gmx_bool bHaveVdW
[],
1155 int i
,j
,jcg
,igid
,gid
;
1156 atom_id jj
,jj0
,jj1
,i_atom
;
1160 /* Get atom range */
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
++)
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 */
1182 /* Charge groups cannot have QM and MM atoms simultaneously */
1187 /* Finally loop over the atoms in the j-charge group */
1188 for(jj
=jj0
; jj
<jj1
; jj
++)
1190 bNotEx
= NOTEXCL(bExcl
,i
,jj
);
1192 add_j_to_nblist(coul
,jj
,bLR
);
1196 close_i_nblist(coul
);
1201 put_in_list_cg(gmx_bool bHaveVdW
[],
1217 int igid
,gid
,nbl_ind
;
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)
1233 nbl_ind
= fr
->gid2nblists
[gid
];
1237 vdwc
= &fr
->nblists
[nbl_ind
].nlist_lr
[eNL_VDWQQ
];
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
++)
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
,
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
]);
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
)
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 */
1343 fprintf(log
,"naaj=%d\n",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.
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
;
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
;
1382 dy
-= ty
*box
[YY
][YY
];
1383 dx
-= ty
*box
[YY
][XX
];
1385 tx
= dx
*b_inv
[XX
]+h25
;
1387 dx
-= tx
*box
[XX
][XX
];
1389 /* Distance squared */
1390 r2
= (dx
*dx
) + (dy
*dy
) + (dz
*dz
);
1392 *shift
= XYZ2IS(tx
,ty
,tz
);
1397 static real
calc_image_rect(rvec xi
,rvec xj
,rvec box_size
,
1398 rvec b_inv
,int *shift
)
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
;
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
);
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
;
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
)
1460 int *cginfo
=fr
->cginfo
;
1461 atom_id cg_j
,*cgindex
;
1464 cgindex
= cgs
->index
;
1466 for(j
=0; (j
<njcg
); 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
,
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
)
1493 int *cginfo
=fr
->cginfo
;
1494 atom_id cg_j
,*cgindex
;
1497 cgindex
= cgs
->index
;
1501 for(j
=0; (j
<njcg
); 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
,
1519 for(j
=0; (j
<njcg
); 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
,
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
,
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
[])
1548 int nsearch
,icg
,jcg
,igid
,i0
,nri
,nn
;
1551 /* atom_id *i_atoms; */
1552 t_block
*cgs
=&(top
->cgs
);
1553 t_blocka
*excl
=&(top
->excls
);
1556 gmx_bool bBox
,bTriclinic
;
1559 rlist2
= sqr(fr
->rlist
);
1561 bBox
= (fr
->ePBC
!= epbcNONE
);
1564 for(m
=0; (m
<DIM
); m
++)
1566 b_inv
[m
] = divide_err(1.0,box_size
[m
]);
1568 bTriclinic
= TRICLINIC(box
);
1575 cginfo
= fr
->cginfo
;
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
);
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
);
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
);
1606 for(nn
=0; (nn
<ngid
); nn
++)
1608 for(k
=0; (k
<SHIFTS
); k
++)
1610 nsbuf
= &(ns_buf
[nn
][k
]);
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
);
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
)
1662 for(i
=xgi0
; i
>=0; i
--)
1664 dcx
= (i
+1)*gridx
-x
;
1671 for(i
=xgi1
; i
<Nx
; i
++)
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
)
1689 int g_min
,g_max
,shift_home
;
1722 g_min
= (shift_min
== shift_home
? 0 : ncpddc
);
1723 g_max
= (shift_max
== shift_home
? ncpddc
- 1 : Nx
- 1);
1730 else if (shift_max
< 0)
1745 /* Check one grid cell down */
1746 dcx
= ((*g0
- 1) + 1)*gridx
- x
;
1758 /* Check one grid cell up */
1759 dcx
= (*g1
+ 1)*gridx
- x
;
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
,
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
)
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
);
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
);
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
);
1854 *rcoul2
= sqr(fr
->rcoulomb
);
1859 /* Workaround for a gcc -O3 or -ffast-math problem */
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
;
1872 get_cutoff2(fr
,TRUE
,&rvdw2
,&rcoul2
,&rs2
,&rm2
,&rl2
);
1874 /* Short range buffers */
1875 snew(ns
->nl_sr
,ngid
);
1878 snew(ns
->nlr_ljc
,ngid
);
1879 snew(ns
->nlr_one
,ngid
);
1883 /* Long range VdW and Coul buffers */
1884 snew(ns
->nl_lr_ljc
,ngid
);
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
);
1895 snew(ns
->nl_lr_ljc
[j
],MAX_CG
);
1899 snew(ns
->nl_lr_one
[j
],MAX_CG
);
1905 "ns5_core: rs2 = %g, rm2 = %g, rl2 = %g (nm^2)\n",
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
)
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; */
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
;
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
;
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
;
1948 gmx_bool bDomDec
,bTriclinicX
,bTriclinicY
;
1953 bDomDec
= DOMAINDECOMP(cr
);
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);
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
)
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
;
1992 gridind
= grid
->index
;
1993 gridnra
= grid
->nra
;
1996 gridx
= grid
->cell_size
[XX
];
1997 gridy
= grid
->cell_size
[YY
];
1998 gridz
= grid
->cell_size
[ZZ
];
2002 copy_rvec(grid
->cell_offset
,grid_offset
);
2003 copy_ivec(grid
->ncpddc
,ncpddc
);
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 */
2023 /* We only want a list for the test particle */
2032 /* Set the shift range */
2033 for(d
=0; d
<DIM
; d
++)
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))
2047 box
[XX
][XX
] - fabs(box
[YY
][XX
]) - fabs(box
[ZZ
][XX
]) < sqrt(rl2
))
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
])
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
2083 naaj
= calc_naaj(icg
,cgsnr
);
2090 /* make a normal neighbourlist */
2094 /* Get the j charge-group and dd cell shift ranges */
2095 dd_get_ns_ranges(cr
->dd
,icg
,&jcg0
,&jcg1
,sh0
,sh1
);
2100 /* Compute the number of charge groups that fall within the control
2103 naaj
= calc_naaj(icg
,cgsnr
);
2109 /* The i-particle is awlways the test particle,
2110 * so we want all j-particles
2112 max_jcg
= cgsnr
- 1;
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)
2132 fprintf(log
,"icg=%5d, naaj=%5d, cell %d %d %d\n",
2133 icg
,naaj
,cell_x
,cell_y
,cell_z
);
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
;
2143 get_dx(Nz
,gridz
,rl2
,zgi
,ZI
,&dz0
,&dz1
,dcz2
);
2145 get_dx_dd(Nz
,gridz
,rl2
,zgi
,ZI
-grid_offset
[ZZ
],
2146 ncpddc
[ZZ
],sh0
[ZZ
],sh1
[ZZ
],&dz0
,&dz1
,dcz2
);
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 */
2158 ygi
= (int)(Ny
+ (YI
- grid_offset
[YY
])*grid_y
) - Ny
;
2162 ygi
= cell_y
+ ty
*Ny
;
2165 get_dx(Ny
,gridy
,rl2
,ygi
,YI
,&dy0
,&dy1
,dcy2
);
2167 get_dx_dd(Ny
,gridy
,rl2
,ygi
,YI
-grid_offset
[YY
],
2168 ncpddc
[YY
],sh0
[YY
],sh1
[YY
],&dy0
,&dy1
,dcy2
);
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 */
2180 xgi
= (int)(Nx
+ (XI
- grid_offset
[XX
])*grid_x
) - Nx
;
2184 xgi
= cell_x
+ tx
*Nx
;
2187 get_dx(Nx
,gridx
,rl2
,xgi
*Nx
,XI
,&dx0
,&dx1
,dcx2
);
2189 get_dx_dd(Nx
,gridx
,rl2
,xgi
,XI
-grid_offset
[XX
],
2190 ncpddc
[XX
],sh0
[XX
],sh1
[XX
],&dx0
,&dx1
,dcx2
);
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
)){
2203 /* Get shift vector */
2204 shift
=XYZ2IS(tx
,ty
,tz
);
2206 range_check(shift
,0,SHIFTS
);
2208 for(nn
=0; (nn
<ngid
); nn
++)
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
);
2221 for (dx
=dx0
; (dx
<=dx1
); dx
++)
2223 tmp1
= rl2
- dcx2
[dx
];
2224 for (dy
=dy0
; (dy
<=dy1
); dy
++)
2226 tmp2
= tmp1
- dcy2
[dy
];
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 */
2237 /* Find the offset in the cg list */
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.
2245 (grida
[cgj0
] >= max_jcg
&&
2246 (grida
[cgj0
] >= jcg1
|| grida
[cgj0
+nrj
-1] < jcg0
)))
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
) ||
2260 r2
=calc_dx2(XI
,YI
,ZI
,cgcm
[jjcg
]);
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
))
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
);
2277 nl_sr
[jgid
][nsr
[jgid
]++]=jjcg
;
2281 if (nlr_ljc
[jgid
] >= MAX_CG
)
2283 do_longrange(cr
,top
,fr
,ngid
,md
,icg
,jgid
,
2285 nl_lr_ljc
[jgid
],bexcl
,shift
,x
,
2295 nl_lr_ljc
[jgid
][nlr_ljc
[jgid
]++]=jjcg
;
2299 if (nlr_one
[jgid
] >= MAX_CG
) {
2300 do_longrange(cr
,top
,fr
,ngid
,md
,icg
,jgid
,
2302 nl_lr_one
[jgid
],bexcl
,shift
,x
,
2306 rvdw_lt_rcoul
,rcoul_lt_rvdw
,FALSE
,
2312 nl_lr_one
[jgid
][nlr_one
[jgid
]++]=jjcg
;
2324 /* CHECK whether there is anything left in the buffers */
2325 for(nn
=0; (nn
<ngid
); nn
++)
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
++)
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
);
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
);
2377 /* Close off short range neighbourlists */
2378 close_neighbor_list(fr
,FALSE
,-1,-1,bMakeQMMMnblist
);
2383 void ns_realloc_natoms(gmx_ns_t
*ns
,int natoms
)
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
++)
2398 void init_ns(FILE *fplog
,const t_commrec
*cr
,
2399 gmx_ns_t
*ns
,t_forcerec
*fr
,
2400 const gmx_mtop_t
*mtop
,
2403 int mt
,icg
,nr_in_cg
,maxcg
,i
,j
,jcg
,ngid
,ncg
;
2407 /* Compute largest charge groups size (# atoms) */
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",
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
;
2444 ns
->grid
= init_grid(fplog
,fr
);
2445 init_nsgrid_lists(fr
,ngid
,ns
);
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
] ||
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))));
2480 pr_bvec(debug
,0,"bHaveVdW",ns
->bHaveVdW
,fr
->ntype
,TRUE
);
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");
2497 ns
->dump_nl
=strtol(ptr
,NULL
,10);
2500 fprintf(fplog
, "GMX_DUMP_NL = %d", ns
->dump_nl
);
2511 int search_neighbours(FILE *log
,t_forcerec
*fr
,
2512 rvec x
[],matrix box
,
2513 gmx_localtop_t
*top
,
2514 gmx_groups_t
*groups
,
2516 t_nrnb
*nrnb
,t_mdatoms
*md
,
2517 real lambda
,real
*dvdlambda
,
2518 gmx_grppairener_t
*grppener
,
2520 gmx_bool bDoLongRange
,
2521 gmx_bool bDoForces
,rvec
*f
)
2523 t_block
*cgs
=&(top
->cgs
);
2524 rvec box_size
,grid_x0
,grid_x1
;
2526 real min_size
,grid_dens
;
2530 gmx_bool
*i_egp_flags
;
2531 int cg_start
,cg_end
,start
,end
;
2534 gmx_domdec_zones_t
*dd_zones
;
2535 put_in_list_t
*put_in_list
;
2539 /* Set some local variables */
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.");
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
]);
2568 /* Reset the neighbourlists */
2569 reset_neighbor_list(fr
,FALSE
,-1,-1);
2571 if (bGrid
&& bFillGrid
)
2575 if (DOMAINDECOMP(cr
))
2577 dd_zones
= domdec_zones(cr
->dd
);
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
);
2591 /* Don't know why this all is... (DvdS 3/99) */
2597 end
= (cgs
->nr
+1)/2;
2600 if (DOMAINDECOMP(cr
))
2603 fill_grid(log
,dd_zones
,grid
,end
,-1,end
,fr
->cg_cm
);
2605 grid
->icg1
= dd_zones
->izone
[dd_zones
->nizone
-1].cg1
;
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
;
2619 calc_elemnr(log
,grid
,start
,end
,cgs
->nr
);
2621 grid_last(log
,grid
,start
,end
,cgs
->nr
);
2625 check_grid(debug
,grid
);
2626 print_grid(debug
,grid
);
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
);
2638 if (!fr
->ns
.bCGlist
)
2640 put_in_list
= put_in_list_at
;
2644 put_in_list
= put_in_list_cg
;
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
,
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
,
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
);
2689 inc_nrnb(nrnb
,eNR_NS
,nsearch
);
2690 /* inc_nrnb(nrnb,eNR_LR,fr->nlr); */
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
;
2701 gmx_bool bIsotropic
;
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",
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
)
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])
2751 if (scale_tot
[i
][j
] != 0)
2757 hbuf2
= sqr(0.5*(scale
*ir
->rlist
- rint
));
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
)
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
)