4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * Gnomes, ROck Monsters And Chili Sauce
37 #include "sortwater.h"
39 static rvec
*xptr
,box_1
;
44 void randwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],int *seed
)
50 for(i
=0; (i
<nwater
); i
++)
52 for(j
=0; (j
<23*nwater
); j
++) {
53 wi
= (int) (nwater
*rando(seed
)) % nwater
;
55 wj
= (int) (nwater
*rando(seed
)) % nwater
;
57 wi
= astart
+wi
*nwatom
;
58 wj
= astart
+wj
*nwatom
;
59 /* Swap coords for wi and wj */
60 for(i
=0; (i
<nwatom
); i
++) {
61 copy_rvec(x
[wi
+i
],buf
);
62 copy_rvec(x
[wj
+i
],x
[wi
+i
]);
63 copy_rvec(buf
,x
[wj
+i
]);
65 copy_rvec(v
[wi
+i
],buf
);
66 copy_rvec(v
[wj
+i
],v
[wi
+i
]);
67 copy_rvec(buf
,v
[wj
+i
]);
74 static int rvcomp(const void *a
,const void *b
)
78 aa
= nwat
*(*((int *)a
));
79 bb
= nwat
*(*((int *)b
));
80 if (xptr
[aa
][XX
] < xptr
[bb
][XX
])
82 else if (xptr
[aa
][XX
] > xptr
[bb
][XX
])
88 static int block_index(rvec x
,ivec nbox
)
93 for(m
=0; (m
<DIM
); m
++)
94 ixyz
[m
] = ((int)((1+x
[m
]*box_1
[m
])*nbox
[m
])) % nbox
[m
];
95 return ixyz
[XX
]*nbox
[YY
]*nbox
[ZZ
]+ixyz
[YY
]*nbox
[ZZ
]+ixyz
[ZZ
];
98 static int blockcomp(const void *a
,const void *b
)
102 aa
= nwat
*(*((int *)a
));
103 bb
= nwat
*(*((int *)b
));
105 aind
= block_index(xptr
[aa
],NBOX
);
106 bind
= block_index(xptr
[bb
],NBOX
);
109 if (xptr
[aa
][XX
] < xptr
[bb
][XX
])
111 else if (xptr
[aa
][XX
] > xptr
[bb
][XX
])
120 static void lo_sortwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],
127 /* Sort indices to rvecs */
128 snew(rvindex
,nwater
);
129 for(i
=0; (i
<nwater
); i
++)
134 qsort(rvindex
,nwater
,sizeof(rvindex
[0]),bBlock
? blockcomp
: rvcomp
);
136 for(i
=0; (i
<nwater
); i
++) {
137 rvi
= rvindex
[i
]*nwatom
;
138 fprintf(debug
,"rvindex[%5d] = %5d (x = %8.3f %8.3f %8.3f)\n",
139 i
,rvi
,x
[astart
+rvi
][XX
],x
[astart
+rvi
][YY
],x
[astart
+rvi
][ZZ
]);
141 snew(tmp
,nwater
*nwatom
);
143 for(i
=0; (i
<nwater
); i
++) {
144 i0
= astart
+nwatom
*rvindex
[i
];
145 for(j
=0; (j
<nwatom
); j
++)
146 copy_rvec(x
[i0
+j
],tmp
[nwatom
*i
+j
]);
148 for(i
=0; (i
<nwater
*nwatom
); i
++)
149 copy_rvec(tmp
[i
],x
[astart
+i
]);
151 for(i
=0; (i
<nwater
); i
++) {
152 i0
= astart
+nwatom
*rvindex
[i
];
153 for(j
=0; (j
<nwatom
); j
++)
154 copy_rvec(v
[i0
+j
],tmp
[nwatom
*i
+j
]);
156 for(i
=0; (i
<nwater
*nwatom
); i
++)
157 copy_rvec(tmp
[i
],v
[astart
+i
]);
163 void sortwater(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[])
165 lo_sortwater(astart
,nwater
,nwatom
,x
,v
,FALSE
);
168 static void factorize(int nn
,int fac
[])
172 for(i
=0; (i
<=n
); i
++)
184 fprintf(debug
,"Factorizing %d into primes:\n",nn
);
185 for(i
=2; (i
<=nn
); i
++) {
187 fprintf(debug
,"%d ^ %d\n",i
,fac
[i
]);
192 static int ipow(int base
,int exp
)
196 for(ip
=1,i
=0; (i
<exp
); i
++) {
202 static int iv_comp(const void *a
,const void *b
)
208 if (ia
[XX
] != ib
[XX
])
209 return (ia
[XX
] - ib
[XX
]);
210 else if (ia
[YY
] != ib
[YY
])
211 return (ia
[YY
] - ib
[YY
]);
213 return (ia
[ZZ
] - ib
[ZZ
]);
216 static int add_bb(ivec BB
[],int n
,ivec b
)
218 #define SWPX(vv,xx,yy) { int tmp; tmp=vv[xx]; vv[xx] = vv[yy]; vv[yy] = tmp; }
219 copy_ivec(b
,BB
[n
++]); /* x y z */
221 copy_ivec(b
,BB
[n
++]); /* y x z */
223 copy_ivec(b
,BB
[n
++]); /* z x y */
225 copy_ivec(b
,BB
[n
++]); /* x z y */
227 copy_ivec(b
,BB
[n
++]); /* y z x */
229 copy_ivec(b
,BB
[n
++]); /* z y x */
230 SWPX(b
,XX
,ZZ
); /* Back to normal */
235 static real
box_weight(ivec nbox
,matrix box
)
240 /* Calculate area of subbox */
241 for(m
=0; (m
<DIM
); m
++)
242 lx
[m
] = box
[m
][m
]/nbox
[m
];
243 return 2*(lx
[XX
]*lx
[YY
]+lx
[XX
]*lx
[ZZ
]+lx
[YY
]*lx
[ZZ
]);
246 static int w_comp(const void *a
,const void *b
)
254 wa
= box_weight(ia
,BOX
);
255 wb
= box_weight(ib
,BOX
);
256 if (fabs(wa
- wb
) < 1e-4)
257 return (iiprod(ia
,ia
) - iiprod(ib
,ib
));
264 static void buildbox(int nnode
,ivec nbox
,matrix box
)
267 int i
,j
,m
,n
,n3
,ny
,*fx
,*fy
,nbb
;
269 n3
= ipow(nnode
,3)*6;
275 for(i
=0; (i
<=nnode
); i
++) {
276 for(m
=1; (m
<=fx
[i
]); m
++) {
277 bxyz
[XX
] = ipow(i
,m
);
280 for(j
=0; (j
<=ny
); j
++) {
281 for(n
=1; (n
<=fy
[j
]); n
++) {
282 bxyz
[YY
] = ipow(j
,n
);
283 bxyz
[ZZ
] = ny
/bxyz
[YY
];
285 nbb
= add_bb(BB
,nbb
,bxyz
);
291 /* Sort boxes and remove doubles */
292 qsort(BB
,nbb
,sizeof(BB
[0]),iv_comp
);
294 for(i
=1; (i
<nbb
); i
++) {
295 if ((BB
[i
][XX
] != BB
[j
][XX
]) ||
296 (BB
[i
][YY
] != BB
[j
][YY
]) ||
297 (BB
[i
][ZZ
] != BB
[j
][ZZ
])) {
299 copy_ivec(BB
[i
],BB
[j
]);
303 /* Sort boxes according to weight */
305 qsort(BB
,nbb
,sizeof(BB
[0]),w_comp
);
306 for(i
=0; (i
<nbb
); i
++) {
307 fprintf(stderr
,"nbox = %2d %2d %2d [ prod %3d ] area = %12.5f (nm^2)\n",
308 BB
[i
][XX
],BB
[i
][YY
],BB
[i
][ZZ
],
309 BB
[i
][XX
]*BB
[i
][YY
]*BB
[i
][ZZ
],
310 box_weight(BB
[i
],box
));
312 copy_ivec(BB
[0],nbox
);
318 void mkcompact(int astart
,int nwater
,int nwatom
,rvec x
[],rvec v
[],
319 int nnode
,matrix box
)
321 /* Make a compact configuration for each processor.
322 * Divide the computational box in near cubic boxes and spread them
323 * evenly over processors.
331 buildbox(nnode
,NBOX
,box
);
332 /* copy_ivec(nbox,NBOX); */
333 for(m
=0; (m
<DIM
); m
++)
334 box_1
[m
] = 1.0/box
[m
][m
];
336 lo_sortwater(astart
,nwater
,nwatom
,x
,v
,TRUE
);