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 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
36 /* This file is completely threadsafe - keep it that way! */
48 int bond_sort (const void *a
, const void *b
)
56 return (sa
->aj
-sb
->aj
);
58 return (sa
->ai
-sb
->ai
);
62 #define prints(str, n, s) __prints(str, n, s)
63 static void __prints(char *str
, int n
, sortable
*s
)
68 fprintf(debug
,"%s\n",str
);
69 fprintf(debug
,"Sortables \n");
70 for (i
=0; (i
< n
); i
++)
71 fprintf(debug
,"%d\t%d\n",s
[i
].ai
,s
[i
].aj
);
77 #define prints(str, n, s)
80 void init_nnb(t_nextnb
*nnb
, int nr
, int nrex
)
90 for (i
=0; (i
< nr
); i
++) {
91 snew(nnb
->a
[i
],nrex
+1);
92 snew(nnb
->nrexcl
[i
],nrex
+1);
96 static void add_nnb (t_nextnb
*nnb
, int nre
, int i
, int j
)
98 srenew(nnb
->a
[i
][nre
],nnb
->nrexcl
[i
][nre
]+1);
99 nnb
->a
[i
][nre
][nnb
->nrexcl
[i
][nre
]] = j
;
100 nnb
->nrexcl
[i
][nre
]++;
103 void done_nnb (t_nextnb
*nnb
)
107 for (i
=0; (i
< nnb
->nr
); i
++) {
108 for (nre
=0; (nre
<= nnb
->nrex
); nre
++)
109 if (nnb
->nrexcl
[i
][nre
] > 0)
110 sfree (nnb
->a
[i
][nre
]);
111 sfree (nnb
->nrexcl
[i
]);
121 void __print_nnb(t_nextnb
*nnb
, char *s
)
126 fprintf(debug
,"%s\n",s
);
127 fprintf(debug
,"nnb->nr: %d\n",nnb
->nr
);
128 fprintf(debug
,"nnb->nrex: %d\n",nnb
->nrex
);
129 for(i
=0; (i
<nnb
->nr
); i
++)
130 for(j
=0; (j
<=nnb
->nrex
); j
++) {
131 fprintf(debug
,"nrexcl[%d][%d]: %d, excl: ",i
,j
,nnb
->nrexcl
[i
][j
]);
132 for(k
=0; (k
<nnb
->nrexcl
[i
][j
]); k
++)
133 fprintf(debug
,"%d, ",nnb
->a
[i
][j
][k
]);
140 void nnb2excl (t_nextnb
*nnb
, t_block
*excl
)
143 int nre
,nrx
,nrs
,nr_of_sortables
;
146 srenew(excl
->index
, nnb
->nr
+1);
148 for (i
=0; (i
< nnb
->nr
); i
++) {
149 /* calculate the total number of exclusions for atom i */
151 for (nre
=0; (nre
<=nnb
->nrex
); nre
++)
152 nr_of_sortables
+=nnb
->nrexcl
[i
][nre
];
155 fprintf(debug
,"nr_of_sortables: %d\n",nr_of_sortables
);
156 /* make space for sortable array */
157 snew(s
,nr_of_sortables
);
159 /* fill the sortable array and sort it */
161 for (nre
=0; (nre
<= nnb
->nrex
); nre
++)
162 for (nrx
=0; (nrx
< nnb
->nrexcl
[i
][nre
]); nrx
++) {
164 s
[nrs
].aj
= nnb
->a
[i
][nre
][nrx
];
167 assert(nrs
==nr_of_sortables
);
168 prints("nnb2excl before qsort",nr_of_sortables
,s
);
169 if (nr_of_sortables
> 1) {
170 qsort ((void *)s
,nr_of_sortables
,(size_t)sizeof(s
[0]),bond_sort
);
171 prints("nnb2excl after qsort",nr_of_sortables
,s
);
174 /* remove duplicate entries from the list */
176 if (nr_of_sortables
> 0) {
177 for (j
=1; (j
< nr_of_sortables
); j
++)
178 if ((s
[j
].ai
!=s
[j
-1].ai
) || (s
[j
].aj
!=s
[j
-1].aj
))
182 nr_of_sortables
=j_index
;
183 prints("after rm-double",j_index
,s
);
185 /* make space for arrays */
186 srenew(excl
->a
,excl
->nra
+nr_of_sortables
);
188 /* put the sorted exclusions in the target list */
189 for (nrs
=0; (nrs
<nr_of_sortables
); nrs
++)
190 excl
->a
[excl
->nra
+nrs
] = s
[nrs
].aj
;
191 excl
->nra
+=nr_of_sortables
;
192 excl
->index
[i
+1]=excl
->nra
;
194 /* cleanup temporary space */
198 print_block(debug
,"Exclusions","Atom","Excluded",excl
);
201 static void do_gen(int nrbonds
, /* total number of bonds in s */
202 sortable
*s
, /* bidirectional list of bonds */
203 t_nextnb
*nnb
) /* the tmp storage for excl */
204 /* Assume excl is initalised and s[] contains all bonds bidirectional */
209 for(i
=0; (i
<nnb
->nr
); i
++)
211 print_nnb(nnb
,"After exclude self");
213 /* exclude all the bonded atoms */
215 for (i
=0; (i
< nrbonds
); i
++)
216 add_nnb(nnb
,1,s
[i
].ai
,s
[i
].aj
);
217 print_nnb(nnb
,"After exclude bonds");
219 /* for the nr of exclusions per atom */
220 for (n
=1; (n
< nnb
->nrex
); n
++)
222 /* now for all atoms */
223 for (i
=0; (i
< nnb
->nr
); i
++)
225 /* for all directly bonded atoms of atom i */
226 for (j
=0; (j
< nnb
->nrexcl
[i
][1]); j
++) {
228 /* store the 1st neighbour in nb */
229 nb
= nnb
->a
[i
][1][j
];
231 /* store all atoms in nb's n-th list into i's n+1-th list */
232 for (k
=0; (k
< nnb
->nrexcl
[nb
][n
]); k
++)
233 add_nnb(nnb
,n
+1,i
,nnb
->a
[nb
][n
][k
]);
235 print_nnb(nnb
,"After exclude rest");
238 static void add_b(t_params
*bonds
, int *nrf
, sortable
*s
)
243 for (i
=0; (i
< bonds
->nr
); i
++) {
244 ai
= bonds
->param
[i
].AI
;
245 aj
= bonds
->param
[i
].AJ
;
246 if ((ai
< 0) || (aj
< 0))
247 fatal_error(0,"Impossible atom numbers in bond %d: ai=%d, aj=%d",
249 /* Add every bond twice */
257 void gen_nnb(t_nextnb
*nnb
,t_params plist
[])
263 for(i
=0; (i
<F_NRE
); i
++)
265 /* we need every bond twice (bidirectional) */
266 nrbonds
+= 2*plist
[i
].nr
;
271 for(i
=0; (i
<F_NRE
); i
++)
273 add_b(&plist
[i
],&nrf
,s
);
275 /* now sort the bonds */
276 prints("gen_excl before qsort",nrbonds
,s
);
278 qsort((void *) s
,nrbonds
,(size_t)sizeof(sortable
),bond_sort
);
279 prints("gen_excl after qsort",nrbonds
,s
);
282 do_gen(nrbonds
,s
,nnb
);
286 void generate_excl (int nrexcl
,int nratoms
,t_params plist
[],t_block
*excl
)
291 fatal_error(0,"Can't have %d exclusions...",nrexcl
);
292 init_nnb(&nnb
,nratoms
,nrexcl
);
295 nnb2excl (&nnb
,excl
);