MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HGRID_2D.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_2D.h"
27 
31 void HGRID_2D::CheckCell_current(int x, int y, int l, HGrid *grid)
32 {
33  int bucket = grid->ComputeHashBucketIndex(x,y,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_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_2D::CheckCell(int x, int y, int l, BaseParticle *obj, HGrid *grid)
59 {
60  int bucket = grid->ComputeHashBucketIndex(x,y,l);
61 
62  if ((obj->get_HGRID_x() == x) && (obj->get_HGRID_y() == y) && (obj->get_HGRID_Level() == l)) {return; }
63 
64  // Loop through all objects in the bucket to find nearby objects
65  BaseParticle *p = grid->objectBucket[bucket];
66 
67  while (p!=NULL)
68  {
70  //Check if the particle realy is in the target cell (i.e. no hashing error has occured)
71  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_Level() == l))
72  {
74  }
75  p = p->get_HGRID_NextObject();
76  }
77 }
78 
83 {
84  unsigned int startLevel = obj->get_HGRID_Level();
85 
86  int x, y;
87  Mdouble inv_size;
88 
89  switch(getHGridMethod())
90  {
91  case BOTTOMUP:
92  {
93  int occupiedLevelsMask = grid->occupiedLevelsMask >> obj->get_HGRID_Level();
94  for (unsigned int level = startLevel; level < grid->cellSizes_.size(); occupiedLevelsMask >>= 1, level++)
95  {
96  // If no objects in rest of grid, stop now
97  if (occupiedLevelsMask == 0) break;
98 
99  // If no objects at this level, go on to the next level
100  if ((occupiedLevelsMask & 1) == 0) continue;
101 
102  if (level == startLevel)
103  {
104  x = obj->get_HGRID_x();
105  y = obj->get_HGRID_y();
106  CheckCell_current(x, y, level, grid);
107  CheckCell(x , y+1, level, obj, grid);
108  CheckCell(x+1, y-1, level, obj, grid);
109  CheckCell(x+1, y , level, obj, grid);
110  CheckCell(x+1, y+1, level, obj, grid);
111  }
112  else
113  {
114  int xs,ys,xe,ye;
115  inv_size = grid->invCellSizes_[level];
116  xs = (int) floor((obj->get_Position().X-obj->get_InteractionRadius()) * inv_size -0.5);
117  xe = (int) floor((obj->get_Position().X+obj->get_InteractionRadius()) * inv_size +0.5);
118  ys = (int) floor((obj->get_Position().Y-obj->get_InteractionRadius()) * inv_size -0.5);
119  ye = (int) floor((obj->get_Position().Y+obj->get_InteractionRadius()) * inv_size +0.5);
120  for(x=xs;x<=xe;x++)
121  {
122  for(y=ys;y<=ye;y++)
123  {
124  CheckCell(x,y,level,obj,grid);
125  }
126  }
127  }
128  }
129  break;
130  }
131  case TOPDOWN:
132  {
133  int occupiedLevelsMask = grid->occupiedLevelsMask;
134  for (unsigned int level = 0; level <= startLevel; occupiedLevelsMask >>= 1, level++)
135  {
136  // If no objects in rest of grid, stop now
137  if (occupiedLevelsMask == 0) break;
138 
139  // If no objects at this level, go on to the next level
140  if ((occupiedLevelsMask & 1) == 0) continue;
141 
142  if (level == startLevel)
143  {
144  x = obj->get_HGRID_x();
145  y = obj->get_HGRID_y();
146  CheckCell_current(x, y, level, grid);
147  CheckCell(x , y+1, level, obj, grid);
148  CheckCell(x+1, y-1, level, obj, grid);
149  CheckCell(x+1, y , level, obj, grid);
150  CheckCell(x+1, y+1, level, obj, grid);
151  }
152  else
153  {
154  int xs,ys,xe,ye;
155  inv_size = grid->invCellSizes_[level];
156  xs = (int) floor((obj->get_Position().X-obj->get_InteractionRadius()) * inv_size-0.5);
157  xe = (int) floor((obj->get_Position().X+obj->get_InteractionRadius()) * inv_size+0.5);
158  ys = (int) floor((obj->get_Position().Y-obj->get_InteractionRadius()) * inv_size-0.5);
159  ye = (int) floor((obj->get_Position().Y+obj->get_InteractionRadius()) * inv_size+0.5);
160  for(x=xs;x<=xe;x++)
161  {
162  for(y=ys;y<=ye;y++)
163  {
164  CheckCell(x,y,level,obj,grid);
165  }
166  }
167  }
168  }
169  break;
170  }
171  }
172 }
173 
174 
180 {
181  int l = obj->get_HGRID_Level();
182  Mdouble inv_size = grid->invCellSizes_[l];
183 
184  int x=(int)floor(obj->get_Position().X * inv_size);
185  int y=(int)floor(obj->get_Position().Y * inv_size);
186 
187 #ifdef ContactListHgrid
188  if(obj->get_HGRID_x()!=x||obj->get_HGRID_y()!=y||obj->get_PeriodicFromParticle())
189  {
190  if(!obj->get_PeriodicFromParticle())
191  {
192  int bucket = grid->ComputeHashBucketIndex(x, y, l);
193 
194  //First the object has to be removed
196 
197  //Also remove all contact associated with it
198  getPossibleContactList().remove_ParticlePosibleContacts(obj);
199 
200  //And now reinserted
201  obj->set_HGRID_NextObject(grid->objectBucket[bucket]);
202  if(grid->objectBucket[bucket])
203  grid->objectBucket[bucket]->set_HGRID_PrevObject(obj);
204  obj->set_HGRID_PrevObject(0);
205  grid->objectBucket[bucket] = obj;
206  }
207 
208  obj->set_HGRID_x(x);
209  obj->set_HGRID_y(y);
210 
211  InsertObjAgainstGrid(grid, obj);
212  }
213 #else
214  int bucket = grid->ComputeHashBucketIndex(x, y, l);
215 
216  obj->set_HGRID_NextObject(grid->objectBucket[bucket]);
217  if(grid->objectBucket[bucket])
218  grid->objectBucket[bucket]->set_HGRID_PrevObject(obj);
219  obj->set_HGRID_PrevObject(0);
220  grid->objectBucket[bucket] = obj;
221 
222  obj->set_HGRID_x(x);
223  obj->set_HGRID_y(y);
224 #endif
225 }
226 
228 {
229  int bucket = grid->ComputeHashBucketIndex(obj->get_HGRID_x(),obj->get_HGRID_y(), obj->get_HGRID_Level());
230  if(obj->get_HGRID_PrevObject())
232  else
233  if(grid->objectBucket[bucket]==obj)
234  grid->objectBucket[bucket]=obj->get_HGRID_NextObject();
235 
236  if(obj->get_HGRID_NextObject())
238 }
239 
244 bool HGRID_2D::TestCell(int x, int y, int l, BaseParticle *obj, HGrid *grid)
245 {
246  bool Test = true;
247 
248  // Loop through all objects in the bucket to find nearby objects
249  int bucket = grid->ComputeHashBucketIndex(x,y,l);
250  BaseParticle *p = grid->objectBucket[bucket];
251 
252  while (Test && p!=NULL)
253  {
254  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_Level() == l))
255  {
256  Test = Test && TestObject(obj,p);
257  }
258  p = p->get_HGRID_NextObject();
259  }
260 
261  return Test;
262 }
263 
269 {
270 
271  bool Test = true;
272 
273  int x, y;
274  Mdouble inv_size;
275  int occupiedLevelsMask = grid->occupiedLevelsMask;
276 
277  for (unsigned int level = 0; level < grid->cellSizes_.size() && Test; occupiedLevelsMask >>= 1, level++)
278  {
279  // If no objects in rest of grid, stop now
280  if (occupiedLevelsMask == 0) break;
281 
282  // If no objects at this level, go on to the next level
283  if ((occupiedLevelsMask & 1) == 0) continue;
284 
285  // Treat level as a third dimension coordinate
286  inv_size = grid->invCellSizes_[level];
287 
288  x = (int)floor(obj->get_Position().X * inv_size);
289  y = (int)floor(obj->get_Position().Y * inv_size);
290 
291  Test = Test
292  && TestCell(x , y , level, obj, grid)
293  && TestCell(x , y-1, level, obj, grid)
294  && TestCell(x , y+1, level, obj, grid)
295  && TestCell(x-1, y , level, obj, grid)
296  && TestCell(x+1, y , level, obj, grid)
297  && TestCell(x-1, y-1, level, obj, grid)
298  && TestCell(x-1, y+1, level, obj, grid)
299  && TestCell(x+1, y-1, level, obj, grid)
300  && TestCell(x+1, y+1, level, obj, grid);
301  } //end for level
302 
303  return Test;
304 }
305 
306 #ifdef ContactListHgrid
307 void HGRID_2D::InsertCell(int x, int y, int l, BaseParticle *obj, HGrid *grid)
308 {
309  // Loop through all objects in the bucket to find nearby objects
310  int bucket = grid->ComputeHashBucketIndex(x,y,l);
311  BaseParticle *p = grid->objectBucket[bucket];
312 
313  while (p!=NULL)
314  {
315  if ((p->get_HGRID_x() == x) && (p->get_HGRID_y() == y) && (p->get_HGRID_Level() == l) && (obj!=p))
316  {
317  getPossibleContactList().add_PossibleContact(obj,p);
318  }
319  p = p->get_HGRID_NextObject();
320  }
321 }
322 
323 void HGRID_2D::InsertObjAgainstGrid(HGrid *grid, BaseParticle *obj)
324 {
325  int xmin,xmax;
326  int ymin,ymax;
327  Mdouble inv_size;
328  int occupiedLevelsMask = grid->occupiedLevelsMask;
329 
330  inv_size=grid->inv_size[obj->get_HGRID_Level()];
331 
332  double ownXMin=(obj->get_HGRID_x()-0.5)/inv_size;
333  double ownXMax=(obj->get_HGRID_x()+1.5)/inv_size;
334  double ownYMin=(obj->get_HGRID_y()-0.5)/inv_size;
335  double ownYMax=(obj->get_HGRID_y()+1.5)/inv_size;
336 
337  for (int level = 0; level < grid->HGRID_MAX_LEVELS; occupiedLevelsMask >>= 1, level++)
338  {
339  // If no objects in rest of grid, stop now
340  if (occupiedLevelsMask == 0) break;
341 
342  // If no objects at this level, go on to the next level
343  if ((occupiedLevelsMask & 1) == 0) continue;
344 
345  // Treat level as a third dimension coordinate
346  inv_size = grid->inv_size[level];
347 
348  xmin=(int)floor(ownXMin*inv_size-0.5);
349  xmax=(int)floor(ownXMax*inv_size+0.5);
350  ymin=(int)floor(ownYMin*inv_size-0.5);
351  ymax=(int)floor(ownYMax*inv_size+0.5);
352 
353  for(int i=xmin;i<=xmax;i++)
354  for(int j=ymin;j<=ymax;j++)
355  InsertCell(i, j, level, obj, grid);
356  } //end for level
357 }
358 #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
Mdouble get_InteractionRadius() const
BaseParticle * get_PeriodicFromParticle() const
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
void HGRID_UpdateParticleInHgrid(BaseParticle *obj)
This adds a partcile to the Grid, called in the grid setup routies.
Definition: HGRID_2D.cc:179
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)
virtual void CheckCell_current(int x, int y, int l, HGrid *grid)
Checks for a collision in the particles own cell.
Definition: HGRID_2D.cc:31
int ComputeHashBucketIndex(int x, int y, int z, int l)
Computes hash bucket index in range [0, NUM_BUCKETS-1].
Definition: HGRID.cc:93
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
void CheckObjAgainstGrid(HGrid *grid, BaseParticle *obj)
Check if an Particle has a collision in the grid; avoids multiple checks.
Definition: HGRID_2D.cc:82
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
void HGRID_RemoveParticleFromHgrid(BaseParticle *obj)
Definition: HGRID_2D.cc:227
Mdouble xmin
These store the size of the domain, assume walls at the ends.
Definition: MD.h:668
void set_HGRID_NextObject(BaseParticle *_new)
Mdouble ymin
Definition: MD.h:668
bool TestCell(int x, int y, 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_2D.cc:244
int get_HGRID_Level() const
bool TestObjAgainstGrid(HGrid *grid, BaseParticle *obj)
Tests obj against all neighbouring particles similar to CheckObjAgainstGrid, but links to TestCell in...
Definition: HGRID_2D.cc:268
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
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
virtual void CheckCell(int x, int y, int l, BaseParticle *obj, HGrid *grid)
Check collisions for a general cell.
Definition: HGRID_2D.cc:58