4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_topexcl_c
= "$Id$";
32 #ident "@(#) topexcl.c 1.38 2/2/97"
46 int bond_sort (const void *a
, const void *b
)
54 return (sa
->aj
-sb
->aj
);
56 return (sa
->ai
-sb
->ai
);
60 #define prints(str, n, s) __prints(str, n, s)
61 static void __prints(char *str
, int n
, sortable
*s
)
66 fprintf(debug
,"%s\n",str
);
67 fprintf(debug
,"Sortables \n");
68 for (i
=0; (i
< n
); i
++)
69 fprintf(debug
,"%d\t%d\n",s
[i
].ai
,s
[i
].aj
);
75 #define prints(str, n, s)
78 void init_nnb(t_nextnb
*nnb
, int nr
, int nrex
)
88 for (i
=0; (i
< nr
); i
++) {
89 snew(nnb
->a
[i
],nrex
+1);
90 snew(nnb
->nrexcl
[i
],nrex
+1);
94 static void add_nnb (t_nextnb
*nnb
, int nre
, int i
, int j
)
96 srenew(nnb
->a
[i
][nre
],nnb
->nrexcl
[i
][nre
]+1);
97 nnb
->a
[i
][nre
][nnb
->nrexcl
[i
][nre
]] = j
;
98 nnb
->nrexcl
[i
][nre
]++;
101 void done_nnb (t_nextnb
*nnb
)
105 for (i
=0; (i
< nnb
->nr
); i
++) {
106 for (nre
=0; (nre
<= nnb
->nrex
); nre
++)
107 if (nnb
->nrexcl
[i
][nre
] > 0)
108 sfree (nnb
->a
[i
][nre
]);
109 sfree (nnb
->nrexcl
[i
]);
119 void __print_nnb(t_nextnb
*nnb
, char *s
)
124 fprintf(debug
,"%s\n",s
);
125 fprintf(debug
,"nnb->nr: %d\n",nnb
->nr
);
126 fprintf(debug
,"nnb->nrex: %d\n",nnb
->nrex
);
127 for(i
=0; (i
<nnb
->nr
); i
++)
128 for(j
=0; (j
<=nnb
->nrex
); j
++) {
129 fprintf(debug
,"nrexcl[%d][%d]: %d, excl: ",i
,j
,nnb
->nrexcl
[i
][j
]);
130 for(k
=0; (k
<nnb
->nrexcl
[i
][j
]); k
++)
131 fprintf(debug
,"%d, ",nnb
->a
[i
][j
][k
]);
138 void nnb2excl (t_nextnb
*nnb
, t_block
*excl
)
141 int nre
,nrx
,nrs
,nr_of_sortables
;
144 srenew(excl
->index
, nnb
->nr
+1);
146 for (i
=0; (i
< nnb
->nr
); i
++) {
147 /* calculate the total number of exclusions for atom i */
149 for (nre
=0; (nre
<=nnb
->nrex
); nre
++)
150 nr_of_sortables
+=nnb
->nrexcl
[i
][nre
];
153 fprintf(debug
,"nr_of_sortables: %d\n",nr_of_sortables
);
154 /* make space for sortable array */
155 snew(s
,nr_of_sortables
);
157 /* fill the sortable array and sort it */
159 for (nre
=0; (nre
<= nnb
->nrex
); nre
++)
160 for (nrx
=0; (nrx
< nnb
->nrexcl
[i
][nre
]); nrx
++) {
162 s
[nrs
].aj
= nnb
->a
[i
][nre
][nrx
];
165 assert(nrs
==nr_of_sortables
);
166 prints("nnb2excl before qsort",nr_of_sortables
,s
);
167 qsort ((void *)s
,nr_of_sortables
,(size_t)sizeof(s
[0]),bond_sort
);
168 prints("nnb2excl after qsort",nr_of_sortables
,s
);
170 /* remove duplicate entries from the list */
172 if (nr_of_sortables
> 0) {
173 for (j
=1; (j
< nr_of_sortables
); j
++)
174 if ((s
[j
].ai
!=s
[j
-1].ai
) || (s
[j
].aj
!=s
[j
-1].aj
))
178 nr_of_sortables
=j_index
;
179 prints("after rm-double",j_index
,s
);
181 /* make space for arrays */
182 srenew(excl
->a
,excl
->nra
+nr_of_sortables
);
184 /* put the sorted exclusions in the target list */
185 for (nrs
=0; (nrs
<nr_of_sortables
); nrs
++)
186 excl
->a
[excl
->nra
+nrs
] = s
[nrs
].aj
;
187 excl
->nra
+=nr_of_sortables
;
188 excl
->index
[i
+1]=excl
->nra
;
190 /* cleanup temporary space */
194 print_block(debug
,"Exclusions","Atom","Excluded",excl
);
197 static void do_gen(int nrbonds
, /* total number of bonds in s */
198 sortable
*s
, /* bidirectional list of bonds */
199 t_nextnb
*nnb
) /* the tmp storage for excl */
200 /* Assume excl is initalised and s[] contains all bonds bidirectional */
205 for(i
=0; (i
<nnb
->nr
); i
++)
207 print_nnb(nnb
,"After exclude self");
209 /* exclude all the bonded atoms */
211 for (i
=0; (i
< nrbonds
); i
++)
212 add_nnb(nnb
,1,s
[i
].ai
,s
[i
].aj
);
213 print_nnb(nnb
,"After exclude bonds");
215 /* for the nr of exclusions per atom */
216 for (n
=1; (n
< nnb
->nrex
); n
++)
218 /* now for all atoms */
219 for (i
=0; (i
< nnb
->nr
); i
++)
221 /* for all directly bonded atoms of atom i */
222 for (j
=0; (j
< nnb
->nrexcl
[i
][1]); j
++) {
224 /* store the 1st neighbour in nb */
225 nb
= nnb
->a
[i
][1][j
];
227 /* store all atoms in nb's n-th list into i's n+1-th list */
228 for (k
=0; (k
< nnb
->nrexcl
[nb
][n
]); k
++)
229 add_nnb(nnb
,n
+1,i
,nnb
->a
[nb
][n
][k
]);
231 print_nnb(nnb
,"After exclude rest");
234 static void add_b(t_params
*bonds
, int *nrf
, sortable
*s
)
239 for (i
=0; (i
< bonds
->nr
); i
++) {
240 ai
= bonds
->param
[i
].AI
;
241 aj
= bonds
->param
[i
].AJ
;
242 if ((ai
< 0) || (aj
< 0))
243 fatal_error(0,"Impossible atom numbers in bond %d: ai=%d, aj=%d",
245 /* Add every bond twice */
253 void gen_nnb(t_nextnb
*nnb
,t_params plist
[])
259 for(i
=0; (i
<F_NRE
); i
++)
260 if ( (interaction_function
[i
].flags
& IF_CONNECT
) &&
261 !(interaction_function
[i
].flags
& IF_DUMMY
) )
262 /* we need every bond twice (bidirectional) */
263 nrbonds
+= 2*plist
[i
].nr
;
268 for(i
=0; (i
<F_NRE
); i
++)
269 if ( (interaction_function
[i
].flags
& IF_CONNECT
) &&
270 !(interaction_function
[i
].flags
& IF_DUMMY
) )
271 add_b(&plist
[i
],&nrf
,s
);
273 /* now sort the bonds */
274 prints("gen_excl before qsort",nrbonds
,s
);
275 qsort((void *) s
,nrbonds
,(size_t)sizeof(sortable
),bond_sort
);
276 prints("gen_excl after qsort",nrbonds
,s
);
278 do_gen(nrbonds
,s
,nnb
);
282 void generate_excl (int nrexcl
,int nratoms
,t_params plist
[],t_block
*excl
)
287 fatal_error(0,"Can't have %d exclusions...",nrexcl
);
288 init_nnb(&nnb
,nratoms
,nrexcl
);
291 nnb2excl (&nnb
,excl
);