MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HGRID_3D.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "HGRID_3D.h"
27 
31 void HGRID_3D::CheckCell_current(int x, int y, int z, int l, HGrid *grid)
32 {
33  int bucket = grid->ComputeHashBucketIndex(x,y,z,l);
34  if (grid->bucketIsChecked[bucket]) { return; }
35  BaseParticle* p1 = grid->objectBucket[bucket];
36 
37  while (p1!=NULL)
38  {
40  while (p2!=NULL)
41  {
43  //Check if the particle realy is in the target cell (i.e. no hashing error has occured)
44  if ((p1->get_HGRID_x() == p2->get_HGRID_x()) && (p1->get_HGRID_y() == p2->get_HGRID_y()) && (p1->get_HGRID_z() == p2->get_HGRID_z()) && (p1->get_HGRID_Level() == p2->get_HGRID_Level()))
45  {
47  }
48  p2 = p2->get_HGRID_NextObject();
49  }
50  p1 = p1->get_HGRID_NextObject();
51  }
52  grid->bucketIsChecked[bucket] = true;
53 }
54 
58 void HGRID_3D::CheckCell(int x, int y, int z, int l, BaseParticle *obj, HGrid *grid)
59 {
60  int bucket = grid->ComputeHashBucketIndex(x,y,z,l);
61 
63  if ((obj->get_HGRID_x() == x) && (obj->get_HGRID_y() == y) && (obj->get_HGRID_z() == z) && (obj->get_HGRID_Level() == l)) { return; }
64 
65  // Loop through all objects in the bucket to find nearby objects
66  BaseParticle *p = grid->objectBucket[bucket];
67 
68  while (p!=NULL)
69  {
71  //Check if the particle realy is in the target cell (i.e. no hashing error has occured)
72  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_z() == z) && (p->get_HGRID_Level() == l))
73  {
75  }
76  p = p->get_HGRID_NextObject();
77  }
78 }
79 
84 {
85  unsigned int startLevel = obj->get_HGRID_Level();
86 
87  int x, y, z;
88  Mdouble inv_size;
89 
90  switch(getHGridMethod())
91  {
92  case BOTTOMUP:
93  {
94  int occupiedLevelsMask = grid->occupiedLevelsMask >> obj->get_HGRID_Level();
95  for (unsigned int level = startLevel; level < grid->cellSizes_.size(); occupiedLevelsMask >>= 1, level++)
96  {
97  // If no objects in rest of grid, stop now
98  if (occupiedLevelsMask == 0) break;
99 
100  // If no objects at this level, go on to the next level
101  if ((occupiedLevelsMask & 1) == 0) continue;
102 
103  if (level == startLevel)
104  {
105  x = obj->get_HGRID_x();
106  y = obj->get_HGRID_y();
107  z = obj->get_HGRID_z();
108 
109  CheckCell_current(x, y, z, level, grid);
110 
111  CheckCell(x+1, y-1, z , level, obj, grid);
112  CheckCell(x+1, y, z , level, obj, grid);
113  CheckCell(x+1, y+1, z , level, obj, grid);
114 
115  CheckCell(x+1, y-1, z+1, level, obj, grid);
116  CheckCell(x+1, y, z+1, level, obj, grid);
117  CheckCell(x+1, y+1, z+1, level, obj, grid);
118 
119  CheckCell(x+1, y-1, z-1, level, obj, grid);
120  CheckCell(x+1, y, z-1, level, obj, grid);
121  CheckCell(x+1, y+1, z-1, level, obj, grid);
122 
123  CheckCell(x , y+1, z , level, obj, grid);
124  CheckCell(x , y, z-1, level, obj, grid);
125  CheckCell(x , y+1, z-1, level, obj, grid);
126  CheckCell(x , y+1, z+1, level, obj, grid);
127  }
128  else
129  {
130  int xs,ys,zs,xe,ye,ze;
131  inv_size = grid->invCellSizes_[level];
132  xs = (int) floor((obj->get_Position().X-obj->get_InteractionRadius()) * inv_size - 0.5);
133  xe = (int) floor((obj->get_Position().X+obj->get_InteractionRadius()) * inv_size + 0.5);
134  ys = (int) floor((obj->get_Position().Y-obj->get_InteractionRadius()) * inv_size - 0.5);
135  ye = (int) floor((obj->get_Position().Y+obj->get_InteractionRadius()) * inv_size + 0.5);
136  zs = (int) floor((obj->get_Position().Z-obj->get_InteractionRadius()) * inv_size - 0.5);
137  ze = (int) floor((obj->get_Position().Z+obj->get_InteractionRadius()) * inv_size + 0.5);
138  for(x=xs;x<=xe;x++)
139  {
140  for(y=ys;y<=ye;y++)
141  {
142  for(z=zs;z<=ze;z++)
143  {
144  CheckCell(x,y,z,level,obj,grid);
145  }
146  }
147  }
148  }
149  }
150  break;
151  }
152  case TOPDOWN:
153  {
154  int occupiedLevelsMask = grid->occupiedLevelsMask;
155  for (unsigned int level = 0; level <=startLevel; occupiedLevelsMask >>= 1, level++)
156  {
157  // If no objects in rest of grid, stop now
158  if (occupiedLevelsMask == 0) break;
159 
160  // If no objects at this level, go on to the next level
161  if ((occupiedLevelsMask & 1) == 0) continue;
162 
163  if (level == startLevel)
164  {
165  x = obj->get_HGRID_x();
166  y = obj->get_HGRID_y();
167  z = obj->get_HGRID_z();
168 
169  CheckCell_current(x, y, z, level, grid);
170 
171  CheckCell(x+1, y-1, z , level, obj, grid);
172  CheckCell(x+1, y, z , level, obj, grid);
173  CheckCell(x+1, y+1, z , level, obj, grid);
174 
175  CheckCell(x+1, y-1, z+1, level, obj, grid);
176  CheckCell(x+1, y, z+1, level, obj, grid);
177  CheckCell(x+1, y+1, z+1, level, obj, grid);
178 
179  CheckCell(x+1, y-1, z-1, level, obj, grid);
180  CheckCell(x+1, y, z-1, level, obj, grid);
181  CheckCell(x+1, y+1, z-1, level, obj, grid);
182 
183  CheckCell(x , y+1, z , level, obj, grid);
184  CheckCell(x , y, z-1, level, obj, grid);
185  CheckCell(x , y+1, z-1, level, obj, grid);
186  CheckCell(x , y+1, z+1, level, obj, grid);
187  }
188  else
189  {
190  int xs,ys,zs,xe,ye,ze;
191  inv_size = grid->invCellSizes_[level];
192  xs = (int) floor((obj->get_Position().X-obj->get_InteractionRadius()) * inv_size - 0.5);
193  xe = (int) floor((obj->get_Position().X+obj->get_InteractionRadius()) * inv_size + 0.5);
194  ys = (int) floor((obj->get_Position().Y-obj->get_InteractionRadius()) * inv_size - 0.5);
195  ye = (int) floor((obj->get_Position().Y+obj->get_InteractionRadius()) * inv_size + 0.5);
196  zs = (int) floor((obj->get_Position().Z-obj->get_InteractionRadius()) * inv_size - 0.5);
197  ze = (int) floor((obj->get_Position().Z+obj->get_InteractionRadius()) * inv_size + 0.5);
198  for(x=xs;x<=xe;x++)
199  {
200  for(y=ys;y<=ye;y++)
201  {
202  for(z=zs;z<=ze;z++)
203  {
204  CheckCell(x,y,z,level,obj,grid);
205  }
206  }
207  }
208  }
209  }
210  break;
211  }
212  }
213 }
214 
215 
221 {
222  int l = obj->get_HGRID_Level();
223  Mdouble inv_size = grid->invCellSizes_[l];
224 
225  int x=(int)floor(obj->get_Position().X * inv_size);
226  int y=(int)floor(obj->get_Position().Y * inv_size);
227  int z=(int)floor(obj->get_Position().Z * inv_size);
228 
229 #ifdef ContactListHgrid
230  if(obj->get_HGRID_x()!=x||obj->get_HGRID_y()!=y||obj->get_HGRID_z()!=z||obj->get_PeriodicFromParticle())
231  {
232  if(!obj->get_PeriodicFromParticle())
233  {
234  int bucket = grid->ComputeHashBucketIndex(x, y, z, l);
235 
236  //First the object has to be removed
238  //Also remove all contact associated with it
239  getPossibleContactList().remove_ParticlePosibleContacts(obj);
240 
241  //And now reinserted
242  obj->set_HGRID_NextObject(grid->objectBucket[bucket]);
243  if(grid->objectBucket[bucket])
244  grid->objectBucket[bucket]->set_HGRID_PrevObject(obj);
245  obj->set_HGRID_PrevObject(0);
246  grid->objectBucket[bucket] = obj;
247  }
248 
249  obj->set_HGRID_x(x);
250  obj->set_HGRID_y(y);
251  obj->set_HGRID_z(z);
252  InsertObjAgainstGrid(grid, obj);
253  }
254 #else
255  int bucket = grid->ComputeHashBucketIndex(x,y,z,l);
256 
257  obj->set_HGRID_NextObject(grid->objectBucket[bucket]);
258  if(grid->objectBucket[bucket])
259  grid->objectBucket[bucket]->set_HGRID_PrevObject(obj);
260  obj->set_HGRID_PrevObject(0);
261  grid->objectBucket[bucket] = obj;
262 
263  obj->set_HGRID_x(x);
264  obj->set_HGRID_y(y);
265  obj->set_HGRID_z(z);
266 #endif
267 }
268 
270 {
271  int bucket = grid->ComputeHashBucketIndex(obj->get_HGRID_x(),obj->get_HGRID_y(), obj->get_HGRID_z(), obj->get_HGRID_Level());
272  if(obj->get_HGRID_PrevObject())
274  else
275  if(grid->objectBucket[bucket]==obj)
276  grid->objectBucket[bucket]=obj->get_HGRID_NextObject();
277 
278  if(obj->get_HGRID_NextObject())
280 }
281 
286 bool HGRID_3D::TestCell(int x, int y, int z, int l, BaseParticle *obj, HGrid *grid)
287 {
288  bool Test = true;
289 
290  // Loop through all objects in the bucket to find nearby objects
291  int bucket = grid->ComputeHashBucketIndex(x,y,z,l);
292  BaseParticle *p = grid->objectBucket[bucket];
293 
294  while (Test && p!=NULL)
295  {
296  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_z() == z) && (p->get_HGRID_Level() == l))
297  {
298  Test = Test && TestObject(obj,p);
299  }
300  p = p->get_HGRID_NextObject();
301  }
302 
303  return Test;
304 }
305 
311 {
312  bool Test = true;
313 
314  int x, y, z;
315  Mdouble inv_size;
316  int occupiedLevelsMask = grid->occupiedLevelsMask;
317 
318  for (unsigned int level = 0; level < grid->cellSizes_.size() && Test; occupiedLevelsMask >>= 1, level++)
319  {
320  // If no objects in rest of grid, stop now
321  if (occupiedLevelsMask == 0) break;
322 
323  // If no objects at this level, go on to the next level
324  if ((occupiedLevelsMask & 1) == 0) continue;
325 
326  // Treat level as a third dimension coordinate
327  inv_size = grid->invCellSizes_[level];
328 
329  x = (int)floor(obj->get_Position().X * inv_size);
330  y = (int)floor(obj->get_Position().Y * inv_size);
331  z = (int)floor(obj->get_Position().Z * inv_size);
332 
333  Test = Test
334  && TestCell(x , y , z , level, obj, grid)
335  && TestCell(x , y-1, z , level, obj, grid)
336  && TestCell(x , y+1, z , level, obj, grid)
337  && TestCell(x-1, y , z , level, obj, grid)
338  && TestCell(x+1, y , z , level, obj, grid)
339  && TestCell(x-1, y-1, z , level, obj, grid)
340  && TestCell(x-1, y+1, z , level, obj, grid)
341  && TestCell(x+1, y-1, z , level, obj, grid)
342  && TestCell(x+1, y+1, z , level, obj, grid)
343 
344  && TestCell(x , y , z-1, level, obj, grid)
345  && TestCell(x , y-1, z-1, level, obj, grid)
346  && TestCell(x , y+1, z-1, level, obj, grid)
347  && TestCell(x-1, y , z-1, level, obj, grid)
348  && TestCell(x+1, y , z-1, level, obj, grid)
349  && TestCell(x-1, y-1, z-1, level, obj, grid)
350  && TestCell(x-1, y+1, z-1, level, obj, grid)
351  && TestCell(x+1, y-1, z-1, level, obj, grid)
352  && TestCell(x+1, y+1, z-1, level, obj, grid)
353 
354  && TestCell(x , y , z+1, level, obj, grid)
355  && TestCell(x , y-1, z+1, level, obj, grid)
356  && TestCell(x , y+1, z+1, level, obj, grid)
357  && TestCell(x-1, y , z+1, level, obj, grid)
358  && TestCell(x+1, y , z+1, level, obj, grid)
359  && TestCell(x-1, y-1, z+1, level, obj, grid)
360  && TestCell(x-1, y+1, z+1, level, obj, grid)
361  && TestCell(x+1, y-1, z+1, level, obj, grid)
362  && TestCell(x+1, y+1, z+1, level, obj, grid);
363  } //end for level
364 
365  return Test;
366 }
367 
368 #ifdef ContactListHgrid
369 void HGRID_3D::InsertCell(int x, int y, int z, int l, BaseParticle *obj, HGrid *grid)
370 {
371  // Loop through all objects in the bucket to find nearby objects
372  int bucket = grid->ComputeHashBucketIndex(x,y,z,l);
373  BaseParticle *p = grid->objectBucket[bucket];
374 
375  while (p!=NULL)
376  {
377  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_z() == z) && (p->get_HGRID_Level() == l) && (obj!=p))
378  {
379  getPossibleContactList().add_PossibleContact(obj,p);
380  }
381  p = p->get_HGRID_NextObject();
382  }
383 }
384 
385 void HGRID_3D::InsertObjAgainstGrid(HGrid *grid, BaseParticle *obj)
386 {
387  int xmin,xmax;
388  int ymin,ymax;
389  int zmin,zmax;
390  Mdouble inv_size;
391  int occupiedLevelsMask = grid->occupiedLevelsMask;
392 
393  inv_size=grid->inv_size[obj->get_HGRID_Level()];
394 
395  double ownXMin=(obj->get_HGRID_x()-0.5)/inv_size;
396  double ownXMax=(obj->get_HGRID_x()+1.5)/inv_size;
397  double ownYMin=(obj->get_HGRID_y()-0.5)/inv_size;
398  double ownYMax=(obj->get_HGRID_y()+1.5)/inv_size;
399  double ownZMin=(obj->get_HGRID_z()-0.5)/inv_size;
400  double ownZMax=(obj->get_HGRID_z()+1.5)/inv_size;
401 
402  for (int level = 0; level < grid->HGRID_MAX_LEVELS; occupiedLevelsMask >>= 1, level++)
403  {
404  // If no objects in rest of grid, stop now
405  if (occupiedLevelsMask == 0) break;
406 
407  // If no objects at this level, go on to the next level
408  if ((occupiedLevelsMask & 1) == 0) continue;
409 
410  // Treat level as a third dimension coordinate
411  inv_size = grid->inv_size[level];
412 
413  xmin=(int)floor(ownXMin*inv_size-0.5);
414  xmax=(int)ceil(ownXMax*inv_size+0.5);
415  ymin=(int)floor(ownYMin*inv_size-0.5);
416  ymax=(int)ceil(ownYMax*inv_size+0.5);
417  zmin=(int)floor(ownZMin*inv_size-0.5);
418  zmax=(int)ceil(ownZMax*inv_size+0.5);
419  //std::cout<<"dx="<<xmax-xmin<<" dy="<<ymax-ymin<<" dz="<<zmax-zmin<<std::endl;
420  //std::cout<<"xmin="<<xmin<<" x="<<obj->get_HGRID_x()<<" xmax="<<xmax<<std::endl;
421  //std::cout<<ownXMin*inv_size<<" "<<ownXMax*inv_size<<std::endl;
422 
423  for(int i=xmin;i<xmax;i++)
424  for(int j=ymin;j<ymax;j++)
425  for(int k=zmin;k<zmax;k++)
426  InsertCell(i, j, k, level, obj, grid);
427  } //end for level
428 }
429 #endif
HGridMethod getHGridMethod()
Definition: HGRID_base.cc:298
void set_HGRID_x(const int _new)
void set_HGRID_PrevObject(BaseParticle *_new)
BaseParticle * get_HGRID_PrevObject() const
Mdouble X
Definition: Vector.h:44
void HGRID_UpdateParticleInHgrid(BaseParticle *obj)
This adds a partcile to the Grid, called in the grid setup routies.
Definition: HGRID_3D.cc:220
Mdouble get_InteractionRadius() const
BaseParticle * get_PeriodicFromParticle() const
virtual void CheckCell(int x, int y, int z, int l, BaseParticle *obj, HGrid *grid)
Check collisions for a general cell.
Definition: HGRID_3D.cc:58
void set_HGRID_z(const int _new)
int get_HGRID_z() const
void HGRID_RemoveParticleFromHgrid(BaseParticle *obj)
Definition: HGRID_3D.cc:269
BaseParticle * get_HGRID_NextObject() const
int get_HGRID_x() const
std::vector< double > invCellSizes_
Definition: HGRID.h:51
std::vector< double > cellSizes_
Definition: HGRID.h:50
Mdouble xmax
Definition: MD.h:668
bool TestCell(int x, int y, int z, int l, BaseParticle *obj, HGrid *grid)
Tests obj against all particles in cell similar to CheckCell, but links to TestObject instead of comp...
Definition: HGRID_3D.cc:286
bool TestObjAgainstGrid(HGrid *grid, BaseParticle *obj)
Tests obj against all neighbouring particles similar to CheckObjAgainstGrid, but links to TestCell in...
Definition: HGRID_3D.cc:310
Mdouble zmax
Definition: MD.h:668
double Mdouble
Definition: ExtendedMath.h:33
This is the HGRID class - This is the actually HGRID code.
Definition: HGRID.h:39
virtual bool TestObject(BaseParticle *pI, BaseParticle *pJ)
criterium for inserting a particle (returns false, if particles overlap;)
Definition: HGRID_base.cc:251
void set_HGRID_y(const int _new)
int ComputeHashBucketIndex(int x, int y, int z, int l)
Computes hash bucket index in range [0, NUM_BUCKETS-1].
Definition: HGRID.cc:93
void CheckObjAgainstGrid(HGrid *grid, BaseParticle *obj)
Check if an Particle has a collision in the grid; avoids multiple checks.
Definition: HGRID_3D.cc:83
HGrid * grid
Definition: HGRID_base.h:131
const Vec3D & get_Position() const
Mdouble Y
Definition: Vector.h:44
bool * bucketIsChecked
bucketIsChecked[b] stores if hash bucket b is checked already; initially all zero ...
Definition: HGRID.h:61
int get_HGRID_y() const
int occupiedLevelsMask
l-th bit of occupiedLevelsMask is 1 if level l is contains particles; initially zero (Implies max 32 ...
Definition: HGRID.h:55
Mdouble xmin
These store the size of the domain, assume walls at the ends.
Definition: MD.h:668
void set_HGRID_NextObject(BaseParticle *_new)
virtual void CheckCell_current(int x, int y, int z, int l, HGrid *grid)
Checks for a collision in the particles own cell.
Definition: HGRID_3D.cc:31
Mdouble Z
Definition: Vector.h:44
Mdouble ymin
Definition: MD.h:668
int get_HGRID_Level() const
virtual void compute_internal_forces(BaseParticle *i)
Computes the forces between particles (internal in the sence that the sum over all these forces is ze...
Definition: MD.cc:1980
Mdouble zmin
Definition: MD.h:668
BaseParticle ** objectBucket
objectBucket[b] stores pointer to first element in hash bucket b; initially all NULL ...
Definition: HGRID.h:58
Mdouble ymax
Definition: MD.h:668