Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/linkedcell.cpp

    r717e0c ra67d19  
    4545  max.Zero();
    4646  min.Zero();
    47   Log() << Verbose(1) << "Begin of LinkedCell" << endl;
    48   if (set->IsEmpty()) {
    49     eLog() << Verbose(1) << "set contains no linked cell nodes!" << endl;
     47  DoLog(1) && (Log() << Verbose(1) << "Begin of LinkedCell" << endl);
     48  if ((set == NULL) || (set->IsEmpty())) {
     49    DoeLog(1) && (eLog()<< Verbose(1) << "set is NULL or contains no linked cell nodes!" << endl);
    5050    return;
    5151  }
     
    6868    set->GoToNext();
    6969  }
    70   Log() << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
     70  DoLog(2) && (Log() << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl);
    7171
    7272  // 2. find then number of cells per axis
     
    7474    N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
    7575  }
    76   Log() << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
     76  DoLog(2) && (Log() << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl);
    7777
    7878  // 3. allocate the lists
    79   Log() << Verbose(2) << "Allocating cells ... ";
     79  DoLog(2) && (Log() << Verbose(2) << "Allocating cells ... ");
    8080  if (LC != NULL) {
    81     eLog() << Verbose(1) << "Linked Cell list is already allocated, I do nothing." << endl;
     81    DoeLog(1) && (eLog()<< Verbose(1) << "Linked Cell list is already allocated, I do nothing." << endl);
    8282    return;
    8383  }
     
    8686    LC [index].clear();
    8787  }
    88   Log() << Verbose(0) << "done."  << endl;
     88  DoLog(0) && (Log() << Verbose(0) << "done."  << endl);
    8989
    9090  // 4. put each atom into its respective cell
    91   Log() << Verbose(2) << "Filling cells ... ";
     91  DoLog(2) && (Log() << Verbose(2) << "Filling cells ... ");
    9292  set->GoToFirst();
    9393  while (!set->IsEnd()) {
     
    101101    set->GoToNext();
    102102  }
    103   Log() << Verbose(0) << "done."  << endl;
    104   Log() << Verbose(1) << "End of LinkedCell" << endl;
     103  DoLog(0) && (Log() << Verbose(0) << "done."  << endl);
     104  DoLog(1) && (Log() << Verbose(1) << "End of LinkedCell" << endl);
    105105};
    106106
     
    120120  max.Zero();
    121121  min.Zero();
    122   Log() << Verbose(1) << "Begin of LinkedCell" << endl;
     122  DoLog(1) && (Log() << Verbose(1) << "Begin of LinkedCell" << endl);
    123123  if (set->empty()) {
    124     eLog() << Verbose(1) << "set contains no linked cell nodes!" << endl;
     124    DoeLog(1) && (eLog()<< Verbose(1) << "set contains no linked cell nodes!" << endl);
    125125    return;
    126126  }
     
    140140    }
    141141  }
    142   Log() << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
     142  DoLog(2) && (Log() << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl);
    143143
    144144  // 2. find then number of cells per axis
     
    146146    N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
    147147  }
    148   Log() << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
     148  DoLog(2) && (Log() << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl);
    149149
    150150  // 3. allocate the lists
    151   Log() << Verbose(2) << "Allocating cells ... ";
     151  DoLog(2) && (Log() << Verbose(2) << "Allocating cells ... ");
    152152  if (LC != NULL) {
    153     eLog() << Verbose(1) << "Linked Cell list is already allocated, I do nothing." << endl;
     153    DoeLog(1) && (eLog()<< Verbose(1) << "Linked Cell list is already allocated, I do nothing." << endl);
    154154    return;
    155155  }
     
    158158    LC [index].clear();
    159159  }
    160   Log() << Verbose(0) << "done."  << endl;
     160  DoLog(0) && (Log() << Verbose(0) << "done."  << endl);
    161161
    162162  // 4. put each atom into its respective cell
    163   Log() << Verbose(2) << "Filling cells ... ";
     163  DoLog(2) && (Log() << Verbose(2) << "Filling cells ... ");
    164164  for (LinkedNodes::iterator Runner = set->begin(); Runner != set->end(); Runner++) {
    165165    Walker = *Runner;
     
    171171    //Log() << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    172172  }
    173   Log() << Verbose(0) << "done."  << endl;
    174   Log() << Verbose(1) << "End of LinkedCell" << endl;
     173  DoLog(0) && (Log() << Verbose(0) << "done."  << endl);
     174  DoLog(1) && (Log() << Verbose(1) << "End of LinkedCell" << endl);
    175175};
    176176
     
    199199    status = status && ((n[i] >=0) && (n[i] < N[i]));
    200200  if (!status)
    201   eLog() << Verbose(1) << "indices are out of bounds!" << endl;
     201  DoeLog(1) && (eLog()<< Verbose(1) << "indices are out of bounds!" << endl);
    202202  return status;
    203203};
     
    220220 * \return LinkedAtoms pointer to current cell, NULL if LinkedCell::n[] are out of bounds.
    221221 */
    222 const LinkedNodes* LinkedCell::GetCurrentCell() const
     222const LinkedCell::LinkedNodes* LinkedCell::GetCurrentCell() const
    223223{
    224224  if (CheckBounds()) {
     
    234234 * \return LinkedAtoms pointer to current cell, NULL if LinkedCell::n[]+relative[] are out of bounds.
    235235 */
    236 const LinkedNodes* LinkedCell::GetRelativeToCurrentCell(const int relative[NDIM]) const
     236const LinkedCell::LinkedNodes* LinkedCell::GetRelativeToCurrentCell(const int relative[NDIM]) const
    237237{
    238238  if (CheckBounds(relative)) {
     
    242242    return NULL;
    243243  }
     244};
     245
     246/** Set the index to the cell containing a given Vector *x.
     247 * \param *x Vector with coordinates
     248 * \return Vector is inside bounding box - true, else - false
     249 */
     250bool LinkedCell::SetIndexToVector(const Vector * const x) const
     251{
     252  for (int i=0;i<NDIM;i++)
     253    n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);
     254
     255  return CheckBounds();
    244256};
    245257
     
    260272    return status;
    261273  } else {
    262     eLog() << Verbose(1) << "Node at " << *Walker << " is out of bounds." << endl;
     274    DoeLog(1) && (eLog()<< Verbose(1) << "Node at " << *Walker << " is out of bounds." << endl);
    263275    return false;
    264276  }
     
    268280 * \param *lower lower bounds
    269281 * \param *upper upper bounds
    270  */
    271 void LinkedCell::GetNeighbourBounds(int lower[NDIM], int upper[NDIM]) const
    272 {
    273   for (int i=0;i<NDIM;i++) {
    274     lower[i] = ((n[i]-1) >= 0) ? n[i]-1 : 0;
    275     upper[i] = ((n[i]+1) < N[i]) ? n[i]+1 : N[i]-1;
    276     //Log() << Verbose(0) << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    277     // check for this axis whether the point is outside of our grid
     282 * \param step how deep to check the neighbouring cells (i.e. number of layers to check)
     283 */
     284void LinkedCell::GetNeighbourBounds(int lower[NDIM], int upper[NDIM], int step) const
     285{
     286  for (int i=0;i<NDIM;i++) {
     287    lower[i] = n[i];
     288    for (int s=step; s>0;--s)
     289      if ((n[i]-s) >= 0) {
     290        lower[i] = n[i]-s;
     291        break;
     292      }
     293    upper[i] = n[i];
     294    for (int s=step; s>0;--s)
     295      if ((n[i]+s) < N[i]) {
     296        upper[i] = n[i]+s;
     297        break;
     298      }
     299    //Log() << Verbose(0) << "axis " << i << " has bounds [" << lower[i] << "," << upper[i] << "]" << endl;
     300  }
     301};
     302
     303/** Returns a list with all neighbours from the current LinkedCell::index.
     304 * \param distance (if no distance, then adjacent cells are taken)
     305 * \return list of tesselpoints
     306 */
     307LinkedCell::LinkedNodes* LinkedCell::GetallNeighbours(const double distance) const
     308{
     309  int Nlower[NDIM], Nupper[NDIM];
     310  TesselPoint *Walker = NULL;
     311  LinkedNodes *TesselList = new LinkedNodes;
     312
     313  // then go through the current and all neighbouring cells and check the contained points for possible candidates
     314  const int step = (distance == 0) ? 1 : (int)floor(distance/RADIUS + 1.);
     315  GetNeighbourBounds(Nlower, Nupper, step);
     316
     317  //Log() << Verbose(0) << endl;
     318  for (n[0] = Nlower[0]; n[0] <= Nupper[0]; n[0]++)
     319    for (n[1] = Nlower[1]; n[1] <= Nupper[1]; n[1]++)
     320      for (n[2] = Nlower[2]; n[2] <= Nupper[2]; n[2]++) {
     321        const LinkedNodes *List = GetCurrentCell();
     322        //Log() << Verbose(1) << "Current cell is " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
     323        if (List != NULL) {
     324          for (LinkedNodes::const_iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     325            Walker = *Runner;
     326            TesselList->push_back(Walker);
     327          }
     328        }
     329      }
     330  return TesselList;
     331};
     332
     333/** Set the index to the cell containing a given Vector *x, which is not inside the LinkedCell's domain
     334 * Note that as we have to check distance from every corner of the closest cell, this function is faw more
     335 * expensive and if Vector is known to be inside LinkedCell's domain, then SetIndexToVector() should be used.
     336 * \param *x Vector with coordinates
     337 * \return minimum squared distance of cell to given vector (if inside of domain, distance is 0)
     338 */
     339double LinkedCell::SetClosestIndexToOutsideVector(const Vector * const x) const
     340{
     341  for (int i=0;i<NDIM;i++) {
     342    n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);
    278343    if (n[i] < 0)
    279       upper[i] = lower[i];
    280     if (n[i] > N[i])
    281       lower[i] = upper[i];
    282 
    283     //Log() << Verbose(0) << "axis " << i << " has bounds [" << lower[i] << "," << upper[i] << "]" << endl;
    284   }
    285 };
    286 
    287 /** Calculates the index for a given Vector *x.
    288  * \param *x Vector with coordinates
    289  * \return Vector is inside bounding box - true, else - false
    290  */
    291 bool LinkedCell::SetIndexToVector(const Vector * const x) const
    292 {
    293   bool status = true;
    294   for (int i=0;i<NDIM;i++) {
    295     n[i] = (int)floor((x->x[i] - min.x[i])/RADIUS);
    296     if (max.x[i] < x->x[i])
    297       status = false;
    298     if (min.x[i] > x->x[i])
    299       status = false;
    300   }
    301   return status;
    302 };
    303 
     344      n[i] = 0;
     345    if (n[i] >= N[i])
     346      n[i] = N[i]-1;
     347  }
     348
     349  // calculate distance of cell to vector
     350  double distanceSquared = 0.;
     351  bool outside = true;  // flag whether x is found in- or outside of LinkedCell's domain/closest cell
     352  Vector corner; // current corner of closest cell
     353  Vector tester; // Vector pointing from corner to center of closest cell
     354  Vector Distance;  // Vector from corner of closest cell to x
     355
     356  Vector center;  // center of the closest cell
     357  for (int i=0;i<NDIM;i++)
     358    center.x[i] = min.x[i]+((double)n[i]+.5)*RADIUS;
     359
     360  int c[NDIM];
     361  for (c[0]=0;c[0]<=1;c[0]++)
     362    for (c[1]=0; c[1]<=1;c[1]++)
     363      for (c[2]=0; c[2]<=1;c[2]++) {
     364        // set up corner
     365        for (int i=0;i<NDIM;i++)
     366          corner.x[i] = min.x[i]+RADIUS*((double)n[i]+c[i]);
     367        // set up distance vector
     368        Distance.CopyVector(x);
     369        Distance.SubtractVector(&corner);
     370        const double dist = Distance.NormSquared();
     371        // check whether distance is smaller
     372        if (dist< distanceSquared)
     373          distanceSquared = dist;
     374        // check whether distance vector goes inside or outside
     375        tester.CopyVector(&center);
     376        tester.SubtractVector(&corner);
     377        if (tester.ScalarProduct(&Distance) < 0)
     378          outside = false;
     379      }
     380  return (outside ? distanceSquared : 0.);
     381};
     382
     383/** Returns a list of all TesselPoint with distance less than \a radius to \a *Center.
     384 * \param radius radius of sphere
     385 * \param *center center of sphere
     386 * \return list of all points inside sphere
     387 */
     388LinkedCell::LinkedNodes* LinkedCell::GetPointsInsideSphere(const double radius, const Vector * const center) const
     389{
     390  const double radiusSquared = radius*radius;
     391  TesselPoint *Walker = NULL;
     392  LinkedNodes *TesselList = new LinkedNodes;
     393  LinkedNodes *NeighbourList = NULL;
     394
     395  // set index of LC to center of sphere
     396  const double dist = SetClosestIndexToOutsideVector(center);
     397  if (dist > 2.*radius) {
     398    DoeLog(1) && (eLog()<< Verbose(1) << "Vector " << *center << " is too far away from any atom in LinkedCell's bounding box." << endl);
     399    return TesselList;
     400  } else
     401    DoLog(1) && (Log() << Verbose(1) << "Distance of closest cell to center of sphere with radius " << radius << " is " << dist << "." << endl);
     402
     403  // gather all neighbours first, then look who fulfills distance criteria
     404  NeighbourList = GetallNeighbours(2.*radius-dist);
     405  //Log() << Verbose(1) << "I found " << NeighbourList->size() << " neighbours to check." << endl;
     406  if (NeighbourList != NULL) {
     407    for (LinkedNodes::const_iterator Runner = NeighbourList->begin(); Runner != NeighbourList->end(); Runner++) {
     408      Walker = *Runner;
     409      //Log() << Verbose(1) << "Current neighbour is at " << *Walker->node << "." << endl;
     410      if ((center->DistanceSquared(Walker->node) - radiusSquared) < MYEPSILON) {
     411        TesselList->push_back(Walker);
     412      }
     413    }
     414    delete(NeighbourList);
     415  } else
     416    DoeLog(2) && (eLog()<< Verbose(2) << "Around vector " << *center << " there are no atoms." << endl);
     417  return TesselList;
     418};
Note: See TracChangeset for help on using the changeset viewer.