Example #1
0
GridSearchPairlist *vmd_gridsearch_bonds(const float *pos, const float *radii,
                                   int natoms, float pairdist, int maxpairs) {
  float min[3], max[3];
  int i, xb, yb, zb, xytotb, totb;
  int **boxatom, *numinbox, *maxinbox, **nbrlist;
  int numon = 0;
  float sidelen[3], volume;
  int paircount = 0;

  // find bounding box for selected atoms, and number of atoms in selection.
#if 1
  minmax_3fv_aligned(pos, natoms, min, max);
#else
  find_minmax_all(pos, natoms, min, max);
#endif

  // check for NaN coordinates propagating to the bounding box result
  if (!(max[0] >= min[0] && max[1] >= min[1] && max[2] >= min[2])) {
    msgErr << "vmd_gridsearch_bonds: NaN coordinates in bounds, aborting!" << sendmsg;
    return NULL;
  }

  // do sanity checks and complain if we've got bogus atom coordinates,
  // we shouldn't ever have density higher than 0.1 atom/A^3, but we'll
  // be generous and allow much higher densities.  
  if (maxpairs != -1) {
    vec_sub(sidelen, max, min);
    // include estimate for atom radius (1 Angstrom) in volume determination
    volume = fabsf((sidelen[0] + 2.0f) * (sidelen[1] + 2.0f) * (sidelen[2] + 2.0f));
    if ((numon / volume) > 1.0) {
      msgWarn << "vmd_gridsearch_bonds: insane atom density" << sendmsg;
    }
  }

  // I don't want the grid to get too large, otherwise I could run out
  // of memory.  Octrees would be cool, but I'll just limit the grid size
  // and let the performance degrade a little for pathological systems.
  // Note that pairdist^2 is what gets used for the actual distance checks;
  // from here on out pairdist is only used to set the grid size, so we 
  // can set it to anything larger than the original pairdist.
  const int MAXBOXES = 4000000;
  totb = MAXBOXES + 1;

  float newpairdist = pairdist;
  float xrange = max[0]-min[0];
  float yrange = max[1]-min[1];
  float zrange = max[2]-min[2];
  do {
    pairdist = newpairdist;
    const float invpairdist = 1.0f / pairdist; 
    xb = ((int)(xrange*invpairdist))+1;
    yb = ((int)(yrange*invpairdist))+1;
    zb = ((int)(zrange*invpairdist))+1;
    xytotb = yb * xb;
    totb = xytotb * zb;
    newpairdist = pairdist * 1.26f; // cbrt(2) is about 1.26
  } while (totb > MAXBOXES || totb < 1); // check for integer wraparound too
 
  // 2. Sort each atom into appropriate bins
  boxatom = (int **) calloc(1, totb*sizeof(int *));
  numinbox = (int *) calloc(1, totb*sizeof(int));
  maxinbox = (int *) calloc(1, totb*sizeof(int));
  if (boxatom == NULL || numinbox == NULL || maxinbox == NULL) {
    if (boxatom != NULL)
      free(boxatom);
    if (numinbox != NULL)
      free(numinbox);
    if (maxinbox != NULL)
      free(maxinbox);
    msgErr << "Bondsearch memory allocation failed, bailing out" << sendmsg;
    return NULL; // ran out of memory, bail out!
  }

  const float invpairdist = 1.0f / pairdist; 
  for (i=0; i<natoms; i++) {
    int axb, ayb, azb, aindex, num;

    // compute box index for new atom
    const float *loc = pos + 3L*i;
    axb = (int)((loc[0] - min[0])*invpairdist);
    ayb = (int)((loc[1] - min[1])*invpairdist);
    azb = (int)((loc[2] - min[2])*invpairdist);

    // clamp box indices to valid range in case of FP error
    if (axb >= xb) axb = xb-1;
    if (ayb >= yb) ayb = yb-1;
    if (azb >= zb) azb = zb-1;

    aindex = azb * xytotb + ayb * xb + axb;

    // grow box if necessary 
    if ((num = numinbox[aindex]) == maxinbox[aindex]) {
      boxatom[aindex] = (int *) realloc(boxatom[aindex], (num+4)*sizeof(int));
      maxinbox[aindex] += 4;
    }

    // store atom index in box
    boxatom[aindex][num] = i;
    numinbox[aindex]++;
  }
  free(maxinbox);
 
  nbrlist = (int **) calloc(1, totb*sizeof(int *));
  if (make_neighborlist(nbrlist, xb, yb, zb)) {
    if (boxatom != NULL) {
      for (i=0; i<totb; i++) {
        if (boxatom[i] != NULL) free(boxatom[i]);
      }
      free(boxatom);
    }
    if (nbrlist != NULL) {
      for (i=0; i<totb; i++) {
        if (nbrlist[i] != NULL) free(nbrlist[i]);
      }
      free(nbrlist);
    }
    free(numinbox);
    msgErr << "Bondsearch memory allocation failed, bailing out" << sendmsg;
    return NULL; // ran out of memory, bail out!
  }

  // if maxpairs is "unlimited", set it to the biggest positive int
  if (maxpairs < 0) {
    maxpairs = 2147483647;
  }

  // setup head of pairlist
  GridSearchPairlist *head, *cur;
  head = (GridSearchPairlist *) malloc(sizeof(GridSearchPairlist));
  head->next = NULL;
  paircount = vmd_bondsearch_thr(pos, radii, head, totb, 
                                 boxatom, numinbox, nbrlist, 
                                 maxpairs, pairdist);

  for (i=0; i<totb; i++) {
    free(boxatom[i]);
    free(nbrlist[i]);
  }
  free(boxatom);
  free(nbrlist);
  free(numinbox);

  cur = head->next;
  free(head);

  if (paircount > maxpairs) 
    msgErr << "vmdgridsearch_bonds: exceeded pairlist sanity check, aborted" << sendmsg;

  return cur;
}
Example #2
0
int main() {
  int i;
  float minfv[3], maxfv[3];
  float minf, maxf;
  int isz = 100000000;
  int sz = 3 * isz;
  int *on = (int *) malloc(isz * sizeof(int));
  float *fv = (float *) malloc(sz * sizeof(float));

  for (i=0; i<sz; i++) 
    fv[i] = (float) i; 

  wkf_timerhandle timer = wkf_timer_create();

  int j;
  for (j=0; j<1; j++) {
    memset(on, 0, isz*sizeof(int));

    wkf_timer_start(timer);
    minmax_1fv_aligned(fv, sz, &minf, &maxf);
    wkf_timer_stop(timer);
    printf("minmax_1fv_aligned: %f\n", wkf_timer_time(timer));
//  printf("min: %f max: %f\n", minf, maxf);

    wkf_timer_start(timer);
    minmax_3fv_aligned(fv, sz/3, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_3fv_aligned: %f\n", wkf_timer_time(timer));
    for (i=0; i<3; i++) {
      minf += minfv[i];
      maxf += maxfv[i];
    }

    // set exactly one selected atom to measure perf of the
    // fast first/last selection traversal loops
    on[isz/2 + 7] = 1;
    print_firstlast_selection(timer, isz, on);
    print_analyze_selection(timer, isz, on);

#if 1
    wkf_timer_start(timer);
    minmax_selected_3fv_aligned(fv, on, isz, 0, isz-1, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_selected_3fv_aligned(  0%%): %f\n", wkf_timer_time(timer));

    for (i=0; i<(isz-7); i+=8) {
      on[i+7] = 1;
    }
    print_analyze_selection(timer, isz, on);
    wkf_timer_start(timer);
    minmax_selected_3fv_aligned(fv, on, isz, 0, isz-1, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_selected_3fv_aligned( 12%%): %f\n", wkf_timer_time(timer));
    for (i=0; i<3; i++) {
      minf += minfv[i];
      maxf += maxfv[i];
    }


    for (i=0; i<(isz-7); i+=8) {
      on[i+6] = 1;
    }
    print_analyze_selection(timer, isz, on);
    wkf_timer_start(timer);
    minmax_selected_3fv_aligned(fv, on, isz, 0, isz-1, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_selected_3fv_aligned( 25%%): %f\n", wkf_timer_time(timer));
    for (i=0; i<3; i++) {
      minf += minfv[i];
      maxf += maxfv[i];
    }


    for (i=0; i<(isz-7); i+=8) {
      on[i+4] = 1;
      on[i+5] = 1;
      on[i+6] = 1;
      on[i+7] = 1;
    }
    print_analyze_selection(timer, isz, on);
    wkf_timer_start(timer);
    minmax_selected_3fv_aligned(fv, on, isz, 0, isz-1, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_selected_3fv_aligned( 50%%): %f\n", wkf_timer_time(timer));
    for (i=0; i<3; i++) {
      minf += minfv[i];
      maxf += maxfv[i];
    }


    for (i=0; i<isz; i++)
      on[i] = 1;
    print_analyze_selection(timer, isz, on);
    wkf_timer_start(timer);
    minmax_selected_3fv_aligned(fv, on, isz, 0, isz-1, minfv, maxfv);
    wkf_timer_stop(timer);
    printf("minmax_selected_3fv_aligned(100%%): %f\n", wkf_timer_time(timer));
    for (i=0; i<3; i++) {
      minf += minfv[i];
      maxf += maxfv[i];
    }
#endif

    msmparms mp;
    setupmsm(mp);
    wkf_timer_start(timer);
    testmsm(mp);
    wkf_timer_stop(timer);
    printf("MSM testmsm(): %f\n", wkf_timer_time(timer));
    finishmsm(mp);

    printf("\n");
  }

  wkf_timer_destroy(timer);  

  printf("checking sum: %g\n", minf+maxf);

  return 0;
}