MercuryDPM  Beta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AngledPeriodicBoundary.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 #include "AngledPeriodicBoundary.h"
26 #include "ParticleHandler.h"
27 #include "Particles/BaseParticle.h"
28 #include "Math/MatrixSymmetric.h"
30 
35 {
36 #ifdef DEBUG_CONSTRUCTOR
37  std::cout << "AngledPeriodicBoundary::copy() const finished" << std::endl;
38 #endif
39  return new AngledPeriodicBoundary(*this);
40 }
41 
50 void AngledPeriodicBoundary::set(Vec3D normalLeft, Vec3D normalRight, Vec3D origin)
51 {
52  origin_ = origin;
53  leftNormal_ = normalLeft / Vec3D::getLength(normalLeft);
54  rightNormal_ = normalRight / Vec3D::getLength(normalRight);
55  //http://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d
59  Matrix3D vx = {0, -v.Z, v.Y,
60  v.Z, 0, -v.X,
61  -v.Y, v.X, 0};
62  Matrix3D eye = {1, 0, 0, 0, 1, 0, 0, 0, 1};
63  rotateLeft = eye - vx + vx * vx * ((1 - c) / s / s);
64  rotateRight = eye + vx + vx * vx * ((1 - c) / s / s);
65  //std::cout << "rotationMatrix" << rotationMatrix << std::endl;
66  commonAxis_ = v / s;
72  // walls; maybe this has to wait till quaternions are implemented.}
73  //angularShift = 0;
74  // std::cout << "common_axis " << common_axis
75  // << ", radialAxis_left " << radialAxis_left
76  // << ", radialAxis_right " << radialAxis_right
77  // << ", angularShift " << angularShift
78  // << std::endl;
79 }
80 
85 {
86  return distance(P.getPosition());
87 }
88 
93 {
94  Vec3D position = P - origin_;
95  Mdouble distance_left = Vec3D::dot(position, leftNormal_);
96  Mdouble distance_right = -Vec3D::dot(position, rightNormal_);
97 
98  if (distance_left < distance_right)
99  {
100  leftWall_ = true;
101  //std::cout << "left wall, " << position << ", distance " << distance_left << "<" << distance_right << std::endl;
102  return distance_left;
103  }
104  else
105  {
106  leftWall_ = false;
107  //std::cout << "right wall, " << position << ", distance " << distance_right << "<" << distance_left << std::endl;
108  return distance_right;
109  }
110 }
111 
116 {
117  Vec3D position = P->getPosition() - origin_;
118  if (leftWall_)
119  {
120  Mdouble normalDistance = Vec3D::dot(position, leftNormal_);
121  Mdouble radialDistance = Vec3D::dot(position, leftRadialAxis_);
122  P->move(normalDistance * differenceNormal_ + radialDistance * differenceRadialAxis_);
123  Mdouble normalVelocity = Vec3D::dot(P->getVelocity(), leftNormal_);
124  Mdouble radialVelocity = Vec3D::dot(P->getVelocity(), leftRadialAxis_);
125  P->accelerate(normalVelocity * differenceNormal_ + radialVelocity * differenceRadialAxis_);
126  Mdouble normalAngularDistance = Vec3D::dot(P->getOrientation(), leftNormal_);
127  Mdouble radialAngularDistance = Vec3D::dot(P->getOrientation(), leftRadialAxis_);
129  P->rotate(normalAngularDistance * differenceNormal_ + radialAngularDistance * differenceRadialAxis_);
130  Mdouble normalAngularVelocity = Vec3D::dot(P->getAngularVelocity(), leftNormal_);
131  Mdouble radialAngularVelocity = Vec3D::dot(P->getAngularVelocity(), leftRadialAxis_);
132  P->angularAccelerate(normalAngularVelocity * differenceNormal_ + radialAngularVelocity * differenceRadialAxis_);
133  leftWall_ = false;
135  //std::cout << "shift to right wall, " << P->getInteractions().size() << std::endl;
136  for (BaseInteraction* i : P->getInteractions())
137  {
138  if (i->getP()->getIndex() >= P->getIndex())
139  {
140  i->rotateHistory(rotateRight);
141  }
142  }
143  }
144  else
145  {
146  Mdouble normalDistance = Vec3D::dot(position, rightNormal_);
147  Mdouble radialDistance = Vec3D::dot(position, rightRadialAxis_);
148  P->move(-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
149  Mdouble normalVelocity = Vec3D::dot(P->getVelocity(), rightNormal_);
150  Mdouble radialVelocity = Vec3D::dot(P->getVelocity(), rightRadialAxis_);
151  P->accelerate(-normalVelocity * differenceNormal_ - radialVelocity * differenceRadialAxis_);
152  Mdouble normalAngularDistance = Vec3D::dot(P->getOrientation(), rightNormal_);
153  Mdouble radialAngularDistance = Vec3D::dot(P->getOrientation(), rightRadialAxis_);
154  P->rotate(-normalAngularDistance * differenceNormal_ - radialAngularDistance * differenceRadialAxis_);
155  Mdouble normalAngularVelocity = Vec3D::dot(P->getAngularVelocity(), rightNormal_);
156  Mdouble radialAngularVelocity = Vec3D::dot(P->getAngularVelocity(), rightRadialAxis_);
157  P->angularAccelerate(-normalAngularVelocity * differenceNormal_ - radialAngularVelocity * differenceRadialAxis_);
158  leftWall_ = true;
159  //std::cout << "shift to left wall, " << P->getPosition() << std::endl;
160  for (BaseInteraction* i : P->getInteractions())
161  {
162  if (i->getP()->getIndex() >= P->getIndex()) //if it is the deleted interaction
163  {
164  i->rotateHistory(rotateLeft);
165  }
166  }
167  }
168 }
169 
174 {
176  Vec3D position1 = P1 - origin_;
177  Vec3D position2 = P2 - origin_;
178  Mdouble normalDistance;
179  Mdouble radialDistance;
180  if (leftWall_)
181  {
182  normalDistance = Vec3D::dot(position1, leftNormal_);
183  radialDistance = Vec3D::dot(position1, leftRadialAxis_);
184  P1 += (normalDistance * differenceNormal_ + radialDistance * differenceRadialAxis_);
185  normalDistance = Vec3D::dot(position2, leftNormal_);
186  radialDistance = Vec3D::dot(position2, leftRadialAxis_);
187  P2 += (normalDistance * differenceNormal_ + radialDistance * differenceRadialAxis_);
188  leftWall_ = false;
189  }
190  else
191  {
192  normalDistance = Vec3D::dot(position1, rightNormal_);
193  radialDistance = Vec3D::dot(position1, rightRadialAxis_);
194  P1 += (-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
195  normalDistance = Vec3D::dot(position2, rightNormal_);
196  radialDistance = Vec3D::dot(position2, rightRadialAxis_);
197  P2 += (-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
198  leftWall_ = true;
199  }
200 }
201 
205 void AngledPeriodicBoundary::read(std::istream & is)
206 {
207  BaseBoundary::read(is);
208  std::string dummy;
209  is >> dummy >> leftNormal_ >> dummy >> rightNormal_ >> dummy >> origin_;
210  set(leftNormal_, rightNormal_, origin_);
211 }
212 
216 void AngledPeriodicBoundary::oldRead(std::istream & is)
217 {
218  std::string dummy;
219  is >> dummy >> leftNormal_ >> dummy >> rightNormal_ >> dummy >> origin_;
220  set(leftNormal_, rightNormal_, origin_);
221 }
222 
226 void AngledPeriodicBoundary::write(std::ostream & os) const
227 {
229  os << " normal_left " << leftNormal_
230  << " normal_right " << rightNormal_
231  << " origin " << origin_;
232 }
233 
238 {
239  return "AngledPeriodicBoundary";
240 }
241 
246 {
247  if (leftWall_)
248  return leftNormal_;
249  else
250  return rightNormal_;
251 }
252 
257 {
258  return acos(Vec3D::dot(leftNormal_, rightNormal_));
259 }
260 
265 {
267  {
268  //std::cout << "Copy particle " << p->getIndex() << " to new ghost particle" << std::endl;
269  //Step 1: Copy the particle to new ghost particle.
270  BaseParticle* pGhost = p->copy();
271 
272  //std::cout << "pGhostInteractions " << pGhost->getInteractions().size();
273  //Step 2: Copy the interactions to the ghost particle.
275  //std::cout << "-> " << pGhost->getInteractions().size() << std::endl;
276 
277  //Step 3: Shift the ghost to the 'reflected' location.
278  shiftPosition(pGhost);
279  //rotateHistory
280  //std::cout << "pGhostPosition " << pGhost->getPosition() << std::endl;
281 
282  // BaseParticle* F0 = P->copy();
283  // shiftPosition(F0);
284 
285  //Step 4: If Particle is double shifted, get correct original particle
286  BaseParticle* from = p;
287  while (from->getPeriodicFromParticle() != nullptr)
288  from = from->getPeriodicFromParticle();
289  pGhost->setPeriodicFromParticle(from);
290 
291  pH.addObject(pGhost);
292  }
293 }
294 
299 {
300  if (distance(*P) < 0)
301  {
302  shiftPosition(P);
303  }
304  return false;
305 }
Vec3D origin_
common point of both walls
BaseParticle * getLargestParticle() const
Gets a pointer to the largest BaseParticle (by interactionRadius) in this ParticleHandler.
unsigned int getIndex() const
Returns the index of the object in the handler.
Definition: BaseObject.cc:106
void rotate(const Vec3D &rotate)
Rotates this BaseInteractable.
AngledPeriodicBoundary * copy() const final
Used to create a copy of the object NB: purely virtual function.
Mdouble X
the vector components
Definition: Vector.h:52
void shiftPositions(Vec3D &P1, Vec3D &P2)
only needed in StatisticsVector
void write(std::ostream &os) const =0
Adds object's id_ to given ostream NB: purely virtual function.
Definition: BaseBoundary.cc:76
bool checkBoundaryAfterParticleMoved(BaseParticle *P, ParticleHandler &pH UNUSED)
double Mdouble
void read(std::istream &is)
reads wall
Vec3D leftRadialAxis_
outward unit normal vector for left wall
void setPeriodicFromParticle(BaseParticle *p)
Assigns the pointer to the 'original' particle this one's a periodic copy of.
void oldRead(std::istream &is)
virtual const Vec3D & getAngularVelocity() const
Returns the angular velocity of this interactable.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:187
void accelerate(const Vec3D &vel)
Increases the particle's velocity_ by the given vector.
Mdouble getOpeningAngle()
angle between walls in radians
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
const Vec3D & getOrientation() const
Returns the orientation of this BaseInteractable.
Stores information about interactions between two interactable objects; often particles but could be ...
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
virtual void addObject(BaseParticle *P)
Adds a BaseParticle to the ParticleHandler.
Vec3D commonAxis_
The normalized cross product of the left and right normal vector. This vector points in the direction...
#define UNUSED
Definition: GeneralDefine.h:37
Mdouble distance(const BaseParticle &P)
Returns the distance of the wall to the particle and sets left_wall = true, if the left wall is the w...
void set(Vec3D normalLeft, Vec3D normalRight, Vec3D origin)
Defines a periodic wall.
static Vec3D cross(const Vec3D &a, const Vec3D &b)
Calculates the cross product of two Vec3D: .
Definition: Vector.cc:268
void copyInteractionsForPeriodicParticles(const BaseInteractable &p)
Copies interactions to this BaseInteractable whenever a periodic copy made.
Container to store all BaseParticle.
Mdouble Y
Definition: Vector.h:52
virtual std::string getName() const
Returns the name of the object.
bool leftWall_
true if closest wall is the left wall
Vec3D rightRadialAxis_
outward unit normal vector for right wall
Mdouble getLength() const
Calculates the length of this Vec3D: .
Definition: Vector.cc:416
Vec3D rightNormal_
outward unit normal vector for right wall
void angularAccelerate(const Vec3D &angVel)
Increases the particle's angularVelocity_ by the given vector.
const std::list< BaseInteraction * > & getInteractions() const
Returns a reference to the list of interactions in this BaseInteractable.
Implementation of a 3D matrix.
Definition: Matrix.h:36
virtual const Vec3D & getVelocity() const
Returns the velocity of this interactable.
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
virtual void move(const Vec3D &move)
Moves this BaseInteractable by adding an amount to the position.
void shiftPosition(BaseParticle *P)
shifts the particle (after distance set the left_wall value)
Mdouble Z
Definition: Vector.h:52
Mdouble getInteractionRadius() const
Returns the particle's interaction radius, which might be different from radius_ (e.g., when dealing with wet particles)
void createPeriodicParticles(BaseParticle *P, ParticleHandler &pH)
virtual BaseParticle * copy() const
Particle copy method. It calls to copy constructor of this Particle, useful for polymorfism.
void read(std::istream &is)=0
Reads the object's id_ from given istream NB: purely virtual function.
Definition: BaseBoundary.cc:67
void write(std::ostream &os) const
outputs wall