MercuryDPM  Trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MeshTriangle.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2020, 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 <MercuryBase.h>
27 #include <algorithm>
28 
29 #include "MeshTriangle.h"
30 #include "InteractionHandler.h"
31 #include "WallHandler.h"
32 #include "DPMBase.h"
33 #include "Particles/BaseParticle.h"
34 
48 MeshTriangle::getInteractionWith(BaseParticle* p, unsigned timeStamp, InteractionHandler* interactionHandler)
49 {
50  if (!isActive) return nullptr;
51 
52  // TODO: Note that this if may lead to contacts beeing ignored in md->checkParticleForInteraction because unadded
53  // particles have the Id 0, which might indeed be the Id of an node particle
54  if ( std::find(vertexIds_.begin(), vertexIds_.end(), p->getId()) != vertexIds_.end() )
55  {
56  // Do not detect any contact between particles that correspond to the walls nodes
57  return nullptr;
58  }
59 
60  Mdouble distance;
61  Vec3D normal;
62  Mdouble overlap;
63  unsigned int type;
64 
65  if (!(p->isSphericalParticle()))
66  {
67  logger(ERROR, "MeshTriangle::getInteractionWith not implemented for particles of type %", p->getName());
68  }
69 
70  if (getDistanceNormalOverlapType(*p, distance, normal, overlap, type))
71  {
72  // look for an existing interaction, or create a new one
73  BaseInteraction *c = nullptr;
74  if (getGroupId() > 0 && p->getInteractions().size() > 0)
75  {
76  // Do not care for the result in that case.
77  return BaseWall::getInteractionWith(p, timeStamp, interactionHandler);
78  }
79 
80  // look for an existing interaction, or create a new one
81  c = interactionHandler->getInteraction(p, this, timeStamp);
82 
83  c->setNormal(-normal);
84  c->setDistance(distance);
85  c->setOverlap(overlap);
87  c->setWallInteraction(1);
88 
90  c->setContactPoint(p->getPosition() - (p->getRadius() - 0.5 * c->getOverlap()) * c->getNormal());
91 
92  logger(DEBUG, "Particle contact with wall at %", c->getContactPoint());
93  return c;
94  }
95  return nullptr;
96 }
97 
110 void MeshTriangle::checkInteractions(InteractionHandler* interactionHandler, unsigned int timeStamp)
111 {
112  unsigned j, id;
113  // Iterate through the interactions and check if there is one with higher priority
114  // Note: The id should already be taken into account when creating the interactions
115  for (j = 0; j<getInteractions().size(); j++)
116  {
117  bool interactionValid = true;
118  auto i = getInteractions()[j];
119  if (i->getTimeStamp()!=timeStamp)
120  {
121  continue; // Old interactions are not needed
122  logger(WARN, "Taking old interaction into account");
123  }
124  if (i->getMultiContactIdentifier()>3) // Vertex contact
125  {
126  id = i->getMultiContactIdentifier() - 4;
127  for (auto triangleId : vertexNeighbors[id])
128  {
129  // logger(INFO, "id % %", id, getId());
130  auto k = getHandler()->getObjectById(triangleId);
131  auto interactionNeighbor = interactionHandler->getExistingInteraction(i->getP(), k);
132  if (interactionNeighbor && interactionNeighbor->getTimeStamp()==timeStamp)
133  {
134  if (interactionNeighbor->getMultiContactIdentifier() <= 3)
135  {
136  // logger(INFO, "Found invalid vertex contact");
137  interactionValid = false;
138  break;
139  }
140  }
141  }
142  }
143  else if (i->getMultiContactIdentifier()>0) // Edge contact
144  {
145  id = i->getMultiContactIdentifier() - 1;
146  if (neighbor[id])
147  {
148  auto interactionNeighbor = interactionHandler->getExistingInteraction(i->getP(), neighbor[id]);
149  if (interactionNeighbor && interactionNeighbor->getTimeStamp()==timeStamp)
150  {
151  if (interactionNeighbor->getMultiContactIdentifier() == 0)
152  {
153  // logger(INFO, "Found invalid edge contact");
154  interactionValid = false;
155  }
156  }
157  }
158  }
159 
160  // Undo the interaction
161  if (!interactionValid)
162  {
163  i->getP()->addForce(-i->getForce());
164  this->addForce(i->getForce());
165  if (getHandler()->getDPMBase()->getRotation()) {
166  i->getP()->addTorque(-i->getTorque() + Vec3D::cross(i->getP()->getPosition() - i->getContactPoint(), i->getForce()));
167  this->addTorque(i->getTorque() - Vec3D::cross(this->getPosition() - i->getContactPoint(), i->getForce()));
168  }
169  i->setForce(Vec3D(0,0,0));
170  }
171  else
172  {
173  Vec3D weight = getBaricentricWeight(i->getContactPoint());
174 
175  // Contact seems valid, distribute its force to the edges
176  Vec3D force = -i->getForce();
177 
178  for(unsigned k=0; k<3; k++)
179  {
180  vertexParticle_[k]->addForce(weight.getComponent(k)*force);
181  }
182  }
183  }
184 }
199 bool MeshTriangle::getDistanceAndNormal(const BaseParticle& p, Mdouble& distance, Vec3D& normal) const
200 {
201  if (!isActive) return false;
202  Mdouble overlap;
203  unsigned int type;
204  return getDistanceNormalOverlapType(p, distance, normal, overlap, type);
205 }
206 
207 
225 bool MeshTriangle::getDistanceNormalOverlapType(const BaseParticle& p, Mdouble& distance, Vec3D& normal, Mdouble& overlap, unsigned int& type) const
226 {
227  if (!isActive) return false;
228 
229  // TODO: Note that this if may lead to contacts beeing ignored in md->checkParticleForInteraction because unadded
230  // particles have the Id 0, which might indeed be the Id of a node particle
231  if ( std::find(vertexIds_.begin(), vertexIds_.end(), p.getId()) != vertexIds_.end() )
232  {
233  // Do not detect any contact between particles that correspond to the walls nodes
234  return false;
235  }
236 
237  const Vec3D position = p.getPosition(); // note: no transfer to lab coordinates
238  const Mdouble distanceMax = p.getWallInteractionRadius(this);
239 
240  // compute distance from face
241  // get distance from particle position to the face
242  const Mdouble signedDistance = Vec3D::dot(position-vertex_[0], faceNormal_);
243  distance = std::abs(signedDistance);
244 
245  // check if any contact is possible
246  if (distance >= distanceMax) return false;
247 
248  // compute distance from edges
249  const std::array<Vec3D,3> edgeBranch {position - vertex_[0], position - vertex_[1], position - vertex_[2]};
250  const std::array<double,3> edgeDistance {Vec3D::dot(edgeBranch[0], edgeNormal_[0]), Vec3D::dot(edgeBranch[1], edgeNormal_[1]), Vec3D::dot(edgeBranch[2], edgeNormal_[2])};
251 
252  // find edge with largest distance (this will be the edge if there is a edge contact)
253  const size_t id = (edgeDistance[1] > edgeDistance[2]) ?
254  (edgeDistance[0] > edgeDistance[1] ? 0 : 1) : (edgeDistance[0] > edgeDistance[2] ? 0 : 2);
255 
256  // check if there will be contact
257  if (edgeDistance[id] > distanceMax) return false;
258 
259  // determine if it is a face contact
260  const Vec3D posProjected = position - signedDistance * faceNormal_;
261  if (edgeDistance[id] <= 0 && isInsideTriangle(posProjected)){
262  normal = (signedDistance >= 0) ? -faceNormal_ : faceNormal_;
263  overlap = p.getRadius() - distance;
264  type=0; // Face contact
265  return true;
266  }
267 
268  // Then the neighbor will handle this interaction
269  if (neighbor[id] && neighbor[id]->getId()<this->getId()) return false;
270  // determine if it is an edge or vertex contact
271  const double positionAlongEdge = Vec3D::dot(edgeBranch[id], edge_[id]);
272  if (positionAlongEdge <= 0) {
273  //possible contact with left vertex
274  distance = edgeBranch[id].getLength();
275  if (distance > distanceMax) return false;
276  // check vertex ids
277  for (auto triangleId: vertexNeighbors[id])
278  {
279  if (triangleId<this->getId()) return false;
280  }
281  normal = edgeBranch[id] / -distance;
282  type = 4 + id; // Vertex contact
283  } else if (positionAlongEdge >= edgeLength_[id]) {
284  //contact with right vertex
285  const size_t idRight = (id + 1) % 3;
286  distance = edgeBranch[idRight].getLength();
287  if (distance > distanceMax) return false;
288  // check vertex ids
289  for (auto triangleId: vertexNeighbors[idRight])
290  {
291  if (triangleId<this->getId()) return false;
292  }
293  type = 4 + idRight; // Vertex contact
294  normal = edgeBranch[idRight] / -distance;
295 
296  } else {
297  // edge contact
298  normal = edge_[id] * positionAlongEdge - edgeBranch[id];
299  distance = normal.getLength();
300  if (distance > distanceMax) return false;
301  normal /= distance;
302  type = 1 + id;
303  }
304 
305  overlap = p.getRadius() - distance;
306  return true;
307 }
308 
315 const Vec3D MeshTriangle::getVelocityAtContact(const Vec3D& contact) const
316 {
317  Vec3D m = getBaricentricWeight(contact);
318  return m.x()*vertexVelocity_[0] + m.y()*vertexVelocity_[1] + m.z()*vertexVelocity_[2];
319 };
320 
326 const Vec3D MeshTriangle::getBaricentricWeight(const Vec3D& contact) const
327 {
328  Vec3D m;
329  // The area of a triangle is
330  // Taken from https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates
331  // Mdouble areaABC = Vec3D::dot( getFaceNormal(), Vec3D::cross(vertex_[1]-vertex_[0], vertex_[2]-vertex_[0] ) ) ;
332  // logger.assert_always(std::fabs(areaABC-area_*2)<1e-8, "OOPS, triangle area calculared wrong % %", areaABC, area_*2);
333  Mdouble areaPBC = 0.5*Vec3D::dot( getFaceNormal(), Vec3D::cross(vertex_[1]-contact, vertex_[2]-contact ) ) ;
334  Mdouble areaPCA = 0.5*Vec3D::dot( getFaceNormal(), Vec3D::cross(vertex_[2]-contact, vertex_[0]-contact ) ) ;
335 
336  m.X = areaPBC / area_ ; // alpha
337  m.Y = areaPCA / area_ ; // beta
338  m.Z = 1.0f - m.X - m.Y ; // gamma
339  return m;
340 }
341 
342 void MeshTriangle::rotate(const Vec3D& angularVelocityDt)
343 {
344  if (!angularVelocityDt.isZero())
345  {
346  BaseInteractable::rotate(angularVelocityDt);
348  }
349 }
350 
354 void MeshTriangle::read(std::istream& is)
355 {
356  BaseWall::read(is);
357 
358  unsigned int i, j, s1, s2, Id;
359  std::string dummy;
360 
361  is >> dummy >> s1;
362  vertexNeighbors.reserve(s1);
363  for (i=0; i<s1; i++)
364  {
365  is >> dummy >> s2;
366  std::vector<unsigned int> vN;
367  vN.reserve(s2);
368 
369  for (j=0; j<s2; j++)
370  {
371  is >> Id;
372  vN.push_back(Id);
373  }
374  vertexNeighbors.push_back(vN);
375 
376  }
377 
378 
379 
380  is >> dummy;
381  for (int i = 0; i < 3; i++)
382  {
383  is >> vertexInLabFrame_[i];
384  }
385  is >> dummy;
386  for (int i = 0; i < 3; i++)
387  {
388  is >> vertexIds_[i];
389  }
390 
391  is >> dummy >> invMass_;
392  is >> dummy >> isActive;
393 
394  checkActive();
395  // updateVerticesFromParticles();
397 }
398 
403 void MeshTriangle::write(std::ostream& os) const
404 {
405  BaseWall::write(os);
406  unsigned int i, j, s1, s2;
407  s1 = vertexNeighbors.size();
408  os << " vertexNeighbors " << s1;
409  for (i=0; i<s1; i++)
410  {
411  s2 = vertexNeighbors[i].size();
412  os << " vertexNeighborsElements " << s2;
413  for (j=0; j<s2; j++)
414  {
415  os << " " << vertexNeighbors[i][j];
416  }
417  }
418 
419  os << " vertexInLabFrame ";
420  for (int i = 0; i < 3; i++)
421  {
422  os << ' ' << vertexInLabFrame_[i];
423  }
424  os << " edgeParticleIds ";
425  for (int i = 0; i < 3; i++)
426  {
427  os << ' ' << vertexIds_[i];
428  }
429 
430  os << " invMass " << invMass_;
431 
432  os << " isActive " << isActive;
433 
434  // Note: need not to write faceNormal_ and area_, as these are recalculated
435  // on read.
436 }
437 
439 {
440  if (!isActive) return;
441 
442  const unsigned long s = vtk.points.size();
443  for (auto v : vertex_)
444  {
445  vtk.points.push_back(v);
446  }
447  std::vector<double> cell;
448  cell.reserve(3);
449  cell.push_back(s);
450  cell.push_back(s + 1);
451  cell.push_back(s + 2);
452 
453  vtk.triangleStrips.push_back(cell);
454 }
455 
456 void MeshTriangle::setVertices(const Vec3D A, const Vec3D B, const Vec3D C)
457 {
458  setPosition((A + B + C) / 3);
459  setOrientation({1, 0, 0, 0});
460  vertexInLabFrame_[0] = A - getPosition();
461  vertexInLabFrame_[1] = B - getPosition();
462  vertexInLabFrame_[2] = C - getPosition();
463  //vertexInLabFrame_[0] = A;
464  //vertexInLabFrame_[1] = B;
465  //vertexInLabFrame_[2] = C;
467 }
468 
469 void MeshTriangle::setVertexVelocities(const Vec3D A, const Vec3D B, const Vec3D C)
470 {
471  vertexVelocity_[0] = A;
472  vertexVelocity_[1] = B;
473  vertexVelocity_[2] = C;
474 }
475 
479 void MeshTriangle::setVertexIds(unsigned int i, unsigned int j, unsigned int k)
480 {
481  vertexIds_[0] = i;
482  vertexIds_[1] = j;
483  vertexIds_[2] = k;
485 }
486 
492 {
493  BaseWall::setHandler(handler);
494 
495  if (handler->getDPMBase()->particleHandler.getNumberOfObjects()==0)
496  {
497  // Without this, restart does not work
498  return;
499  }
500 
502 }
503 
509 {
510  // Need to get references to the particles
511  checkActive();
512  if (!isActive) return;
513 
516 }
517 
524 {
525  unsigned int i;
526  for (i=0; i<3; i++)
527  {
528  if (vertexIds_[i] == id)
529  {
530  vertexParticle_[i] = nullptr;
531  isActive = false;
532  }
533  }
534 }
535 
544 {
545  unsigned int i;
546  for (i=0; i<3; i++)
547  {
548  if (vertexIds_[i] == id)
549  {
550  vertexParticle_[i] = p;
551  checkActive();
553  }
554  }
555 }
556 
562 {
563  if (getHandler())
564  {
565  unsigned int i;
566  for (i=0; i<3; i++)
567  {
569  }
570  checkActive();
572  }
573 }
574 
580 {
582 }
583 
588 {
589  // Note this can not be done in the read sequence, as the particles are not yet available there
591 }
592 
598 {
600 }
601 
608 void MeshTriangle::move(const Vec3D& move)
609 {
612 }
613 
614 void MeshTriangle::setVertices(const Vec3D A, const Vec3D B, const Vec3D C, const Vec3D position)
615 {
616  setPosition(position);
617  setOrientation({1, 0, 0, 0});
618  vertexInLabFrame_[0] = A - getPosition();
619  vertexInLabFrame_[1] = B - getPosition();
620  vertexInLabFrame_[2] = C - getPosition();
622 }
623 
631 {
632  // logger(INFO, "Position: A: %, B: %, C: %", vertex_[0], vertex_[1], vertex_[2]);
633  for (int i = 0; i < 3; i++)
634  {
637  vertex_[i] += getPosition();
638  }
641 
642  edge_ = {vertex_[1] - vertex_[0], vertex_[2] - vertex_[1], vertex_[0] - vertex_[2]};
644  area_ = 0.5*faceNormal_.getLength();
645  logger.assert_always(0.5*sqrt(Vec3D::cross(vertex_[1] - vertex_[0], vertex_[2] - vertex_[1]).getLengthSquared())==area_, "OOPS, face area wrong");
646 
648 
649  for (int i = 0; i < 3; i++)
650  {
652  edgeLength_[i] = edge_[i].getLength();
653  edge_[i] /= edgeLength_[i];
654  edgeNormal_[i].normalise();
655  }
656  //logger(INFO,"vertex %,%,% edge %,%,% face %",vertex_[0],vertex_[1],vertex_[2],edgeNormal_[0],edgeNormal_[1],edgeNormal_[2],faceNormal_);
657 }
658 
664 bool MeshTriangle::isLocal(Vec3D& min, Vec3D& max) const
665 {
666  min = vertexMin_;
667  max = vertexMax_;
668  return true;
669 }
670 
675 bool MeshTriangle::isInsideTriangle(const Vec3D &point) const
676 {
677  const Vec3D branch0 = point - vertex_[0];
678  const Vec3D branch1 = point - vertex_[1];
679  const Vec3D branch2 = point - vertex_[2];
680 
681  //compute total area
682  Mdouble s = sqrt(Vec3D::cross(vertex_[1] - vertex_[0], vertex_[2] - vertex_[1]).getLengthSquared());
683  //compute barycentric coordinates
684  Mdouble s0 = sqrt(Vec3D::cross(branch0, branch1).getLengthSquared())/s;
685  Mdouble s1 = sqrt(Vec3D::cross(branch1, branch2).getLengthSquared())/s;
686  Mdouble s2 = sqrt(Vec3D::cross(branch2, branch0).getLengthSquared())/s;
687  // return (1 > s0 > 0 && 1 > s1 > 0 && 1 > s2 > 0) && (1 > s0+s1 > 0 && 1 > s1+s2 > 0 && 1 > s2+s0 > 0);
688 
689  Mdouble eps = 1e-12;
690  return ((1-eps) > s0 > eps && (1-eps) > s1 > eps && (1-eps) > s2 > eps) && ((1-eps) > s0+s1 > eps && (1-eps) > s1+s2 > eps && (1-eps) > s2+s0 > eps);
691 
692 }
693 
694 
696 {
697  return invMass_;
698 }
699 
706 {
707  logger.assert_always(mass > 0.0,
708  "Error in MeshTriangle::setMass, the given mass to be set must be positive.");
709  invMass_ = 1.0 / mass;
710 
711 }
712 
719 {
720  if (isActive)
721  {
722  // Area in Normaldirection
723  // Calculate F = p*A/3.0
724  // The division by 3.0 is to split the force evenly between the points
725  Vec3D pressureForce = getArea()*pressure*getFaceNormal()/3.0;
726  for (unsigned int j=0; j<3; j++){
727  vertexParticle_[j]->addForce(pressureForce);
728  }
729  }
730 }
731 
738 {
739  if (isActive)
740  {
741  force /= 3.0;
742  for (unsigned int j=0; j<3; j++){
743  vertexParticle_[j]->addForce(force);
744  }
745  }
746 
747 }
unsigned int getId() const
Returns the unique identifier of any particular object.
Definition: BaseObject.h:125
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
void setNormal(Vec3D normal)
Sets the normal vector between the two interacting objects.
Mdouble X
the vector components
Definition: Vector.h:65
void setHandler(WallHandler *handler) override
Set the handler.
void write(std::ostream &os) const override
Writes an MeshTriangle to an output stream, for example a restart file.
virtual bool isSphericalParticle() const
Definition: BaseParticle.h:645
std::array< Vec3D, 3 > vertexVelocity_
Definition: MeshTriangle.h:287
void setVertexVelocities(Vec3D A, Vec3D B, Vec3D C)
Sets the velocity of the vertex points.
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here...
void setOverlap(Mdouble overlap)
Set the overlap between the two interacting object.
double Mdouble
Definition: GeneralDefine.h:34
void addForce(const Vec3D &addForce)
Adds an amount to the force on this BaseInteractable.
unsigned int getNumberOfObjects() const override
Returns the number of objects in the container. In parallel code this practice is forbidden to avoid ...
void normalise()
Makes this Vec3D unit length.
Definition: Vector.cc:123
void setVertexIds(unsigned int i, unsigned int j, unsigned int k)
sets the ids of the vertex particles. Calls retrieveVertexParticles.
void move(const Vec3D &move) override
void handleParticleRemoval(unsigned int id) override
Handles the removal of particles to the particle Handler.
T * getObjectById(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:565
void checkInteractions(InteractionHandler *interactionHandler, unsigned int timeStamp) override
Checks, if the forces of all interctions should be applied.
bool isLocal(Vec3D &min, Vec3D &max) const override
Determines if the triangle is considered local.
void actionsOnRestart() override
Actions executed on restart.
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
virtual void setHandler(WallHandler *handler)
A function which sets the WallHandler for this BaseWall.
Definition: BaseWall.cc:127
void setContactPoint(Vec3D contactPoint)
Set the location of the contact point between the two interacting objects.
void write(std::ostream &os) const override
Function that writes a BaseWall to an output stream, usually a restart file.
Definition: BaseWall.cc:102
bool isInsideTriangle(const Vec3D &point) const
Determines if a given point is within the triangle.
const Vec3D & getContactPoint() const
Gets constant reference to contact point (vector).
void applyForce(Vec3D force)
Apply the given force to the triangle.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:76
void rotate(Vec3D &position) const
Applies the rotation to a position.
Definition: Quaternion.cc:563
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:369
std::string getName() const override
Returns the name of the object.
void setDistance(Mdouble distance)
Sets the interaction distance between the two interacting objects.
void handleParticleAddition(unsigned int id, BaseParticle *p) override
Handles the addition of particles to the particle Handler.
std::array< double, 3 > edgeLength_
Definition: MeshTriangle.h:303
Vec3D vertexMax_
Definition: MeshTriangle.h:294
bool isZero() const
Checks if ALL elements are zero.
Definition: Vector.h:102
Mdouble & z()
RW reference to Z.
Definition: Vector.h:368
Stores information about interactions between two interactable objects; often particles but could be ...
static Mdouble getLength(const Vec3D &a)
Calculates the length of a Vec3D: .
Definition: Vector.cc:331
const Vec3D & getNormal() const
Gets the normal vector between the two interacting objects.
WallHandler * getHandler() const
A function which returns the WallHandler that handles this BaseWall.
Definition: BaseWall.cc:136
std::array< Vec3D, 3 > vertexInLabFrame_
Definition: MeshTriangle.h:280
std::array< BaseParticle *, 3 > vertexParticle_
Definition: MeshTriangle.h:288
std::array< MeshTriangle *, 3 > neighbor
Definition: MeshTriangle.h:258
void actionsAfterParticleGhostUpdate() override
actionsPerformed after the position update of (ghost-) particles.
void setMultiContactIdentifier(unsigned int multiContactIdentifier_)
std::array< unsigned int, 3 > vertexIds_
Definition: MeshTriangle.h:302
std::array< Vec3D, 3 > edge_
Definition: MeshTriangle.h:300
Mdouble getWallInteractionRadius(const BaseWall *wall) const
returns the radius plus the interactionDistance
Definition: BaseParticle.h:386
void updateVerticesFromParticles()
Retrieve new positions from updated vertex particles.
static Vec3D min(const Vec3D &a, const Vec3D &b)
Calculates the pointwise minimum of two Vec3D.
Definition: Vector.cc:102
BaseInteraction * getInteraction(BaseInteractable *P, BaseInteractable *I, unsigned timeStamp)
Returns the Interaction between the BaseInteractable's P and I.
Mdouble getComponent(int index) const
Returns the requested component of this Vec3D.
Definition: Vector.cc:194
BaseInteraction * getInteractionWith(BaseParticle *p, unsigned timeStamp, InteractionHandler *interactionHandler) override
Definition: MeshTriangle.cc:48
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created...
Definition: DPMBase.h:1395
std::vector< std::vector< double > > triangleStrips
Definition: BaseWall.h:39
Container to store Interaction objects.
Mdouble & x()
RW reference to X.
Definition: Vector.h:344
void applyPressure(Mdouble presure)
Apply a force pointing in normal direction corresponding to the specified pressure.
Vec3D faceNormal_
Definition: MeshTriangle.h:309
Mdouble getArea() const
Returns the area of the triangle.
Definition: MeshTriangle.h:148
void setMass(Mdouble mass)
static Vec3D cross(const Vec3D &a, const Vec3D &b)
Calculates the cross product of two Vec3D: .
Definition: Vector.cc:163
Mdouble getRadius() const
Returns the particle's radius.
Definition: BaseParticle.h:348
void setVertices(Vec3D A, Vec3D B, Vec3D C)
Sets member variables such that the wall represents a triangle with vertices A, B, C.
Mdouble getOverlap() const
Returns a Mdouble with the current overlap between the two interacting objects.
Mdouble & y()
RW reference to Y.
Definition: Vector.h:356
const Vec3D getVelocityAtContact(const Vec3D &contact) const override
Calculates the local velocity at a specified point.
void read(std::istream &is) override
Function that reads a BaseWall from an input stream, usually a restart file.
Definition: BaseWall.cc:80
std::vector< std::vector< unsigned int > > vertexNeighbors
Definition: MeshTriangle.h:263
Mdouble Y
Definition: Vector.h:65
unsigned getGroupId() const
Definition: BaseObject.h:137
void updateVertexAndNormal()
Update vertexMin_, vertexMax_ and faceNormal_ for an updated position.
Container to store all BaseWall.
Definition: WallHandler.h:42
void setPosition(const Vec3D &position)
Sets the position of this BaseInteractable.
std::vector< Vec3D > points
Definition: BaseWall.h:38
void writeVTK(VTKContainer &vtk) const override
bool getDistanceAndNormal(const BaseParticle &p, Mdouble &distance, Vec3D &normal_return) const override
Compute the distance from the wall for a given BaseParticle and return if there is a collision...
Vec3D vertexMin_
Definition: MeshTriangle.h:293
Mdouble getInvMass() const override
virtual void rotate(const Vec3D &angularVelocityDt)
Rotates this BaseInteractable.
const Vec3D getBaricentricWeight(const Vec3D &contact) const
Calculates the barycentric weight of a specified point.
void rotate(const Vec3D &angularVelocity) override
Rotates this BaseInteractable.
std::array< Vec3D, 3 > vertex_
Definition: MeshTriangle.h:286
const std::vector< BaseInteraction * > & getInteractions() const
Returns a list of interactions which belong to this interactable.
void checkActive()
Check if the triangle is considered active.
Vec3D getFaceNormal() const
Returns the face normal.
Definition: MeshTriangle.h:143
void setWallInteraction(bool flag)
void setOrientation(const Quaternion &orientation)
Sets the orientation of this BaseInteractable.
void addTorque(const Vec3D &addTorque)
Adds an amount to the torque on this BaseInteractable.
virtual const Vec3D & getVelocity() const
Returns the velocity of this interactable.
Definition: Vector.h:49
virtual void move(const Vec3D &move)
Moves this BaseInteractable by adding an amount to the position.
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
Definition: BaseHandler.h:725
void retrieveVertexParticles()
Tries to get pointers to all vertex particles from the handler.
bool getDistanceNormalOverlapType(const BaseParticle &p, Mdouble &distance, Vec3D &normal, Mdouble &overlap, unsigned int &type) const
void read(std::istream &is) override
Reads an MeshTriangle from an input stream, for example a restart file.
const Quaternion & getOrientation() const
Returns the orientation of this BaseInteractable.
BaseInteraction * getExistingInteraction(const BaseInteractable *P, const BaseInteractable *I) const
Returns the Interaction between the BaseInteractable's P and I if it exists, otherwise returns a null...
Mdouble Z
Definition: Vector.h:65
Mdouble invMass_
Definition: MeshTriangle.h:313
bool getRotation() const
Indicates whether particle rotation is enabled or disabled.
Definition: DPMBase.h:559
std::array< Vec3D, 3 > edgeNormal_
Definition: MeshTriangle.h:299
Mdouble area_
Definition: MeshTriangle.h:310
static Vec3D max(const Vec3D &a, const Vec3D &b)
Calculates the pointwise maximum of two Vec3D.
Definition: Vector.cc:89