3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
43 #include "sortwater.h"
45 static rvec
*xptr
,box_1
;
50 void randwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],int *seed
)
56 for(i
=0; (i
<nwater
); i
++)
58 for(j
=0; (j
<23*nwater
); j
++) {
59 wi
= (int) (nwater
*rando(seed
)) % nwater
;
61 wj
= (int) (nwater
*rando(seed
)) % nwater
;
63 wi
= astart
+wi
*nwatom
;
64 wj
= astart
+wj
*nwatom
;
65 /* Swap coords for wi and wj */
66 for(i
=0; (i
<nwatom
); i
++) {
67 copy_rvec(x
[wi
+i
],buf
);
68 copy_rvec(x
[wj
+i
],x
[wi
+i
]);
69 copy_rvec(buf
,x
[wj
+i
]);
71 copy_rvec(v
[wi
+i
],buf
);
72 copy_rvec(v
[wj
+i
],v
[wi
+i
]);
73 copy_rvec(buf
,v
[wj
+i
]);
80 static int rvcomp(const void *a
,const void *b
)
84 aa
= nwat
*(*((int *)a
));
85 bb
= nwat
*(*((int *)b
));
86 if (xptr
[aa
][XX
] < xptr
[bb
][XX
])
88 else if (xptr
[aa
][XX
] > xptr
[bb
][XX
])
94 static int block_index(rvec x
,ivec nbox
)
99 for(m
=0; (m
<DIM
); m
++)
100 ixyz
[m
] = ((int)((1+x
[m
]*box_1
[m
])*nbox
[m
])) % nbox
[m
];
101 return ixyz
[XX
]*nbox
[YY
]*nbox
[ZZ
]+ixyz
[YY
]*nbox
[ZZ
]+ixyz
[ZZ
];
104 static int blockcomp(const void *a
,const void *b
)
108 aa
= nwat
*(*((int *)a
));
109 bb
= nwat
*(*((int *)b
));
111 aind
= block_index(xptr
[aa
],NBOX
);
112 bind
= block_index(xptr
[bb
],NBOX
);
115 if (xptr
[aa
][XX
] < xptr
[bb
][XX
])
117 else if (xptr
[aa
][XX
] > xptr
[bb
][XX
])
126 static void lo_sortwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],
133 /* Sort indices to rvecs */
134 snew(rvindex
,nwater
);
135 for(i
=0; (i
<nwater
); i
++)
140 qsort(rvindex
,nwater
,sizeof(rvindex
[0]),bBlock
? blockcomp
: rvcomp
);
142 for(i
=0; (i
<nwater
); i
++) {
143 rvi
= rvindex
[i
]*nwatom
;
144 fprintf(debug
,"rvindex[%5d] = %5d (x = %8.3f %8.3f %8.3f)\n",
145 i
,rvi
,x
[astart
+rvi
][XX
],x
[astart
+rvi
][YY
],x
[astart
+rvi
][ZZ
]);
147 snew(tmp
,nwater
*nwatom
);
149 for(i
=0; (i
<nwater
); i
++) {
150 i0
= astart
+nwatom
*rvindex
[i
];
151 for(j
=0; (j
<nwatom
); j
++)
152 copy_rvec(x
[i0
+j
],tmp
[nwatom
*i
+j
]);
154 for(i
=0; (i
<nwater
*nwatom
); i
++)
155 copy_rvec(tmp
[i
],x
[astart
+i
]);
157 for(i
=0; (i
<nwater
); i
++) {
158 i0
= astart
+nwatom
*rvindex
[i
];
159 for(j
=0; (j
<nwatom
); j
++)
160 copy_rvec(v
[i0
+j
],tmp
[nwatom
*i
+j
]);
162 for(i
=0; (i
<nwater
*nwatom
); i
++)
163 copy_rvec(tmp
[i
],v
[astart
+i
]);
169 void sortwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[])
171 lo_sortwater(astart
,nwater
,nwatom
,x
,v
,FALSE
);
174 static void factorize(int nn
,int fac
[])
178 for(i
=0; (i
<=n
); i
++)
190 fprintf(debug
,"Factorizing %d into primes:\n",nn
);
191 for(i
=2; (i
<=nn
); i
++) {
193 fprintf(debug
,"%d ^ %d\n",i
,fac
[i
]);
198 static int ipow(int base
,int exp
)
202 for(ip
=1,i
=0; (i
<exp
); i
++) {
208 static int iv_comp(const void *a
,const void *b
)
214 if (ia
[XX
] != ib
[XX
])
215 return (ia
[XX
] - ib
[XX
]);
216 else if (ia
[YY
] != ib
[YY
])
217 return (ia
[YY
] - ib
[YY
]);
219 return (ia
[ZZ
] - ib
[ZZ
]);
222 static int add_bb(ivec BB
[],int n
,ivec b
)
224 #define SWPX(vv,xx,yy) { int tmp; tmp=vv[xx]; vv[xx] = vv[yy]; vv[yy] = tmp; }
225 copy_ivec(b
,BB
[n
++]); /* x y z */
227 copy_ivec(b
,BB
[n
++]); /* y x z */
229 copy_ivec(b
,BB
[n
++]); /* z x y */
231 copy_ivec(b
,BB
[n
++]); /* x z y */
233 copy_ivec(b
,BB
[n
++]); /* y z x */
235 copy_ivec(b
,BB
[n
++]); /* z y x */
236 SWPX(b
,XX
,ZZ
); /* Back to normal */
241 static real
box_weight(ivec nbox
,matrix box
)
246 /* Calculate area of subbox */
247 for(m
=0; (m
<DIM
); m
++)
248 lx
[m
] = box
[m
][m
]/nbox
[m
];
249 return 2*(lx
[XX
]*lx
[YY
]+lx
[XX
]*lx
[ZZ
]+lx
[YY
]*lx
[ZZ
]);
252 static int w_comp(const void *a
,const void *b
)
260 wa
= box_weight(ia
,BOX
);
261 wb
= box_weight(ib
,BOX
);
262 if (fabs(wa
- wb
) < 1e-4)
263 return (iiprod(ia
,ia
) - iiprod(ib
,ib
));
270 static void buildbox(int nnode
,ivec nbox
,matrix box
)
273 int i
,j
,m
,n
,n3
,ny
,*fx
,*fy
,nbb
;
275 n3
= ipow(nnode
,3)*6;
281 for(i
=0; (i
<=nnode
); i
++) {
282 for(m
=1; (m
<=fx
[i
]); m
++) {
283 bxyz
[XX
] = ipow(i
,m
);
286 for(j
=0; (j
<=ny
); j
++) {
287 for(n
=1; (n
<=fy
[j
]); n
++) {
288 bxyz
[YY
] = ipow(j
,n
);
289 bxyz
[ZZ
] = ny
/bxyz
[YY
];
291 nbb
= add_bb(BB
,nbb
,bxyz
);
297 /* Sort boxes and remove doubles */
298 qsort(BB
,nbb
,sizeof(BB
[0]),iv_comp
);
300 for(i
=1; (i
<nbb
); i
++) {
301 if ((BB
[i
][XX
] != BB
[j
][XX
]) ||
302 (BB
[i
][YY
] != BB
[j
][YY
]) ||
303 (BB
[i
][ZZ
] != BB
[j
][ZZ
])) {
305 copy_ivec(BB
[i
],BB
[j
]);
309 /* Sort boxes according to weight */
311 qsort(BB
,nbb
,sizeof(BB
[0]),w_comp
);
312 for(i
=0; (i
<nbb
); i
++) {
313 fprintf(stderr
,"nbox = %2d %2d %2d [ prod %3d ] area = %12.5f (nm^2)\n",
314 BB
[i
][XX
],BB
[i
][YY
],BB
[i
][ZZ
],
315 BB
[i
][XX
]*BB
[i
][YY
]*BB
[i
][ZZ
],
316 box_weight(BB
[i
],box
));
318 copy_ivec(BB
[0],nbox
);
324 void mkcompact(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],
325 int nnode
,matrix box
)
327 /* Make a compact configuration for each processor.
328 * Divide the computational box in near cubic boxes and spread them
329 * evenly over processors.
337 buildbox(nnode
,NBOX
,box
);
338 /* copy_ivec(nbox,NBOX); */
339 for(m
=0; (m
<DIM
); m
++)
340 box_1
[m
] = 1.0/box
[m
][m
];
342 lo_sortwater(astart
,nwater
,nwatom
,x
,v
,TRUE
);