Mercury3DClump.h
Go to the documentation of this file.
1 //Copyright (c) 2013-2023, 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 
27 #include "Mercury3D.h"
28 #include "Walls/InfiniteWall.h"
32 #include <stdlib.h>
33 
38 class Mercury3Dclump : public Mercury3D
39 {
40 public:
41  explicit Mercury3Dclump()
42  {
43 
44  }
45 
50  {
51  // Quit if:
52  // 1) at least one particle is master
53  // 2) pebbles of the same clump
54  // 3) both particles are fixed
55  // 4) both particles are "ghosts".
56  if (P1->isClump() || P2->isClump()) return;
57  if (P1->isPebble() && P2->isPebble() && P1->getClump() == P2->getClump()) return;
58  if (P1->isFixed() && P2->isFixed()) return;
59  if ((P1->getPeriodicFromParticle() != nullptr) && (P2->getPeriodicFromParticle() != nullptr)) return;
60 
61  // Assign pointers PI, PJ such that PI has the lower id than PJ
62  BaseParticle * PI, * PJ;
63  if (P1->getId() > P2->getId()) {PI = P2; PJ = P1;}
64  else {PI = P1; PJ = P2;}
65 
66  // Check for the interaction between PI and PJ
69  if (i!= nullptr) {
70  i->computeForce(); // Compute and apply forces
71  PI->addForce(i->getForce());
72  PJ->addForce(-i->getForce());
73 
74  // Add extra torques to master particles arising from the forces acting on pebbles
75  if (getRotation()) {
76  PI->addTorque(i->getTorque() - Vec3D::cross(PI->getPosition() - i->getContactPoint(), i->getForce()));
77  PJ->addTorque(-i->getTorque() + Vec3D::cross(PJ->getPosition() - i->getContactPoint(), i->getForce()));
78  }
79  }
80  }
81 
86  {
87  // No interaction between walls and master particles
88  if (pI->isClump())
89  return;
90 
91  //No need to compute interactions between periodic particle images and walls
92  if (pI->getPeriodicFromParticle() != nullptr)
93  return;
94 
95  //Checks if the particle is interacting with the current wall
98  if (i!=nullptr) {
99  //...calculates the forces between the two objects...
100  i->computeForce();
101 
102  //...and applies them to each of the two objects (wall and particle).
103  pI->addForce(i->getForce());
104  w->addForce(-i->getForce());
105 
106  //If the rotation flag is on, also applies the relevant torques
107  //(getRotation() returns a boolean).
108  if (getRotation()) // getRotation() returns a boolean.
109  {
110  pI->addTorque(i->getTorque() - Vec3D::cross(pI->getPosition() - i->getContactPoint(), i->getForce()));
111  w->addTorque(-i->getTorque() + Vec3D::cross(w->getPosition() - i->getContactPoint(), i->getForce()));
112  }
113  }
114  }
115 
119  void computeAllForces() override
120  {
121  //Resetting all forces on both particles and walls to zero
122  #pragma omp parallel num_threads(getNumberOfOMPThreads())
123  {
124  #pragma omp for
125  for (int k = 0; k < particleHandler.getSize(); ++k) {
127  }
128  #pragma omp for
129  for (int k = 0; k < wallHandler.getSize(); k++) {
131  }
132  }
133  logger(DEBUG,"All forces set to zero");
134 
135  // compute all internal and external forces; for omp simulations, this can be done in parallel
136  {
137  //logger(INFO, "Number of omp threads = %", getNumberOfOMPThreads());
139  #pragma omp for schedule(dynamic)
140  for (int k = 0; k < particleHandler.getSize(); ++k) {
142  //computing both internal forces (e.g. due to collisions)
143  //and external forces (e.g. gravity)
144  //(compute internal forces compares the current particle p
145  //with all others in the handler!)
147  // body forces
149  }
150 
151  // wall-forces
152  #pragma omp for schedule(dynamic)
153  for (int k = 0; k < wallHandler.getSize(); k++) {
156  }
157  }
158  #pragma omp for schedule(dynamic)
160  for (BaseParticle* p : particleHandler)
161  {
162  if ((p->isPebble()) && (p->getPeriodicFromParticle() == nullptr))
163  {
164  p->getClump()->addForce(p->getForce());
165  Vec3D lever = p->getPosition()- p->getClump()->getPosition();
166 
167  // Patch to fix lever - we do not create ghost masters, that's why this workaround is needed
168  // Should affect all boundaries derived from PeriodicBoundary and do not affect other types
169  for (auto p : boundaryHandler) {
170  auto pb = dynamic_cast<PeriodicBoundary*> (p);
171  if (pb){
172  Vec3D shift = pb->getShift();
173  if (lever.getLength() > (lever - shift).getLength()) lever -= shift;
174  if (lever.getLength() > (lever + shift).getLength()) lever += shift;
175  }
176  }
177  // End patch
178 
179  Vec3D torque = p->getTorque();
180  torque += Vec3D::cross(lever, p->getForce());
181  p->getClump()->addTorque(torque);
182  }
183  }
184  }
185 
190  {
191  ClumpParticle* mp = dynamic_cast<ClumpParticle*>(&particle);
192  if (mp->isClump()){
193  for (int i = 0; i< mp->NPebble(); i++){
194  for (BaseParticle *q: particleHandler) {
195  if (!q->isClump()) { // check every slave vs every non-master intersection
196  if (Vec3D::getDistanceSquared(q->getPosition(), mp->getPebblePositions()[i]) < q->getRadius() +
197  mp->getPebbleRadii()[i]) {
198  return false;
199  }
200  }
201  }
202  }
203  }
204  return true;
205  }
206 
211  {
212  // Note that this implementation only check for interaction with particles
213  bool NP = true;
214  // Periodic case
215  for (BaseBoundary* b : boundaryHandler)
216  {
217  PeriodicBoundary* pb = dynamic_cast<PeriodicBoundary*>(b);
218  if (pb) NP = false;
219  if (pb && particleHandler.getNumberOfObjects() > 0 )
220  {
221  ClumpParticle* mp = dynamic_cast<ClumpParticle*>(&particle);
222  if (mp->isClump()){
223  for (int i = 0; i< mp->NPebble(); i++){
224  for (BaseParticle *q: particleHandler) {
225  if (!q->isClump()) { // check every slave vs every non-master intersection
226  if (Vec3D::getDistanceSquared(q->getPosition(), mp->getPebblePositions()[i]) < (q->getMaxInteractionRadius() +
227  mp->getPebbleRadii()[i]) * (q->getMaxInteractionRadius() +
228  mp->getPebbleRadii()[i]) ) {
229  return false;
230  }
231  BaseParticle *q1 = q->copy(); // check every slave vs non-master ghost intersection
232  pb->shiftPosition(q1);
234  Mdouble dist02 = (q1->getMaxInteractionRadius() + mp->getPebbleRadii()[i]) * (q1->getMaxInteractionRadius() +
235  mp->getPebbleRadii()[i]);
236  delete q1;
237  if (dist2 < dist02) {
238  return false;
239  }
240  }
241  }
242  }
243  }
244  }
245  }
246  // Non-periodic case
247  if ((NP)&&(particleHandler.getNumberOfObjects() > 0 ))
248  {
249  ClumpParticle* mp = dynamic_cast<ClumpParticle*>(&particle);
250  if (mp->isClump()){
251  for (int i = 0; i< mp->NPebble(); i++){
252  for (BaseParticle *q: particleHandler) {
253  if (!q->isClump()) { // check every slave vs every non-master intersection
254  if (Vec3D::getDistanceSquared(q->getPosition(), mp->getPebblePositions()[i]) < (q->getRadius() +
255  mp->getPebbleRadii()[i]) * (q->getRadius() +
256  mp->getPebbleRadii()[i])) {
257  return false;
258  }
259  }
260  }
261  }
262  }
263  }
264  return true;
265  }
266 };
267 
268 
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
@ DEBUG
Definition: BaseBoundary.h:49
unsigned int getSize() const
Gets the size of the particleHandler (including mpi and periodic particles)
Definition: BaseHandler.h:655
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
void addTorque(const Vec3D &addTorque)
Adds an amount to the torque on this BaseInteractable.
Definition: BaseInteractable.cc:132
virtual void resetForceTorque(int numberOfOMPthreads)
Definition: BaseInteractable.cc:141
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:218
void addForce(const Vec3D &addForce)
Adds an amount to the force on this BaseInteractable.
Definition: BaseInteractable.cc:116
Stores information about interactions between two interactable objects; often particles but could be ...
Definition: BaseInteraction.h:60
unsigned int getId() const
Returns the unique identifier of any particular object.
Definition: BaseObject.h:125
Definition: BaseParticle.h:54
bool isFixed() const override
Is fixed Particle function. It returns whether a Particle is fixed or not, by checking its inverse Ma...
Definition: BaseParticle.h:93
BaseInteraction * getInteractionWith(BaseParticle *P, unsigned timeStamp, InteractionHandler *interactionHandler) override
Checks if particle is in interaction with given particle P, and if so, returns vector of pointer to t...
Definition: BaseParticle.cc:690
bool isPebble() const
Checks if particle is a pebble (belongs to a clump)
Definition: BaseParticle.h:673
bool isClump() const
Checks if particle is a clump (container)
Definition: BaseParticle.h:664
Mdouble getMaxInteractionRadius() const
Returns the particle's interaction radius, which might be different from radius_ (e....
Definition: BaseParticle.h:362
virtual BaseParticle * copy() const =0
Particle copy method. It calls to copy constructor of this Particle, useful for polymorphism.
BaseParticle * getClump() const
Definition: BaseParticle.h:656
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
Definition: BaseParticle.h:341
Basic class for walls.
Definition: BaseWall.h:49
BaseInteraction * getInteractionWith(BaseParticle *p, unsigned timeStamp, InteractionHandler *interactionHandler) override
Returns the interaction between this wall and a given particle, nullptr if there is no interaction.
Definition: BaseWall.cc:367
Definition: ClumpParticle.h:41
std::vector< Mdouble > getPebbleRadii()
Definition: ClumpParticle.h:222
int NPebble() const
Definition: ClumpParticle.cc:115
std::vector< Vec3D > getPebblePositions()
Definition: ClumpParticle.h:211
int getNumberOfOMPThreads() const
Definition: DPMBase.cc:1286
unsigned int getNumberOfTimeSteps() const
Returns the current counter of time-steps, i.e. the number of time-steps that the simulation has unde...
Definition: DPMBase.cc:824
WallHandler wallHandler
An object of the class WallHandler. Contains pointers to all the walls created.
Definition: DPMBase.h:1447
BoundaryHandler boundaryHandler
An object of the class BoundaryHandler which concerns insertion and deletion of particles into or fro...
Definition: DPMBase.h:1452
InteractionHandler interactionHandler
An object of the class InteractionHandler.
Definition: DPMBase.h:1467
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created.
Definition: DPMBase.h:1437
virtual void computeExternalForces(BaseParticle *)
Computes the external forces, such as gravity, acting on particles.
Definition: DPMBase.cc:3159
bool getRotation() const
Indicates whether particle rotation is enabled or disabled.
Definition: DPMBase.h:570
This adds on the hierarchical grid code for 3D problems.
Definition: Mercury3D.h:37
void computeInternalForces(BaseParticle *obj) override
Finds contacts with the BaseParticle; avoids multiple checks.
Definition: Mercury3D.cc:224
void computeWallForces(BaseWall *w) override
Compute contacts with a wall.
Definition: Mercury3D.cc:617
Definition: Mercury3DClump.h:39
void computeForcesDueToWalls(BaseParticle *pI, BaseWall *w) override
Definition: Mercury3DClump.h:85
void computeInternalForce(BaseParticle *P1, BaseParticle *P2) override
Definition: Mercury3DClump.h:49
bool checkClumpForInteractionPeriodic(BaseParticle &particle)
Definition: Mercury3DClump.h:210
Mercury3Dclump()
Definition: Mercury3DClump.h:41
bool checkClumpForInteraction(BaseParticle &particle)
Definition: Mercury3DClump.h:189
void computeAllForces() override
Definition: Mercury3DClump.h:119
unsigned int getNumberOfObjects() const override
Returns the number of objects in the container. In parallel code this practice is forbidden to avoid ...
Definition: ParticleHandler.cc:1325
Defines a pair of periodic walls. Inherits from BaseBoundary.
Definition: PeriodicBoundary.h:41
virtual void shiftPosition(BaseParticle *p) const override
shifts the particle
Definition: PeriodicBoundary.cc:219
Definition: Vector.h:51
static Vec3D cross(const Vec3D &a, const Vec3D &b)
Calculates the cross product of two Vec3D: .
Definition: Vector.cc:163
static Mdouble getLength(const Vec3D &a)
Calculates the length of a Vec3D: .
Definition: Vector.cc:331
static Mdouble getDistanceSquared(const Vec3D &a, const Vec3D &b)
Calculates the squared distance between two Vec3D: .
Definition: Vector.h:311
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51