MercuryDPM  Alpha
 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;
134  //std::cout << "shift to right wall, " << P->getInteractions().size() << std::endl;
135  for (BaseInteraction* i : P->getInteractions())
136  {
137  if (i->getP()->getIndex() >= P->getIndex())
138  {
139  i->rotateHistory(rotateRight);
140  }
141  }
142  }
143  else
144  {
145  Mdouble normalDistance = Vec3D::dot(position, rightNormal_);
146  Mdouble radialDistance = Vec3D::dot(position, rightRadialAxis_);
147  P->move(-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
148  Mdouble normalVelocity = Vec3D::dot(P->getVelocity(), rightNormal_);
149  Mdouble radialVelocity = Vec3D::dot(P->getVelocity(), rightRadialAxis_);
150  P->accelerate(-normalVelocity * differenceNormal_ - radialVelocity * differenceRadialAxis_);
151  Mdouble normalAngularDistance = Vec3D::dot(P->getOrientation(), rightNormal_);
152  Mdouble radialAngularDistance = Vec3D::dot(P->getOrientation(), rightRadialAxis_);
153  P->rotate(-normalAngularDistance * differenceNormal_ - radialAngularDistance * differenceRadialAxis_);
154  Mdouble normalAngularVelocity = Vec3D::dot(P->getAngularVelocity(), rightNormal_);
155  Mdouble radialAngularVelocity = Vec3D::dot(P->getAngularVelocity(), rightRadialAxis_);
156  P->angularAccelerate(-normalAngularVelocity * differenceNormal_ - radialAngularVelocity * differenceRadialAxis_);
157  leftWall_ = true;
158  //std::cout << "shift to left wall, " << P->getPosition() << std::endl;
159  for (BaseInteraction* i : P->getInteractions())
160  {
161  if (i->getP()->getIndex() >= P->getIndex()) //if it is the deleted interaction
162  {
163  i->rotateHistory(rotateLeft);
164  }
165  }
166  }
167 }
168 
173 {
175  Vec3D position1 = P1 - origin_;
176  Vec3D position2 = P2 - origin_;
177  Mdouble normalDistance;
178  Mdouble radialDistance;
179  if (leftWall_)
180  {
181  normalDistance = Vec3D::dot(position1, leftNormal_);
182  radialDistance = Vec3D::dot(position1, leftRadialAxis_);
183  P1 += (normalDistance * differenceNormal_ + radialDistance * differenceRadialAxis_);
184  normalDistance = Vec3D::dot(position2, leftNormal_);
185  radialDistance = Vec3D::dot(position2, leftRadialAxis_);
186  P2 += (normalDistance * differenceNormal_ + radialDistance * differenceRadialAxis_);
187  leftWall_ = false;
188  }
189  else
190  {
191  normalDistance = Vec3D::dot(position1, rightNormal_);
192  radialDistance = Vec3D::dot(position1, rightRadialAxis_);
193  P1 += (-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
194  normalDistance = Vec3D::dot(position2, rightNormal_);
195  radialDistance = Vec3D::dot(position2, rightRadialAxis_);
196  P2 += (-normalDistance * differenceNormal_ - radialDistance * differenceRadialAxis_);
197  leftWall_ = true;
198  }
199 }
200 
204 void AngledPeriodicBoundary::read(std::istream & is)
205 {
206  BaseBoundary::read(is);
207  std::string dummy;
208  is >> dummy >> leftNormal_ >> dummy >> rightNormal_ >> dummy >> origin_;
209  set(leftNormal_, rightNormal_, origin_);
210 }
211 
215 void AngledPeriodicBoundary::oldRead(std::istream & is)
216 {
217  std::string dummy;
218  is >> dummy >> leftNormal_ >> dummy >> rightNormal_ >> dummy >> origin_;
219  set(leftNormal_, rightNormal_, origin_);
220 }
221 
225 void AngledPeriodicBoundary::write(std::ostream & os) const
226 {
228  os << " normal_left " << leftNormal_
229  << " normal_right " << rightNormal_
230  << " origin " << origin_;
231 }
232 
237 {
238  return "AngledPeriodicBoundary";
239 }
240 
245 {
246  if (leftWall_)
247  return leftNormal_;
248  else
249  return rightNormal_;
250 }
251 
256 {
257  return acos(Vec3D::dot(leftNormal_, rightNormal_));
258 }
259 
264 {
266  {
267  //std::cout << "Copy particle " << p->getIndex() << " to new ghost particle" << std::endl;
268  //Step 1: Copy the particle to new ghost particle.
269  BaseParticle* pGhost = p->copy();
270 
271  //std::cout << "pGhostInteractions " << pGhost->getInteractions().size();
272  //Step 2: Copy the interactions to the ghost particle.
274  //std::cout << "-> " << pGhost->getInteractions().size() << std::endl;
275 
276  //Step 3: Shift the ghost to the 'reflected' location.
277  shiftPosition(pGhost);
278  //rotateHistory
279  //std::cout << "pGhostPosition " << pGhost->getPosition() << std::endl;
280 
281  // BaseParticle* F0 = P->copy();
282  // shiftPosition(F0);
283 
284  //Step 4: If Particle is double shifted, get correct original particle
285  BaseParticle* from = p;
286  while (from->getPeriodicFromParticle() != nullptr)
287  from = from->getPeriodicFromParticle();
288  pGhost->setPeriodicFromParticle(from);
289 
290  pH.addObject(pGhost);
291  }
292 }
293 
298 {
299  if (distance(*P) < 0)
300  {
301  shiftPosition(P);
302  }
303  return false;
304 }
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:108
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, overriding the version of BaseObject...
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:167
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:39
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:255
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:403
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, overriding the version of Base...
Definition: BaseBoundary.cc:67
void write(std::ostream &os) const
outputs wall