Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SpatialSearch.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: SpatialSearch.C,v $
00013  *      $Author: akohlmey $     $Locker:  $             $State: Exp $
00014  *      $Revision: 1.19 $       $Date: 2011/02/03 16:40:08 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * Distance based bond search code 
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>         // needed for isdigit()
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   // return immediately if there are no atoms, or no atoms are on.
00048   if (n < 1) return;
00049 
00050   // initialize min/max to first 'on' atom, and advance the counter.
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 // find minmax of selected atoms.  Return true if minmax was found;
00073 // false if all flags are zero.
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 // old routine for finding min max of selected atoms
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   // return immediately if there are no atoms, or no atoms are on.
00116   if (n < 1) return;
00117 
00118   // init on count
00119   numon = 0;
00120 
00121   // find first on atom
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   // initialize min/max to first 'on' atom, and advance the counter.
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]; // 14 neighbors, and a -1 to mark end of the list
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; // mark end of list
00193 
00194         int *lst = (int *) malloc(n*sizeof(int));
00195         if (lst == NULL)
00196           return -1; // return on failed allocations
00197         memcpy(lst, nbrs, n*sizeof(int));
00198         nbrlist[aindex] = lst;
00199         aindex++;
00200       }
00201     }
00202   }
00203 
00204   return 0;
00205 }
00206 
00207 
00208 // symetrical version of neighbourlist (each cell has 27 neighbours, incl. itself, instead of just 14)
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]; // 27 neighbors, and a -1 to mark end of the list
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; // mark end of list
00251 
00252         int *lst = (int *) malloc(n*sizeof(int));
00253         if (lst == NULL)
00254           return -1; // return on failed allocations
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   // find bounding box for selected atoms, and number of atoms in selection.
00279   find_minmax(pos, natoms, on, min, max, &numon);
00280 
00281   // do sanity checks and complain if we've got bogus atom coordinates,
00282   // we shouldn't ever have density higher than 0.1 atom/A^3, but we'll
00283   // be generous and allow much higher densities.  
00284   if (maxpairs != -1) {
00285     vec_sub(sidelen, max, min);
00286     // include estimate for atom radius (1 Angstrom) in volume determination
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   // I don't want the grid to get too large, otherwise I could run out
00294   // of memory.  Octrees would be cool, but I'll just limit the grid size
00295   // and let the performance degrade a little for pathological systems.
00296   // Note that sqdist is what gets used for the actual distance checks;
00297   // from here on out pairdist is only used to set the grid size, so we 
00298   // can set it to anything larger than the original pairdist.
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; // cbrt(2) is about 1.26
00315   } while (totb > MAXBOXES || totb < 1); // check for integer wraparound too
00316  
00317   // 2. Sort each atom into appropriate bins
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; // ran out of memory, bail out!
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       // compute box index for new atom
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       // clamp box indices to valid range in case of FP error
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       // grow box if necessary
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       // store atom index in box
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; // ran out of memory, bail out!
00380   }
00381 
00382   // setup head of pairlist
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             // ignore pairs between atoms with nearly identical coords
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             // XXX double-counting still ignores atoms with same coords...
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   // on = union(A,B).  We grid all atoms, then allow pairs only when one
00477   // atom is A and the other atom is B.  An alternative scheme would be to
00478   // to grid the A and B atoms separately, and/or bin them separately, so
00479   // there would be fewer rejected pairs. 
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   // find bounding box for selected atoms
00492   find_minmax(pos, natoms, on, min, max, NULL);
00493 
00494   // do sanity checks and complain if we've got bogus atom coordinates,
00495   // we shouldn't ever have density higher than 0.1 atom/A^3, but we'll
00496   // be generous and allow much higher densities.
00497   if (maxpairs != -1) {
00498     vec_sub(sidelen, max, min);
00499     // include estimate for atom radius (1 Angstrom) in volume determination
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   // I don't want the grid to get too large, otherwise I could run out
00507   // of memory.  Octrees would be cool, but I'll just limit the grid size
00508   // and let the performance degrade a little for pathological systems.
00509   // Note that sqdist is what gets used for the actual distance checks;
00510   // from here on out pairdist is only used to set the grid size, so we 
00511   // can set it to anything larger than the original pairdist.
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; // cbrt(2) is about 1.26
00528   } while (totb > MAXBOXES || totb < 1); // check for integer wraparound too
00529  
00530   // 2. Sort each atom into appropriate bins
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; // ran out of memory, bail out!
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       // compute box index for new atom
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       // clamp box indices to valid range in case of FP error
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       // grow box if necessary
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       // store atom index in box
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; // ran out of memory, bail out!
00594   }
00595 
00596   // setup head of pairlist
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 // Like vmd_gridsearch2, but pairs up atoms from different locations and molecules.
00665 // By default, if (posA == posB), all bonds are unique. Otherwise, double-counting is allowed.
00666 // This can be overridden by setting allow_double_counting (true, false, or default=-1).
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) { //default
00674     if (posA == posB && natomsA == natomsB) 
00675       allow_double_counting = FALSE;
00676     else 
00677       allow_double_counting = TRUE;
00678   }
00679   
00680   // if same molecule and *A[] == *B[], it is a lot faster to use gridsearch1
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]; //tmp storage
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   // 1. Find grid size for binning
00704   // find bounding box for selected atoms
00705   find_minmax(posA, natomsA, A, min, max, &numonA);
00706   find_minmax(posB, natomsB, B, minB, maxB, &numonB);
00707 
00708   // If no atoms were selected we don't have to go on
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   // do sanity checks and complain if we've got bogus atom coordinates,
00717   // we shouldn't ever have density higher than 0.1 atom/A^3, but we'll
00718   // be generous and allow much higher densities.  
00719   if (maxpairs != -1) {
00720     vec_sub(sidelen, max, min);
00721     // include estimate for atom radius (1 Angstrom) in volume determination
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   // I don't want the grid to get too large, otherwise I could run out
00729   // of memory.  Octrees would be cool, but I'll just limit the grid size
00730   // and let the performance degrade a little for pathological systems.
00731   // Note that sqdist is what gets used for the actual distance checks;
00732   // from here on out pairdist is only used to set the grid size, so we 
00733   // can set it to anything larger than the original pairdist.
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; // cbrt(2) is about 1.26
00750   } while (totb > MAXBOXES || totb < 1); // check for integer wraparound too
00751  
00752   // 2. Sort each atom into appropriate bins
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; // ran out of memory, bail out!
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       // compute box index for new atom
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       // clamp box indices to valid range in case of FP error
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       // grow box if necessary
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       // store atom index in box
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; // ran out of memory, bail out!
00810   }
00811 
00812   for (i=0; i<natomsB; i++) {
00813     if (B[i]) {
00814       int axb, ayb, azb, aindex, num;
00815 
00816       // compute box index for new atom
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       // clamp box indices to valid range in case of FP error
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       // grow box if necessary
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       // store atom index in box
00836       boxatomB[aindex][num] = i;
00837       numinboxB[aindex]++;
00838     }
00839   }
00840   free(maxinboxB);
00841   
00842 
00843   // 3. Build pairlists of atoms less than sqrtdist apart
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; // ran out of memory, bail out!
00868   }
00869 
00870   // setup head of pairlist
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; //don't double-count bonds XXX
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 // Multithreaded implementation of find_within()  
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   // find min/max bounds of atom coordinates in flgs
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   // Find the set of atoms with the smallest extent; here we use the sum
00978   // of the box dimensions though other choices might be better.
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   // Generate a grid of mesh size r based on the computed size of the molecule.
00991   // We limit the size of the grid cell dimensions so that we don't get too
00992   // many grid cells.
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   // Adjust the bounds so that we include atoms that are in the outermost
01001   // grid cells.
01002   xmin -= xwidth;
01003   xmax += xwidth;
01004   ymin -= ywidth;
01005   ymax += ywidth;
01006   zmin -= zwidth;
01007   zmax += zwidth;
01008 
01009   // The number of grid cells needed in each dimension is 
01010   // (int)((xmax-xmin)/xwidth) + 1
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     // Due to floating point error in the calcuation of bin widths, we 
01039     // have to range clamp the computed box indices.
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   // set up workspace for multithreaded calculation
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   // combine results
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   // Loop over boxes, checking for flg atoms and other atoms within one
01114   // box of each other.  When one is found, mark the flag.
01115   for (int aindex = tid; aindex<totb; aindex += nthreads) {
01116     // Figure out the neighbors for this box
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;     // Always include self
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     // Compare the atoms in boxflg to those in nbrother
01144     int i;
01145     for (i=0; i<boxflg.num(); i++) {
01146       const AtomEntry &flgentry = boxflg[i];
01147       int flgind = flgentry.index;
01148 
01149       // Compare flag atoms in this box to other atoms in neighbor boxes,
01150       for (int inbr=0; inbr<n; inbr++) {  // Loop over neighbors
01151         if (flgs[flgind]) break;
01152   
01153         // Fetch a neighboring otheratoms to compare to boxflg
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     // compare other atoms in this box to flag atoms in the neighbors.
01170     const atomlist& boxother = otheratoms[aindex];
01171 
01172     for (int inbr=0; inbr<n; inbr++) {  // Loop over neighbors
01173       int nbr = nbrs[inbr];
01174 
01175       // Fetch a neighboring flgatoms to compare to boxother 
01176       const atomlist& nbrflg = flgatoms[nbr];
01177 
01178       // Compare the atoms in boxother to those in nbrflg
01179       for (i=0; i<nbrflg.num(); i++) {
01180         const AtomEntry &flgentry = nbrflg[i];
01181         int flgind = flgentry.index;
01182         // The next test helps a lot when the boxes are large, but hurts
01183         // a little when the boxes are small.
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 

Generated on Tue May 22 01:48:12 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002