MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Mercury2D.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 "Mercury2D.h"
27 #include "Particles/BaseParticle.h"
28 
30 {
31  constructor();
32  logger(DEBUG, "Mercury2D::Mercury2D() constructor finished");
33 }
34 
41  : DPMBase(other), MercuryBase(other)
42 {
43  logger(DEBUG, "Mercury2D::Mercury2D(Mercury2D& other) copy constructor finished");
44 }
45 
53  : DPMBase(other), MercuryBase()
54 {
55  constructor();
56  logger(DEBUG, "Mercury2D::Mercury2D(DPMBase& other) finished");
57 }
58 
60 {
63 }
64 
72 void Mercury2D::hGridFindContactsWithinTargetCell(int x, int y, unsigned int l)
73 {
74  HGrid* hgrid=getHGrid();
75  unsigned int bucket = hgrid->computeHashBucketIndex(x, y, l);
76 
77  //Check if this function is already applied to this bucket
78  if (hgrid->getBucketIsChecked(bucket))
79  {
80  return;
81  }
82 
83  BaseParticle* p1 = hgrid->getFirstBaseParticleInBucket(bucket);
84  while (p1 != nullptr)
85  {
86  BaseParticle* p2 = p1->getHGridNextObject();
87  while (p2 != nullptr)
88  {
91  //Check if the BaseParticle* p1 and BaseParticle* p2 are really in the same cell (i.e. no hashing error has occurred)
92  if ((p1->getHGridX() == p2->getHGridX()) && (p1->getHGridY() == p2->getHGridY()) && (p1->getHGridLevel() == p2->getHGridLevel()))
93  {
94  computeInternalForces(p1, p2);
95  }
96  p2 = p2->getHGridNextObject();
97  }
98  p1 = p1->getHGridNextObject();
99  }
100  hgrid->setBucketIsChecked(bucket);
101 }
102 
114 void Mercury2D::hGridFindContactsWithTargetCell(int x, int y, unsigned int l, BaseParticle* obj)
115 {
116  //Check if the object is not in the same cell as being checked, CheckCell_current should handle these cases.
117  if ((obj->getHGridX() == x) && (obj->getHGridY() == y) && (obj->getHGridLevel() == l))
118  {
119  return;
120  }
121 
122  HGrid* hgrid = getHGrid();
123 
124  // Calculate the bucket
125  unsigned int bucket = hgrid->computeHashBucketIndex(x, y, l);
126 
127  // Loop through all objects in the bucket to find nearby objects
128  BaseParticle *p = hgrid->getFirstBaseParticleInBucket(bucket);
129  while (p != nullptr)
130  {
131  //Check if the BaseParticle *p really is in the target cell (i.e. no hashing error has occurred)
132  if ((p->getHGridX() == x) && (p->getHGridY() == y) && (p->getHGridLevel() == l))
133  {
134  computeInternalForces(obj, p);
135  }
136  p = p->getHGridNextObject();
137  }
138 }
139 
146 {
147  HGrid* hgrid=getHGrid();
148  unsigned int startLevel = obj->getHGridLevel();
149 
150  switch (getHGridMethod())
151  {
152  case BOTTOMUP:
153  {
154  int occupiedLevelsMask = hgrid->getOccupiedLevelsMask() >> obj->getHGridLevel();
155  for (unsigned int level = startLevel; level < hgrid->getNumberOfLevels(); occupiedLevelsMask >>= 1, level++)
156  {
157  // If no objects in rest of grid, stop now
158  if (occupiedLevelsMask == 0)
159  {
160  break;
161  }
162 
163  // If no objects at this level, go on to the next level
164  if ((occupiedLevelsMask & 1) == 0)
165  {
166  continue;
167  }
168 
169  if (level == startLevel)
170  {
171  int x = obj->getHGridX();
172  int y = obj->getHGridY();
173 
175  hGridFindContactsWithTargetCell(x, y + 1, level, obj);
176  hGridFindContactsWithTargetCell(x + 1, y - 1, level, obj);
177  hGridFindContactsWithTargetCell(x + 1, y, level, obj);
178  hGridFindContactsWithTargetCell(x + 1, y + 1, level, obj);
179  }
180  else
181  {
182  int xs, ys, xe, ye;
183  Mdouble inv_size = hgrid->getInvCellSize(level);
184  xs = static_cast<int>(std::floor((obj->getPosition().X - obj->getInteractionRadius()) * inv_size - 0.5));
185  xe = static_cast<int>(std::floor((obj->getPosition().X + obj->getInteractionRadius()) * inv_size + 0.5));
186  ys = static_cast<int>(std::floor((obj->getPosition().Y - obj->getInteractionRadius()) * inv_size - 0.5));
187  ye = static_cast<int>(std::floor((obj->getPosition().Y + obj->getInteractionRadius()) * inv_size + 0.5));
188  for (int x = xs; x <= xe; ++x)
189  {
190  for (int y = ys; y <= ye; ++y)
191  {
192  hGridFindContactsWithTargetCell(x, y, level, obj);
193  }
194  }
195  }
196  }
197  break;
198  }
199  case TOPDOWN:
200  {
201  int occupiedLevelsMask = hgrid->getOccupiedLevelsMask();
202  for (unsigned int level = 0; level <= startLevel; occupiedLevelsMask >>= 1, level++)
203  {
204  // If no objects in rest of grid, stop now
205  if (occupiedLevelsMask == 0)
206  {
207  break;
208  }
209 
210  // If no objects at this level, go on to the next level
211  if ((occupiedLevelsMask & 1) == 0)
212  {
213  continue;
214  }
215 
216  if (level == startLevel)
217  {
218  int x = obj->getHGridX();
219  int y = obj->getHGridY();
220 
222  hGridFindContactsWithTargetCell(x, y + 1, level, obj);
223  hGridFindContactsWithTargetCell(x + 1, y - 1, level, obj);
224  hGridFindContactsWithTargetCell(x + 1, y, level, obj);
225  hGridFindContactsWithTargetCell(x + 1, y + 1, level, obj);
226  }
227  else
228  {
229  int xs, ys, xe, ye;
230  Mdouble inv_size = hgrid->getInvCellSize(level);
231  xs = static_cast<int>(std::floor((obj->getPosition().X - obj->getInteractionRadius()) * inv_size - 0.5));
232  xe = static_cast<int>(std::floor((obj->getPosition().X + obj->getInteractionRadius()) * inv_size + 0.5));
233  ys = static_cast<int>(std::floor((obj->getPosition().Y - obj->getInteractionRadius()) * inv_size - 0.5));
234  ye = static_cast<int>(std::floor((obj->getPosition().Y + obj->getInteractionRadius()) * inv_size + 0.5));
235  for (int x = xs; x <= xe; ++x)
236  {
237  for (int y = ys; y <= ye; ++y)
238  {
239  hGridFindContactsWithTargetCell(x, y, level, obj);
240  }
241  }
242  }
243  }
244  break;
245  }
246  }
247 }
248 
254 {
255  HGrid* hGrid=getHGrid();
256  if (hGrid)
257  {
258  unsigned int l = obj->getHGridLevel();
259  Mdouble inv_size = hGrid->getInvCellSize(l);
260 
261  int x = static_cast<int>(std::floor(obj->getPosition().X * inv_size));
262  int y = static_cast<int>(std::floor(obj->getPosition().Y * inv_size));
263 
264 #ifdef CONTACT_LIST_HGRID
265  if(obj->getHGridX() != x || obj->getHGridY() != y)
266  {
267  int bucket = hGrid->computeHashBucketIndex(x, y, l);
268 
269  //First the object has to be removed
270  hGridRemoveParticle(obj);
271 
272  //Also remove all contact associated with it
273  getPossibleContactList().remove_ParticlePosibleContacts(obj);
274 
275  //And now reinserted
277  obj->setHGridPrevObject(nullptr);
278  if(hGrid->getFirstBaseParticleInBucket(bucket))
279  {
281  }
282  hGrid->setFirstBaseParticleInBucket(bucket,obj);
283 
284  obj->setHGridX(x);
285  obj->setHGridY(y);
286  InsertObjAgainstGrid(obj);
287  }
288 #else
289  unsigned int bucket = hGrid->computeHashBucketIndex(x, y, l);
290 
292  obj->setHGridPrevObject(nullptr);
293  if (hGrid->getFirstBaseParticleInBucket(bucket))
294  {
296  }
297 
298  hGrid->setFirstBaseParticleInBucket(bucket, obj);
299 
300  obj->setHGridX(x);
301  obj->setHGridY(y);
302 #endif
303  }
304 }
305 
312 {
313  HGrid* hGrid = getHGrid();
314  if (hGrid != nullptr)
315  {
316  unsigned int bucket = getHGrid()->computeHashBucketIndex(obj->getHGridX(), obj->getHGridY(), obj->getHGridLevel());
317  if (obj->getHGridPrevObject())
318  {
320  }
321  else
322  {
323  if (getHGrid()->getFirstBaseParticleInBucket(bucket) == obj)
324  {
326  }
327  }
328 
329  if (obj->getHGridNextObject())
330  {
332  }
333  }
334 }
335 
351 bool Mercury2D::hGridHasContactsInTargetCell(int x, int y, unsigned int l, const BaseParticle *obj) const
353 {
354  // Loop through all objects in the bucket to find nearby objects
355  unsigned int bucket = getHGrid()->computeHashBucketIndex(x, y, l);
356 
357  const BaseParticle* p = getHGrid()->getFirstBaseParticleInBucket(bucket);
358  while (p != nullptr)
359  {
360  if ((p->getHGridX() == x) && (p->getHGridY() == y) && (p->getHGridLevel() == l))
361  {
362  if (areInContact(obj, p))
363  {
364  return true;
365  }
366  }
367  p = p->getHGridNextObject();
368  }
369  return false;
370 }
371 
381 {
382  if (getHGrid() == nullptr || getHGrid()->getNeedsRebuilding())
383  {
384  logger(INFO, "HGrid needs rebuilding for \"bool Mercury2D::hGridHasParticleContacts(BaseParticle *obj)\"");
385  hGridRebuild();
386  }
387 
388  Mdouble inv_size;
389  int occupiedLevelsMask = getHGrid()->getOccupiedLevelsMask();
390 
391  for (unsigned int level = 0; level < getHGrid()->getNumberOfLevels(); occupiedLevelsMask >>= 1, level++)
392  {
393  // If no objects in rest of grid, stop now
394  if (occupiedLevelsMask == 0)
395  {
396  logger(VERBOSE, "Level % and higher levels are empty.", level);
397  break;
398  }
399 
400  // If no objects at this level, go on to the next level
401  if ((occupiedLevelsMask & 1) == 0)
402  {
403  logger(VERBOSE, "Level % is empty", level);
404  continue;
405  }
406 
407  int xs, ys, xe, ye;
408  inv_size = getHGrid()->getInvCellSize(level);
409  xs = static_cast<int>(std::floor((obj->getPosition().X - obj->getInteractionRadius()) * inv_size - 0.5));
410  xe = static_cast<int>(std::floor((obj->getPosition().X + obj->getInteractionRadius()) * inv_size + 0.5));
411  ys = static_cast<int>(std::floor((obj->getPosition().Y - obj->getInteractionRadius()) * inv_size - 0.5));
412  ye = static_cast<int>(std::floor((obj->getPosition().Y + obj->getInteractionRadius()) * inv_size + 0.5));
413 
414  logger(VERBOSE, "Level % grid cells [%,%] x [%,%]", level, xs, xe, ys, ye);
415  for (int x = xs; x <= xe; ++x)
416  {
417  for (int y = ys; y <= ye; ++y)
418  {
419  if (hGridHasContactsInTargetCell(x, y, level, obj))
420  {
421  return true;
422  }
423  }
424  }
425  } //end for level
426 
427  return false;
428 }
429 
430 #ifdef CONTACT_LIST_HGRID
431 
437 void Mercury2D::InsertCell(int x, int y, unsigned int l, BaseParticle* obj)
438 {
439  // Loop through all objects in the bucket to find nearby objects
440  unsigned int bucket = getHGrid()->computeHashBucketIndex(x,y,l);
442 
443  while (p!=nullptr)
444  {
445  if ((p->getHGridX() == x) && (p->getHGridY() == y) && (p->getHGridLevel() == l) && (obj != p))
446  {
447  getPossibleContactList().add_PossibleContact(obj, p);
448  }
449  p = p->getHGridNextObject();
450  }
451 }
452 
459 void Mercury2D::InsertObjAgainstGrid(BaseParticle* obj)
460 {
461  Mdouble inv_size;
462  int occupiedLevelsMask_ = getHGrid()->getOccupiedLevelsMask();
463 
464  inv_size=getHGrid()->getInvCellSize(obj->getHGridLevel());
465 
466  double ownXMin = (obj->getHGridX()-0.5) * getHGrid()->getCellSize(obj->getHGridLevel());
467  double ownXMax = (obj->getHGridX() + 1.5) * getHGrid()->getCellSize(obj->getHGridLevel());
468  double ownYMin = (obj->getHGridY() - 0.5) * getHGrid()->getCellSize(obj->getHGridLevel());
469  double ownYMax = (obj->getHGridY() + 1.5) * getHGrid()->getCellSize(obj->getHGridLevel());
470 
471  for (int level = 0; level < getHGrid()->getNumberOfLevels(); occupiedLevelsMask_ >>= 1, level++)
472  {
473  // If no objects in rest of grid, stop now
474  if (occupiedLevelsMask_ == 0)
475  {
476  break;
477  }
478 
479  // If no objects at this level, go on to the next level
480  if ((occupiedLevelsMask_ & 1) == 0)
481  {
482  continue;
483  }
484 
485  // Treat level as a third dimension coordinate
486  inv_size = getHGrid()->getInvCellSize(level);
487 
488  //Insert this particle in the list of possible interactions for this level
489  //in the appropriate cells.
490  int xs, xe, ys, ye;
491  xs = static_cast<int>(std::floor(ownXMin * inv_size - 0.5));
492  xe = static_cast<int>(std::floor(ownXMax * inv_size + 0.5));
493  ys = static_cast<int>(std::floor(ownYMin * inv_size - 0.5));
494  ye = static_cast<int>(std::floor(ownYMax * inv_size + 0.5));
495 
496  for(int x = xs; x <= xe; ++x)
497  {
498  for(int y = ys; y <= ye; ++y)
499  {
500  InsertCell(x, y, level, obj);
501  }
502  }
503  } //end for level
504 }
505 #endif
The DPMBase header includes quite a few header files, defining all the handlers, which are essential...
Definition: DPMBase.h:65
Mdouble X
the vector components
Definition: Vector.h:52
bool hGridHasParticleContacts(const BaseParticle *obj) override
Test if a BaseParticle has any contacts in the HGrid.
Definition: Mercury2D.cc:380
bool areInContact(const BaseParticle *pI, const BaseParticle *pJ) const
Checks if two particle are in contact or is there any positive overlap.
Definition: DPMBase.cc:713
virtual void hGridFindContactsWithTargetCell(int x, int y, unsigned int l, BaseParticle *obj)
Finds contacts between given BaseParticle and the BaseParticle in the target cell.
Definition: Mercury2D.cc:114
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
void hGridUpdateParticle(BaseParticle *obj) override
Updates the cell (not the level) of a BaseParticle.
Definition: Mercury2D.cc:253
virtual void computeInternalForces(BaseParticle *i)
Computes the forces between particles (internal in the sense that the sum over all these forces is ze...
Definition: DPMBase.cc:1888
virtual void hGridFindContactsWithinTargetCell(int x, int y, unsigned int l)
Finds contacts between particles the in the target cell.
Definition: Mercury2D.cc:72
double Mdouble
void setHGridY(const int y)
Sets the particle's HGrid cell Y-coordinate.
void setHGridNextObject(BaseParticle *p)
Sets the pointer to the next object in the particle's HGrid cell & level.
void setParticleDimensions(unsigned int particleDimensions)
Allows the dimension of the particle (f.e. for mass) to be changed. e.g. discs or spheres...
Definition: DPMBase.cc:583
HGridMethod getHGridMethod() const
Gets whether the HGrid in this MercuryBase is BOTTOMUP or TOPDOWN.
Definition: MercuryBase.cc:439
int getHGridY() const
Returns particle's HGrid cell Y-coordinate.
void constructor()
Function that sets the ParticleDimensions and SystemDimensions to 2.
Definition: Mercury2D.cc:59
void setSystemDimensions(unsigned int newDim)
Allows for the dimension of the simulation to be changed.
Definition: DPMBase.cc:562
void setHGridX(const int x)
Sets the particle's HGrid cell X-coordinate.
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
int getOccupiedLevelsMask() const
Gets the integer that represents which levels are occupied.
Definition: HGrid.cc:286
unsigned int getNumberOfLevels() const
Gets the number of levels of this HGrid.
Definition: HGrid.cc:235
This is the base class for both Mercury2D and Mercury3D. Note the actually abstract grid is defined i...
Definition: MercuryBase.h:127
In the HGrid class, here all information about the HGrid is stored.
Definition: HGrid.h:41
bool hGridHasContactsInTargetCell(int x, int y, unsigned int l, const BaseParticle *obj) const
Tests if the BaseParticle has contacts with other Particles in the target cell.
Definition: Mercury2D.cc:352
void setFirstBaseParticleInBucket(unsigned int i, BaseParticle *p)
Sets the first particle in bucket i to be the given BaseParticle.
Definition: HGrid.cc:244
void setBucketIsChecked(unsigned int i)
Sets that the bucket with the given index is checked to true.
Definition: HGrid.cc:227
const BaseParticle * getFirstBaseParticleInBucket(unsigned int i) const
Gets the first BaseParticle in the given bucket, const version.
Definition: HGrid.cc:210
Mdouble Y
Definition: Vector.h:52
void hGridRebuild()
This sets up the parameters required for the contact model.
Definition: MercuryBase.cc:201
double getCellSize(unsigned int i) const
Gets the size of the cells at the given level.
Definition: HGrid.cc:253
Mercury2D()
This is the default constructor. All it does is set sensible defaults.
Definition: Mercury2D.cc:29
void hGridFindOneSidedContacts(BaseParticle *obj) override
Finds contacts with the BaseParticle; avoids multiple checks.
Definition: Mercury2D.cc:145
void setHGridPrevObject(BaseParticle *p)
Sets the pointer to the previous object in the particle's HGrid cell & level.
BaseParticle * getHGridPrevObject() const
Returns pointer to previous object in particle's HGrid level & cell.
unsigned int computeHashBucketIndex(int x, int y, int z, unsigned int l) const
Computes hash bucket index in range [0, NUM_BUCKETS-1] for a 3D domain.
Definition: HGrid.cc:125
BaseParticle * getHGridNextObject() const
Returns pointer to next object in particle's HGrid level & cell.
unsigned int getHGridLevel() const
Returns particle's HGrid level.
Mdouble getInteractionRadius() const
Returns the particle's interaction radius, which might be different from radius_ (e.g., when dealing with wet particles)
HGrid * getHGrid()
Gets the HGrid used by this problem.
Definition: MercuryBase.cc:389
bool getBucketIsChecked(unsigned int i) const
Gets whether or not the bucket with index i is checked.
Definition: HGrid.cc:201
double getInvCellSize(unsigned int i) const
Gets 1/cellSize for the cells on level i.
Definition: HGrid.cc:262
This adds on the hierarchical grid code for 2D problems.
Definition: Mercury2D.h:35
int getHGridX() const
Returns particle's HGrid cell X-coordinate.
void hGridRemoveParticle(BaseParticle *obj) override
Removes a BaseParticle to the HGrid.
Definition: Mercury2D.cc:311