00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <math.h>
00025 #include <stdlib.h>
00026 #include "BondSearch.h"
00027 #include "Timestep.h"
00028 #include "BaseMolecule.h"
00029 #include "Molecule.h"
00030 #include "Inform.h"
00031 #include "WKFThreads.h"
00032 #include "WKFUtils.h"
00033 #include <ctype.h>
00034 #include <string.h>
00035
00036 static void add_link(GridSearchPair *link, int i, int j) {
00037 link->next = (GridSearchPair *) malloc(sizeof(GridSearchPair));
00038 link->next->ind1 = i;
00039 link->next->ind2 = j;
00040 link->next->next = NULL;
00041 }
00042
00043 void find_minmax_all(const float *pos, int n, float *min, float *max) {
00044 float x1, x2, y1, y2, z1, z2;
00045 int i=0;
00046
00047
00048 if (n < 1) return;
00049
00050
00051 pos += 3*i;
00052 x1 = x2 = pos[0];
00053 y1 = y2 = pos[1];
00054 z1 = z2 = pos[2];
00055 pos += 3;
00056 i++;
00057
00058 for (; i < n; i++) {
00059 if (pos[0] < x1) x1 = pos[0];
00060 if (pos[0] > x2) x2 = pos[0];
00061 if (pos[1] < y1) y1 = pos[1];
00062 if (pos[1] > y2) y2 = pos[1];
00063 if (pos[2] < z1) z1 = pos[2];
00064 if (pos[2] > z2) z2 = pos[2];
00065 pos += 3;
00066 }
00067 min[0] = x1; min[1] = y1; min[2] = z1;
00068 max[0] = x2; max[1] = y2; max[2] = z2;
00069 }
00070
00071
00072
00073
00074 int find_minmax_selected(int n, const int *flgs, const float *pos,
00075 float &_xmin, float &_ymin, float &_zmin,
00076 float &_xmax, float &_ymax, float &_zmax) {
00077 int i;
00078 float xmin, xmax, ymin, ymax, zmin, zmax;
00079 for (i=0; i<n; i++) if (flgs[i]) break;
00080 if (i==n) return FALSE;
00081 pos += 3*i;
00082 xmin=xmax=pos[0];
00083 ymin=ymax=pos[1];
00084 zmin=zmax=pos[2];
00085 pos += 3;
00086 i += 1;
00087 for (; i<n; i++, pos += 3) {
00088 if (!flgs[i]) continue;
00089 const float xi=pos[0];
00090 const float yi=pos[1];
00091 const float zi=pos[2];
00092 if (xmin>xi) xmin=xi;
00093 if (ymin>yi) ymin=yi;
00094 if (zmin>zi) zmin=zi;
00095 if (xmax<xi) xmax=xi;
00096 if (ymax<yi) ymax=yi;
00097 if (zmax<zi) zmax=zi;
00098 }
00099 _xmin=xmin;
00100 _ymin=ymin;
00101 _zmin=zmin;
00102 _xmax=xmax;
00103 _ymax=ymax;
00104 _zmax=zmax;
00105 return TRUE;
00106 }
00107
00108
00109
00110 void find_minmax(const float *pos, int n, const int *on,
00111 float *min, float *max, int *oncount) {
00112 float x1, x2, y1, y2, z1, z2;
00113 int i, numon;
00114
00115
00116 if (n < 1) return;
00117
00118
00119 numon = 0;
00120
00121
00122 for (i=0; i<n; i++) {
00123 if (on[i]) {
00124 numon++;
00125 break;
00126 }
00127 }
00128 if (i==n) {
00129 if (oncount != NULL)
00130 *oncount = numon;
00131 return;
00132 }
00133
00134
00135 pos += 3*i;
00136 x1 = x2 = pos[0];
00137 y1 = y2 = pos[1];
00138 z1 = z2 = pos[2];
00139 pos += 3;
00140 i++;
00141
00142 for (; i < n; i++) {
00143 if (on[i]) {
00144 if (pos[0] < x1) x1 = pos[0];
00145 else if (pos[0] > x2) x2 = pos[0];
00146 if (pos[1] < y1) y1 = pos[1];
00147 else if (pos[1] > y2) y2 = pos[1];
00148 if (pos[2] < z1) z1 = pos[2];
00149 else if (pos[2] > z2) z2 = pos[2];
00150 numon++;
00151 }
00152 pos += 3;
00153 }
00154 min[0] = x1; min[1] = y1; min[2] = z1;
00155 max[0] = x2; max[1] = y2; max[2] = z2;
00156
00157 if (oncount != NULL)
00158 *oncount = numon;
00159 }
00160
00161 int make_neighborlist(int **nbrlist, int xb, int yb, int zb) {
00162 int xi, yi, zi, aindex, xytotb;
00163
00164 if (nbrlist == NULL)
00165 return -1;
00166
00167 xytotb = xb * yb;
00168 aindex = 0;
00169 for (zi=0; zi<zb; zi++) {
00170 for (yi=0; yi<yb; yi++) {
00171 for (xi=0; xi<xb; xi++) {
00172 int nbrs[15];
00173 int n=0;
00174 nbrs[n++] = aindex;
00175 if (xi < xb-1) nbrs[n++] = aindex + 1;
00176 if (yi < yb-1) nbrs[n++] = aindex + xb;
00177 if (zi < zb-1) nbrs[n++] = aindex + xytotb;
00178 if (xi < (xb-1) && yi < (yb-1)) nbrs[n++] = aindex + xb + 1;
00179 if (xi < (xb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + 1;
00180 if (yi < (yb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + xb;
00181 if (xi < (xb-1) && yi > 0) nbrs[n++] = aindex - xb + 1;
00182 if (xi > 0 && zi < (zb-1)) nbrs[n++] = aindex + xytotb - 1;
00183 if (yi > 0 && zi < (zb-1)) nbrs[n++] = aindex + xytotb - xb;
00184 if (xi < (xb-1) && yi < (yb-1) && zi < (zb-1))
00185 nbrs[n++] = aindex + xytotb + xb + 1;
00186 if (xi > 0 && yi < (yb-1) && zi < (zb-1))
00187 nbrs[n++] = aindex + xytotb + xb - 1;
00188 if (xi < (xb-1) && yi > 0 && zi < (zb-1))
00189 nbrs[n++] = aindex + xytotb - xb + 1;
00190 if (xi > 0 && yi > 0 && zi < (zb-1))
00191 nbrs[n++] = aindex + xytotb - xb - 1;
00192 nbrs[n++] = -1;
00193
00194 int *lst = (int *) malloc(n*sizeof(int));
00195 if (lst == NULL)
00196 return -1;
00197 memcpy(lst, nbrs, n*sizeof(int));
00198 nbrlist[aindex] = lst;
00199 aindex++;
00200 }
00201 }
00202 }
00203
00204 return 0;
00205 }
00206
00207
00208
00209 static int make_neighborlist_sym(int **nbrlist, int xb, int yb, int zb) {
00210 int xi, yi, zi, aindex, xytotb;
00211
00212 if (nbrlist == NULL)
00213 return -1;
00214
00215 xytotb = xb * yb;
00216 aindex = 0;
00217 for (zi=0; zi<zb; zi++) {
00218 for (yi=0; yi<yb; yi++) {
00219 for (xi=0; xi<xb; xi++) {
00220 int nbrs[28];
00221 int n=0;
00222 nbrs[n++] = aindex;
00223 if (xi < xb-1) nbrs[n++] = aindex + 1;
00224 if (yi < yb-1) nbrs[n++] = aindex + xb;
00225 if (zi < zb-1) nbrs[n++] = aindex + xytotb;
00226 if (xi < (xb-1) && yi < (yb-1)) nbrs[n++] = aindex + xb + 1;
00227 if (xi < (xb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + 1;
00228 if (yi < (yb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + xb;
00229 if (xi < (xb-1) && yi) nbrs[n++] = aindex - xb + 1;
00230 if (xi && zi < (zb-1)) nbrs[n++] = aindex + xytotb - 1;
00231 if (yi && zi < (zb-1)) nbrs[n++] = aindex + xytotb - xb;
00232 if (xi < (xb-1) && yi < (yb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + xb + 1;
00233 if (xi && yi < (yb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + xb - 1;
00234 if (xi < (xb-1) && yi && zi < (zb-1)) nbrs[n++] = aindex + xytotb - xb + 1;
00235 if (xi && yi && zi < (zb-1)) nbrs[n++] = aindex + xytotb - xb - 1;
00236
00237 if (xi) nbrs[n++] = aindex - 1;
00238 if (yi) nbrs[n++] = aindex - xb;
00239 if (zi) nbrs[n++] = aindex - xytotb;
00240 if (xi && yi) nbrs[n++] = aindex - xb - 1;
00241 if (xi && zi) nbrs[n++] = aindex - xytotb - 1;
00242 if (yi && zi) nbrs[n++] = aindex - xytotb - xb;
00243 if (xi && yi < (yb-1)) nbrs[n++] = aindex + xb - 1;
00244 if (xi < (xb-1) && zi) nbrs[n++] = aindex - xytotb + 1;
00245 if (yi < (yb-1) && zi) nbrs[n++] = aindex - xytotb + xb;
00246 if (xi && yi && zi) nbrs[n++] = aindex - xytotb - xb - 1;
00247 if (xi < (xb-1) && yi && zi) nbrs[n++] = aindex - xytotb - xb + 1;
00248 if (xi && yi < (yb-1) && zi) nbrs[n++] = aindex - xytotb + xb - 1;
00249 if (xi < (xb-1) && yi < (yb-1) && zi) nbrs[n++] = aindex - xytotb + xb + 1;
00250 nbrs[n++] = -1;
00251
00252 int *lst = (int *) malloc(n*sizeof(int));
00253 if (lst == NULL)
00254 return -1;
00255 memcpy(lst, nbrs, n*sizeof(int));
00256 nbrlist[aindex] = lst;
00257 aindex++;
00258 }
00259 }
00260 }
00261
00262 return 0;
00263 }
00264
00265
00266 GridSearchPair *vmd_gridsearch1(const float *pos,int natoms, const int *on,
00267 float pairdist, int allow_double_counting, int maxpairs) {
00268 float min[3]={0,0,0}, max[3]={0,0,0};
00269 float sqdist;
00270 int i, j, xb, yb, zb, xytotb, totb, aindex;
00271 int **boxatom, *numinbox, *maxinbox, **nbrlist;
00272 int numon = 0;
00273 float sidelen[3], volume;
00274 int paircount = 0;
00275 int maxpairsreached = 0;
00276 sqdist = pairdist * pairdist;
00277
00278
00279 find_minmax(pos, natoms, on, min, max, &numon);
00280
00281
00282
00283
00284 if (maxpairs != -1) {
00285 vec_sub(sidelen, max, min);
00286
00287 volume = fabsf((sidelen[0] + 2.0f) * (sidelen[1] + 2.0f) * (sidelen[2] + 2.0f));
00288 if ((numon / volume) > 1.0) {
00289 msgWarn << "vmd_gridsearch1: insane atom density" << sendmsg;
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298
00299 const int MAXBOXES = 4000000;
00300 totb = MAXBOXES + 1;
00301
00302 float newpairdist = pairdist;
00303 float xrange = max[0]-min[0];
00304 float yrange = max[1]-min[1];
00305 float zrange = max[2]-min[2];
00306 do {
00307 pairdist = newpairdist;
00308 const float invpairdist = 1.0f / pairdist;
00309 xb = ((int)(xrange*invpairdist))+1;
00310 yb = ((int)(yrange*invpairdist))+1;
00311 zb = ((int)(zrange*invpairdist))+1;
00312 xytotb = yb * xb;
00313 totb = xytotb * zb;
00314 newpairdist = pairdist * 1.26f;
00315 } while (totb > MAXBOXES || totb < 1);
00316
00317
00318 boxatom = (int **) calloc(1, totb*sizeof(int *));
00319 numinbox = (int *) calloc(1, totb*sizeof(int));
00320 maxinbox = (int *) calloc(1, totb*sizeof(int));
00321 if (boxatom == NULL || numinbox == NULL || maxinbox == NULL) {
00322 if (boxatom != NULL)
00323 free(boxatom);
00324 if (numinbox != NULL)
00325 free(numinbox);
00326 if (maxinbox != NULL)
00327 free(maxinbox);
00328 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00329 return NULL;
00330 }
00331
00332 const float invpairdist = 1.0f / pairdist;
00333 for (i=0; i<natoms; i++) {
00334 if (on[i]) {
00335 int axb, ayb, azb, aindex, num;
00336
00337
00338 const float *loc = pos + 3*i;
00339 axb = (int)((loc[0] - min[0])*invpairdist);
00340 ayb = (int)((loc[1] - min[1])*invpairdist);
00341 azb = (int)((loc[2] - min[2])*invpairdist);
00342
00343
00344 if (axb >= xb) axb = xb-1;
00345 if (ayb >= yb) ayb = yb-1;
00346 if (azb >= zb) azb = zb-1;
00347
00348 aindex = azb * xytotb + ayb * xb + axb;
00349
00350
00351 if ((num = numinbox[aindex]) == maxinbox[aindex]) {
00352 boxatom[aindex] = (int *) realloc(boxatom[aindex], (num+4)*sizeof(int));
00353 maxinbox[aindex] += 4;
00354 }
00355
00356
00357 boxatom[aindex][num] = i;
00358 numinbox[aindex]++;
00359 }
00360 }
00361 free(maxinbox);
00362
00363 nbrlist = (int **) calloc(1, totb*sizeof(int *));
00364 if (make_neighborlist(nbrlist, xb, yb, zb)) {
00365 if (boxatom != NULL) {
00366 for (i=0; i<totb; i++) {
00367 if (boxatom[i] != NULL) free(boxatom[i]);
00368 }
00369 free(boxatom);
00370 }
00371 if (nbrlist != NULL) {
00372 for (i=0; i<totb; i++) {
00373 if (nbrlist[i] != NULL) free(nbrlist[i]);
00374 }
00375 free(nbrlist);
00376 }
00377 free(numinbox);
00378 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00379 return NULL;
00380 }
00381
00382
00383 GridSearchPair *head, *cur;
00384 head = (GridSearchPair *) malloc(sizeof(GridSearchPair));
00385 head->next = NULL;
00386 cur = head;
00387
00388 wkfmsgtimer *msgt = wkf_msg_timer_create(5);
00389 for (aindex = 0; (aindex < totb) && (!maxpairsreached); aindex++) {
00390 int *tmpbox, *tmpnbr, *nbr;
00391 tmpbox = boxatom[aindex];
00392 tmpnbr = nbrlist[aindex];
00393
00394 if (wkf_msg_timer_timeout(msgt)) {
00395 char tmpbuf[128];
00396 sprintf(tmpbuf, "%6.2f", (100.0f * aindex) / (float) totb);
00397 msgInfo << "vmd_gridsearch1: " << tmpbuf << "% complete" << sendmsg;
00398 }
00399
00400 for (nbr = tmpnbr; (*nbr != -1) && (!maxpairsreached); nbr++) {
00401 int *nbrbox = boxatom[*nbr];
00402 for (i=0; (i<numinbox[aindex]) && (!maxpairsreached); i++) {
00403 int ind1 = tmpbox[i];
00404 if (!on[ind1])
00405 continue;
00406 const float *p1 = pos + 3*ind1;
00407 int startj = 0;
00408 if (aindex == *nbr) startj = i+1;
00409 for (j=startj; (j<numinbox[*nbr]) && (!maxpairsreached); j++) {
00410 int ind2 = nbrbox[j];
00411 if (on[ind2]) {
00412 const float *p2 = pos + 3*ind2;
00413 float ds2 = distance2(p1, p2);
00414
00415
00416 if (ds2 < 0.001)
00417 continue;
00418
00419 if (ds2 > sqdist)
00420 continue;
00421
00422 if (maxpairs > 0) {
00423 if (paircount >= maxpairs) {
00424 maxpairsreached = 1;
00425 continue;
00426 }
00427 }
00428
00429 add_link(cur, ind1, ind2);
00430 paircount++;
00431
00432
00433 if (allow_double_counting) {
00434 add_link(cur, ind2, ind1);
00435 paircount++;
00436 }
00437 cur = cur->next;
00438 cur->next = NULL;
00439 }
00440 }
00441 }
00442 }
00443 }
00444
00445 for (i=0; i<totb; i++) {
00446 free(boxatom[i]);
00447 free(nbrlist[i]);
00448 }
00449 free(boxatom);
00450 free(nbrlist);
00451 free(numinbox);
00452
00453 cur = head->next;
00454 free(head);
00455
00456 if (maxpairsreached)
00457 msgErr << "vmdgridsearch1: exceeded pairlist sanity check, aborted" << sendmsg;
00458
00459 wkf_msg_timer_destroy(msgt);
00460
00461 return cur;
00462 }
00463
00464 GridSearchPair *vmd_gridsearch2(const float *pos,int natoms,
00465 const int *A,const int *B, float pairdist, int maxpairs) {
00466 float min[3]={0,0,0}, max[3]={0,0,0};
00467 float sqdist;
00468 int i, j, xb, yb, zb, xytotb, totb, aindex;
00469 int **boxatom, *numinbox, *maxinbox, **nbrlist;
00470 float sidelen[3], volume;
00471 int numon = 0;
00472 int paircount = 0;
00473 int maxpairsreached = 0;
00474 sqdist = pairdist * pairdist;
00475
00476
00477
00478
00479
00480
00481 int *on = (int *) malloc(natoms*sizeof(int));
00482 for (i=0; i<natoms; i++) {
00483 if (A[i] || B[i]) {
00484 numon++;
00485 on[i] = 1;
00486 } else {
00487 on[i] = 0;
00488 }
00489 }
00490
00491
00492 find_minmax(pos, natoms, on, min, max, NULL);
00493
00494
00495
00496
00497 if (maxpairs != -1) {
00498 vec_sub(sidelen, max, min);
00499
00500 volume = fabsf((sidelen[0] + 2.0f) * (sidelen[1] + 2.0f) * (sidelen[2] + 2.0f));
00501 if ((numon / volume) > 1.0) {
00502 msgWarn << "vmd_gridsearch2: insane atom density" << sendmsg;
00503 }
00504 }
00505
00506
00507
00508
00509
00510
00511
00512 const int MAXBOXES = 4000000;
00513 totb = MAXBOXES + 1;
00514
00515 float newpairdist = pairdist;
00516 float xrange = max[0]-min[0];
00517 float yrange = max[1]-min[1];
00518 float zrange = max[2]-min[2];
00519 do {
00520 pairdist = newpairdist;
00521 const float invpairdist = 1.0f / pairdist;
00522 xb = ((int)(xrange*invpairdist))+1;
00523 yb = ((int)(yrange*invpairdist))+1;
00524 zb = ((int)(zrange*invpairdist))+1;
00525 xytotb = yb * xb;
00526 totb = xytotb * zb;
00527 newpairdist = pairdist * 1.26f;
00528 } while (totb > MAXBOXES || totb < 1);
00529
00530
00531 boxatom = (int **) calloc(1, totb*sizeof(int *));
00532 numinbox = (int *) calloc(1, totb*sizeof(int));
00533 maxinbox = (int *) calloc(1, totb*sizeof(int));
00534 if (boxatom == NULL || numinbox == NULL || maxinbox == NULL) {
00535 if (boxatom != NULL)
00536 free(boxatom);
00537 if (numinbox != NULL)
00538 free(numinbox);
00539 if (maxinbox != NULL)
00540 free(maxinbox);
00541 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00542 return NULL;
00543 }
00544
00545 const float invpairdist = 1.0f / pairdist;
00546 for (i=0; i<natoms; i++) {
00547 if (on[i]) {
00548 int axb, ayb, azb, aindex, num;
00549
00550
00551 const float *loc = pos + 3*i;
00552 axb = (int)((loc[0] - min[0])*invpairdist);
00553 ayb = (int)((loc[1] - min[1])*invpairdist);
00554 azb = (int)((loc[2] - min[2])*invpairdist);
00555
00556
00557 if (axb >= xb) axb = xb-1;
00558 if (ayb >= yb) ayb = yb-1;
00559 if (azb >= zb) azb = zb-1;
00560
00561 aindex = azb * xytotb + ayb * xb + axb;
00562
00563
00564 if ((num = numinbox[aindex]) == maxinbox[aindex]) {
00565 boxatom[aindex] = (int *) realloc(boxatom[aindex], (num+4)*sizeof(int));
00566 maxinbox[aindex] += 4;
00567 }
00568
00569
00570 boxatom[aindex][num] = i;
00571 numinbox[aindex]++;
00572 }
00573 }
00574 free(maxinbox);
00575 free(on);
00576
00577 nbrlist = (int **) calloc(1, totb*sizeof(int *));
00578 if (make_neighborlist(nbrlist, xb, yb, zb)) {
00579 if (boxatom != NULL) {
00580 for (i=0; i<totb; i++) {
00581 if (boxatom[i] != NULL) free(boxatom[i]);
00582 }
00583 free(boxatom);
00584 }
00585 if (nbrlist != NULL) {
00586 for (i=0; i<totb; i++) {
00587 if (nbrlist[i] != NULL) free(nbrlist[i]);
00588 }
00589 free(nbrlist);
00590 }
00591 free(numinbox);
00592 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00593 return NULL;
00594 }
00595
00596
00597 GridSearchPair *head, *cur;
00598 head = (GridSearchPair *) malloc(sizeof(GridSearchPair));
00599 head->next = NULL;
00600 cur = head;
00601
00602 for (aindex = 0; aindex < totb; aindex++) {
00603 int *tmpbox, *tmpnbr, *nbr;
00604 tmpbox = boxatom[aindex];
00605 tmpnbr = nbrlist[aindex];
00606 for (nbr = tmpnbr; (*nbr != -1) && (!maxpairsreached); nbr++) {
00607 int *nbrbox = boxatom[*nbr];
00608 for (i=0; (i<numinbox[aindex]) && (!maxpairsreached); i++) {
00609 const float *p1;
00610 int ind1, startj;
00611 ind1 = tmpbox[i];
00612 p1 = pos + 3*ind1;
00613 startj = 0;
00614 if (aindex == *nbr) startj = i+1;
00615 for (j=startj; (j<numinbox[*nbr]) && (!maxpairsreached); j++) {
00616 const float *p2;
00617 int ind2;
00618 ind2 = nbrbox[j];
00619 if ((A[ind1] && B[ind2]) || (A[ind2] && B[ind1])) {
00620 p2 = pos + 3*ind2;
00621 if (distance2(p1,p2) > sqdist) continue;
00622
00623 if (maxpairs > 0) {
00624 if (paircount >= maxpairs) {
00625 maxpairsreached = 1;
00626 continue;
00627 }
00628 }
00629
00630 if (A[ind1]) {
00631 add_link(cur, ind1, ind2);
00632 paircount++;
00633 } else {
00634 add_link(cur, ind2, ind1);
00635 paircount++;
00636 }
00637 cur = cur->next;
00638 cur->next = NULL;
00639 }
00640 }
00641 }
00642 }
00643 }
00644
00645 for (i=0; i<totb; i++) {
00646 free(boxatom[i]);
00647 free(nbrlist[i]);
00648 }
00649 free(boxatom);
00650 free(nbrlist);
00651 free(numinbox);
00652
00653 cur = head->next;
00654 free(head);
00655
00656 if (maxpairsreached)
00657 msgErr << "vmdgridsearch2: exceeded pairlist sanity check, aborted" << sendmsg;
00658
00659 return cur;
00660 }
00661
00662
00663
00664
00665
00666
00667 GridSearchPair *vmd_gridsearch3(const float *posA, int natomsA, const int *A,
00668 const float *posB, int natomsB, const int *B,
00669 float pairdist, int allow_double_counting, int maxpairs) {
00670
00671 if (!natomsA || !natomsB) return NULL;
00672
00673 if (allow_double_counting == -1) {
00674 if (posA == posB && natomsA == natomsB)
00675 allow_double_counting = FALSE;
00676 else
00677 allow_double_counting = TRUE;
00678 }
00679
00680
00681 if (posA == posB && natomsA == natomsB) {
00682 bool is_equal = TRUE;
00683 for (int i=0; i<natomsA && is_equal; i++) {
00684 if (A[i] != B[i])
00685 is_equal = FALSE;
00686 }
00687 if (is_equal)
00688 return vmd_gridsearch1(posA, natomsA, A, pairdist, allow_double_counting, maxpairs);
00689 }
00690
00691 float min[3], max[3], sqdist;
00692 float minB[3], maxB[3];
00693 int i, j, xb, yb, zb, xytotb, totb, aindex;
00694 int **boxatomA, *numinboxA, *maxinboxA;
00695 int **boxatomB, *numinboxB, *maxinboxB;
00696 int **nbrlist;
00697 float sidelen[3], volume;
00698 int numonA = 0; int numonB = 0;
00699 int paircount = 0;
00700 int maxpairsreached = 0;
00701 sqdist = pairdist * pairdist;
00702
00703
00704
00705 find_minmax(posA, natomsA, A, min, max, &numonA);
00706 find_minmax(posB, natomsB, B, minB, maxB, &numonB);
00707
00708
00709 if (!numonA || !numonB) return NULL;
00710
00711 for (i=0; i<3; i++) {
00712 if (minB[i] < min[i]) min[i] = minB[i];
00713 if (maxB[i] > max[i]) max[i] = maxB[i];
00714 }
00715
00716
00717
00718
00719 if (maxpairs != -1) {
00720 vec_sub(sidelen, max, min);
00721
00722 volume = fabsf((sidelen[0] + 2.0f) * (sidelen[1] + 2.0f) * (sidelen[2] + 2.0f));
00723 if (((numonA + numonB) / volume) > 1.0) {
00724 msgWarn << "vmd_gridsearch3: insane atom density" << sendmsg;
00725 }
00726 }
00727
00728
00729
00730
00731
00732
00733
00734 const int MAXBOXES = 4000000;
00735 totb = MAXBOXES + 1;
00736
00737 float newpairdist = pairdist;
00738 float xrange = max[0]-min[0];
00739 float yrange = max[1]-min[1];
00740 float zrange = max[2]-min[2];
00741 do {
00742 pairdist = newpairdist;
00743 const float invpairdist = 1.0f / pairdist;
00744 xb = ((int)(xrange*invpairdist))+1;
00745 yb = ((int)(yrange*invpairdist))+1;
00746 zb = ((int)(zrange*invpairdist))+1;
00747 xytotb = yb * xb;
00748 totb = xytotb * zb;
00749 newpairdist = pairdist * 1.26f;
00750 } while (totb > MAXBOXES || totb < 1);
00751
00752
00753 boxatomA = (int **) calloc(1, totb*sizeof(int *));
00754 numinboxA = (int *) calloc(1, totb*sizeof(int));
00755 maxinboxA = (int *) calloc(1, totb*sizeof(int));
00756 if (boxatomA == NULL || numinboxA == NULL || maxinboxA == NULL) {
00757 if (boxatomA != NULL)
00758 free(boxatomA);
00759 if (numinboxA != NULL)
00760 free(numinboxA);
00761 if (maxinboxA != NULL)
00762 free(maxinboxA);
00763 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00764 return NULL;
00765 }
00766
00767 const float invpairdist = 1.0f / pairdist;
00768 for (i=0; i<natomsA; i++) {
00769 if (A[i]) {
00770 int axb, ayb, azb, aindex, num;
00771
00772
00773 const float *loc = posA + 3*i;
00774 axb = (int)((loc[0] - min[0])*invpairdist);
00775 ayb = (int)((loc[1] - min[1])*invpairdist);
00776 azb = (int)((loc[2] - min[2])*invpairdist);
00777
00778
00779 if (axb >= xb) axb = xb-1;
00780 if (ayb >= yb) ayb = yb-1;
00781 if (azb >= zb) azb = zb-1;
00782
00783 aindex = azb * xytotb + ayb * xb + axb;
00784
00785
00786 if ((num = numinboxA[aindex]) == maxinboxA[aindex]) {
00787 boxatomA[aindex] = (int *) realloc(boxatomA[aindex], (num+4)*sizeof(int));
00788 maxinboxA[aindex] += 4;
00789 }
00790
00791
00792 boxatomA[aindex][num] = i;
00793 numinboxA[aindex]++;
00794 }
00795 }
00796 free(maxinboxA);
00797
00798 boxatomB = (int **) calloc(1, totb*sizeof(int *));
00799 numinboxB = (int *) calloc(1, totb*sizeof(int));
00800 maxinboxB = (int *) calloc(1, totb*sizeof(int));
00801 if (boxatomB == NULL || numinboxB == NULL || maxinboxB == NULL) {
00802 if (boxatomB != NULL)
00803 free(boxatomB);
00804 if (numinboxB != NULL)
00805 free(numinboxB);
00806 if (maxinboxB != NULL)
00807 free(maxinboxB);
00808 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00809 return NULL;
00810 }
00811
00812 for (i=0; i<natomsB; i++) {
00813 if (B[i]) {
00814 int axb, ayb, azb, aindex, num;
00815
00816
00817 const float *loc = posB + 3*i;
00818 axb = (int)((loc[0] - min[0])*invpairdist);
00819 ayb = (int)((loc[1] - min[1])*invpairdist);
00820 azb = (int)((loc[2] - min[2])*invpairdist);
00821
00822
00823 if (axb >= xb) axb = xb-1;
00824 if (ayb >= yb) ayb = yb-1;
00825 if (azb >= zb) azb = zb-1;
00826
00827 aindex = azb * xytotb + ayb * xb + axb;
00828
00829
00830 if ((num = numinboxB[aindex]) == maxinboxB[aindex]) {
00831 boxatomB[aindex] = (int *) realloc(boxatomB[aindex], (num+4)*sizeof(int));
00832 maxinboxB[aindex] += 4;
00833 }
00834
00835
00836 boxatomB[aindex][num] = i;
00837 numinboxB[aindex]++;
00838 }
00839 }
00840 free(maxinboxB);
00841
00842
00843
00844 nbrlist = (int **) calloc(1, totb*sizeof(int *));
00845 if (make_neighborlist_sym(nbrlist, xb, yb, zb)) {
00846 if (boxatomA != NULL) {
00847 for (i=0; i<totb; i++) {
00848 if (boxatomA[i] != NULL) free(boxatomA[i]);
00849 }
00850 free(boxatomA);
00851 }
00852 if (boxatomB != NULL) {
00853 for (i=0; i<totb; i++) {
00854 if (boxatomB[i] != NULL) free(boxatomB[i]);
00855 }
00856 free(boxatomB);
00857 }
00858 if (nbrlist != NULL) {
00859 for (i=0; i<totb; i++) {
00860 if (nbrlist[i] != NULL) free(nbrlist[i]);
00861 }
00862 free(nbrlist);
00863 }
00864 free(numinboxA);
00865 free(numinboxB);
00866 msgErr << "Gridsearch memory allocation failed, bailing out" << sendmsg;
00867 return NULL;
00868 }
00869
00870
00871 GridSearchPair *head, *cur;
00872 head = (GridSearchPair *) malloc(sizeof(GridSearchPair));
00873 head->next = NULL;
00874 cur = head;
00875
00876 for (aindex = 0; aindex < totb; aindex++) {
00877 int *tmpbox, *tmpnbr, *nbr;
00878 tmpbox = boxatomA[aindex];
00879 tmpnbr = nbrlist[aindex];
00880 for (nbr = tmpnbr; (*nbr != -1) && (!maxpairsreached); nbr++) {
00881 int *nbrboxB = boxatomB[*nbr];
00882 for (i=0; (i<numinboxA[aindex]) && (!maxpairsreached); i++) {
00883 const float *p1;
00884 int ind1 = tmpbox[i];
00885 p1 = posA + 3*ind1;
00886 for (j=0; (j<numinboxB[*nbr]) && (!maxpairsreached); j++) {
00887 const float *p2;
00888 int ind2 = nbrboxB[j];
00889 p2 = posB + 3*ind2;
00890 if (!allow_double_counting && B[ind1] && A[ind2] && ind2<=ind1) continue;
00891 if (distance2(p1,p2) > sqdist) continue;
00892
00893 if (maxpairs > 0) {
00894 if (paircount >= maxpairs) {
00895 maxpairsreached = 1;
00896 continue;
00897 }
00898 }
00899
00900 add_link(cur, ind1, ind2);
00901 paircount++;
00902 cur = cur->next;
00903 cur->next = NULL;
00904 }
00905 }
00906 }
00907 }
00908
00909 for (i=0; i<totb; i++) {
00910 free(boxatomA[i]);
00911 free(boxatomB[i]);
00912 free(nbrlist[i]);
00913 }
00914 free(boxatomA);
00915 free(boxatomB);
00916 free(nbrlist);
00917 free(numinboxA);
00918 free(numinboxB);
00919
00920 cur = head->next;
00921 free(head);
00922
00923 if (maxpairsreached)
00924 msgErr << "vmdgridsearch3: exceeded pairlist sanity check, aborted" << sendmsg;
00925
00926 return cur;
00927 }
00928
00929
00930
00931
00932
00933 extern "C" void * find_within_routine( void *v );
00934
00935 struct AtomEntry {
00936 float x, y, z;
00937 int index;
00938 AtomEntry() {}
00939 AtomEntry(const float &_x, const float &_y, const float &_z, const int &_i)
00940 : x(_x), y(_y), z(_z), index(_i) {}
00941 };
00942
00943 typedef ResizeArray<AtomEntry> atomlist;
00944 struct FindWithinData {
00945 int nthreads;
00946 int tid;
00947 int totb;
00948 int xytotb;
00949 int xb;
00950 int yb;
00951 int zb;
00952 float r2;
00953 const float * xyz;
00954 const atomlist * flgatoms;
00955 const atomlist * otheratoms;
00956 int * flgs;
00957 FindWithinData() : flgatoms(0), otheratoms(0), flgs(0) {}
00958 ~FindWithinData() { if (flgs) free(flgs); }
00959 };
00960
00961 #define MAXGRIDDIM 31
00962 void find_within(const float *xyz, int *flgs, const int *others,
00963 int num, float r) {
00964 int i;
00965 float xmin, xmax, ymin, ymax, zmin, zmax;
00966 float oxmin, oymin, ozmin, oxmax, oymax, ozmax;
00967 float xwidth, ywidth, zwidth;
00968 const float *pos;
00969
00970
00971 if (!find_minmax_selected(num, flgs, xyz, xmin, ymin, zmin, xmax, ymax, zmax) ||
00972 !find_minmax_selected(num, others, xyz, oxmin, oymin, ozmin, oxmax, oymax, ozmax)) {
00973 memset(flgs, 0, num*sizeof(int));
00974 return;
00975 }
00976
00977
00978
00979 float size = xmax+ymax+zmax - (xmin+ymin+zmin);
00980 float osize = oxmax+oymax+ozmax - (oxmin+oymin+ozmin);
00981 if (osize < size) {
00982 xmin=oxmin;
00983 ymin=oymin;
00984 zmin=ozmin;
00985 xmax=oxmax;
00986 ymax=oymax;
00987 zmax=ozmax;
00988 }
00989
00990
00991
00992
00993 xwidth = (xmax-xmin)/(MAXGRIDDIM-1);
00994 if (xwidth < r) xwidth = r;
00995 ywidth = (ymax-ymin)/(MAXGRIDDIM-1);
00996 if (ywidth < r) ywidth = r;
00997 zwidth = (zmax-zmin)/(MAXGRIDDIM-1);
00998 if (zwidth < r) zwidth = r;
00999
01000
01001
01002 xmin -= xwidth;
01003 xmax += xwidth;
01004 ymin -= ywidth;
01005 ymax += ywidth;
01006 zmin -= zwidth;
01007 zmax += zwidth;
01008
01009
01010
01011 const int xb = (int)((xmax-xmin)/xwidth) + 1;
01012 const int yb = (int)((ymax-ymin)/ywidth) + 1;
01013 const int zb = (int)((zmax-zmin)/zwidth) + 1;
01014
01015 int xytotb = yb * xb;
01016 int totb = xytotb * zb;
01017
01018 atomlist* flgatoms = new atomlist[totb];
01019 atomlist* otheratoms = new atomlist[totb];
01020
01021 float ixwidth = 1.0f/xwidth;
01022 float iywidth = 1.0f/ywidth;
01023 float izwidth = 1.0f/zwidth;
01024 for (i=0; i<num; i++) {
01025 if (!flgs[i] && !others[i]) continue;
01026 pos=xyz+3*i;
01027 float xi = pos[0];
01028 float yi = pos[1];
01029 float zi = pos[2];
01030 if (xi<xmin || xi>xmax || yi<ymin || yi>ymax || zi<zmin || zi>zmax) {
01031 continue;
01032 }
01033 AtomEntry entry(xi,yi,zi,i);
01034 int axb = (int)((xi - xmin)*ixwidth);
01035 int ayb = (int)((yi - ymin)*iywidth);
01036 int azb = (int)((zi - zmin)*izwidth);
01037
01038
01039
01040 if (axb==xb) axb=xb-1;
01041 if (ayb==yb) ayb=yb-1;
01042 if (azb==zb) azb=zb-1;
01043
01044 int aindex = azb*xytotb + ayb*xb + axb;
01045 if (others[i]) otheratoms[aindex].append(entry);
01046 if ( flgs[i]) flgatoms[aindex].append(entry);
01047 }
01048
01049 memset(flgs, 0, num*sizeof(int));
01050 const float r2 = (float) (r*r);
01051
01052
01053 int nthreads;
01054 #ifdef VMDTHREADS
01055 nthreads = wkf_thread_numprocessors();
01056 wkf_thread_t * threads = (wkf_thread_t *)calloc(nthreads, sizeof(wkf_thread_t));
01057 #else
01058 nthreads = 1;
01059 #endif
01060 FindWithinData *data = new FindWithinData[nthreads];
01061 for (i=0; i<nthreads; i++) {
01062 data[i].nthreads = nthreads;
01063 data[i].tid = i;
01064 data[i].totb = totb;
01065 data[i].xytotb = xytotb;
01066 data[i].xb = xb;
01067 data[i].yb = yb;
01068 data[i].zb = zb;
01069 data[i].r2 = r2;
01070 data[i].xyz = xyz;
01071 data[i].flgatoms = flgatoms;
01072 data[i].otheratoms = otheratoms;
01073 data[i].flgs = (int *)calloc(num, sizeof(int));
01074 }
01075 #ifdef VMDTHREADS
01076 for (i=0; i<nthreads; i++) {
01077 wkf_thread_create(threads+i, find_within_routine, data+i);
01078 }
01079 for (i=0; i<nthreads; i++) {
01080 wkf_thread_join(threads[i], NULL);
01081 }
01082 free(threads);
01083 #else
01084 find_within_routine(data);
01085 #endif
01086
01087
01088 for (i=0; i<nthreads; i++) {
01089 const int *tflg = data[i].flgs;
01090 for (int j=0; j<num; j++) {
01091 flgs[j] |= tflg[j];
01092 }
01093 }
01094 delete [] data;
01095 delete [] flgatoms;
01096 delete [] otheratoms;
01097 }
01098
01099 extern "C" void * find_within_routine( void *v ) {
01100 FindWithinData *data = (FindWithinData *)v;
01101 const int nthreads = data->nthreads;
01102 const int tid = data->tid;
01103 const int totb = data->totb;
01104 const int xytotb = data->xytotb;
01105 const int xb = data->xb;
01106 const int yb = data->yb;
01107 const int zb = data->zb;
01108 const float r2 = data->r2;
01109 const atomlist * flgatoms = data->flgatoms;
01110 const atomlist * otheratoms = data->otheratoms;
01111 int * flgs = data->flgs;
01112
01113
01114
01115 for (int aindex = tid; aindex<totb; aindex += nthreads) {
01116
01117 int zi = aindex/xytotb;
01118 int ytmp = aindex - zi*xytotb;
01119 int yi = ytmp/xb;
01120 int xi = ytmp - yi*xb;
01121 int nbrs[14];
01122 int n=0;
01123 nbrs[n++] = aindex;
01124 if (xi < xb-1) nbrs[n++] = aindex + 1;
01125 if (yi < yb-1) nbrs[n++] = aindex + xb;
01126 if (zi < zb-1) nbrs[n++] = aindex + xytotb;
01127 if (xi < (xb-1) && yi < (yb-1)) nbrs[n++] = aindex + xb + 1;
01128 if (xi < (xb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + 1;
01129 if (yi < (yb-1) && zi < (zb-1)) nbrs[n++] = aindex + xytotb + xb;
01130 if (xi < (xb-1) && yi > 0) nbrs[n++] = aindex - xb + 1;
01131 if (xi > 0 && zi < (zb-1)) nbrs[n++] = aindex + xytotb - 1;
01132 if (yi > 0 && zi < (zb-1)) nbrs[n++] = aindex + xytotb - xb;
01133 if (xi < (xb-1) && yi < (yb-1) && zi < (zb-1))
01134 nbrs[n++] = aindex + xytotb + xb + 1;
01135 if (xi > 0 && yi < (yb-1) && zi < (zb-1))
01136 nbrs[n++] = aindex + xytotb + xb - 1;
01137 if (xi < (xb-1) && yi > 0 && zi < (zb-1))
01138 nbrs[n++] = aindex + xytotb - xb + 1;
01139 if (xi > 0 && yi > 0 && zi < (zb-1))
01140 nbrs[n++] = aindex + xytotb - xb - 1;
01141
01142 const atomlist& boxflg = flgatoms[aindex];
01143
01144 int i;
01145 for (i=0; i<boxflg.num(); i++) {
01146 const AtomEntry &flgentry = boxflg[i];
01147 int flgind = flgentry.index;
01148
01149
01150 for (int inbr=0; inbr<n; inbr++) {
01151 if (flgs[flgind]) break;
01152
01153
01154 int nbr = nbrs[inbr];
01155 const atomlist& nbrother = otheratoms[nbr];
01156 for (int j=0; j<nbrother.num(); j++) {
01157 const AtomEntry &otherentry = nbrother[j];
01158 float dx2 = flgentry.x - otherentry.x; dx2 *= dx2;
01159 float dy2 = flgentry.y - otherentry.y; dy2 *= dy2;
01160 float dz2 = flgentry.z - otherentry.z; dz2 *= dz2;
01161 if (dx2 + dy2 + dz2 < r2) {
01162 flgs[flgind] = 1;
01163 break;
01164 }
01165 }
01166 }
01167 }
01168
01169
01170 const atomlist& boxother = otheratoms[aindex];
01171
01172 for (int inbr=0; inbr<n; inbr++) {
01173 int nbr = nbrs[inbr];
01174
01175
01176 const atomlist& nbrflg = flgatoms[nbr];
01177
01178
01179 for (i=0; i<nbrflg.num(); i++) {
01180 const AtomEntry &flgentry = nbrflg[i];
01181 int flgind = flgentry.index;
01182
01183
01184 if (flgs[flgind]) continue;
01185 for (int j=0; j<boxother.num(); j++) {
01186 const AtomEntry &otherentry = boxother[j];
01187 float dx2 = flgentry.x - otherentry.x; dx2 *= dx2;
01188 float dy2 = flgentry.y - otherentry.y; dy2 *= dy2;
01189 float dz2 = flgentry.z - otherentry.z; dz2 *= dz2;
01190 if (dx2 + dy2 + dz2 < r2) {
01191 flgs[flgind] = 1;
01192 break;
01193 }
01194 }
01195 }
01196 }
01197 }
01198 return NULL;
01199 }
01200
01201