MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AngledPeriodicBoundary.h
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 #ifndef AngledPeriodicBoundary_H
27 #define AngledPeriodicBoundary_H
28 
29 #include "../BaseBoundary.h"
30 #include "../Particles/TangentialSpringParticle.h"
31 #include "../Particles/BaseParticle.h"
32 
39 public:
40 
41  virtual AngledPeriodicBoundary* copy() const
42  {
43  #ifdef CONSTUCTOR_OUTPUT
44  std::cerr << "virtual AngledPeriodicBoundary* copy() const finished" << std::endl;
45  #endif
46  return new AngledPeriodicBoundary(*this);
47  }
48 
49 
50  //todo constructors instead of set functions?
51  //AngledPeriodicBoundary (Vec3D normal_left_, Vec3D normal_right_, Vec3D origin_)
52 
58  void set (Vec3D normal_left_, Vec3D normal_right_, Vec3D origin_) {
59  origin=origin_;
60  normal_left = normal_left_ / GetLength(normal_left_);
61  normal_right = normal_right_ / GetLength(normal_right_);
63  common_axis /= GetLength(common_axis);
69  //angularShift = 0;
70  // std::cout << "common_axis " << common_axis
71  // << ", radialAxis_left " << radialAxis_left
72  // << ", radialAxis_right " << radialAxis_right
73  // << ", angularShift " << angularShift
74  // << std::endl;
75  }
84  return distance(P.get_Position());
85  }
86 
87  //this function should be cheap, as it has to be computed for all particles
88  Mdouble distance(const Vec3D &P) {
89  Vec3D position = P-origin;
90  Mdouble distance_left = Dot(position,normal_left);
91  Mdouble distance_right = -Dot(position,normal_right);
92 
93  if (distance_left<distance_right) {
94  left_wall = true;
95  //std::cout << "left wall, " << position << ", distance " << distance_left << "<" << distance_right << std::endl;
96  return distance_left;
97  } else {
98  left_wall = false;
99  //std::cout << "right wall, " << position << ", distance " << distance_right << "<" << distance_left << std::endl;
100  return distance_right;
101  }
102  }
103 
107  Vec3D position = P->get_Position()-origin;
108  if (left_wall) {
109  Mdouble normalDistance = Dot(position,normal_left);
110  Mdouble radialDistance = Dot(position,radialAxis_left);
111  P->move(normalDistance*diff_normal+radialDistance*diff_radial);
112  Mdouble normalVelocity = Dot(P->get_Velocity(),normal_left);
113  Mdouble radialVelocity = Dot(P->get_Velocity(),radialAxis_left);
114  P->accelerate(normalVelocity*diff_normal+radialVelocity*diff_radial);
115  Mdouble normalAngularDistance = Dot(P->get_Angle(),normal_left);
116  Mdouble radialAngularDistance = Dot(P->get_Angle(),radialAxis_left);
118  P->rotate(normalAngularDistance*diff_normal+radialAngularDistance*diff_radial);
119  left_wall = false;
121  //std::cout << "shift to right wall, " << P->get_Position() << std::endl;
122  }
123  else {
124  Mdouble normalDistance = Dot(position,normal_right);
125  Mdouble radialDistance = Dot(position,radialAxis_right);
126  P->move(-normalDistance*diff_normal-radialDistance*diff_radial);
127  Mdouble normalVelocity = Dot(P->get_Velocity(),normal_right);
128  Mdouble radialVelocity = Dot(P->get_Velocity(),radialAxis_right);
129  P->accelerate(-normalVelocity*diff_normal-radialVelocity*diff_radial);
130  Mdouble normalAngularDistance = Dot(P->get_Angle(),normal_right);
131  Mdouble radialAngularDistance = Dot(P->get_Angle(),radialAxis_right);
132  P->rotate(-normalAngularDistance*diff_normal-radialAngularDistance*diff_radial);
133  left_wall = true;
134  //std::cout << "shift to left wall, " << P->get_Position() << std::endl;
135  }
136  }
137 
138  // ///returns the shifted particle w/o actually shifting
139  // Vec3D get_shifted_position(Vec3D &Position) {
140  // if (left_wall) {
141  // return Position + shift;
142  // }
143  // else {
144  // return Position - shift;
145  // }
146  // }
147 
148  // ///shifts two particles
149  // void shift_positions(Vec3D &PI, Vec3D &PJ) {
150  // if (left_wall) {
151  // PI += shift;
152  // PJ += shift;
153  // left_wall = false;
154  // }
155  // else {
156  // PI -= shift;
157  // PJ -= shift;
158  // left_wall = true;
159  // }
160  // }
161 
162  // ///shift P such that it is closest to Q
163  // void get_close_together(Vec3D &P,Vec3D &Q) {
164  // Mdouble PQdotn = Dot(P-Q, normal);
165  // Mdouble shift_norm2 = shift.GetLength2();
166  // //Check if P is so far from Q that a shift would move it closer
167  // if (sqr(PQdotn) > .25 * shift_norm2) {
168  // //Now determine the direction of the shift
169  // if (PQdotn>0.0) P -= shift;
170  // else P += shift;
171  // }
172  // }
173 
174 
176  void read(std::istream& is) {
177  std::string dummy;
178  is >> dummy >> normal_left >> dummy >> normal_right >> dummy >> origin;
179  }
180 
182  void print(std::ostream& os) const {
183  os << "AngledPeriodicBoundary normal_left " << normal_left
184  << " normal_right " << normal_right
185  << " origin " << origin;
186  }
187 
189  if (left_wall) return normal_left;
190  else return normal_right;
191  }
192 
195  {
196  //std::cout << "createPeriodicParticles" << std::endl;
198  {
199  BaseParticle* F0=P->copy();
200  shift_position(F0);
201 
202  //If the Particle includes TangentalSprings reverse them
203  TangentialSpringParticle* TSParticle=dynamic_cast<TangentialSpringParticle*>(F0);
204  if(TSParticle) {
205  TSParticle->reverseTangentialSprings();
206  for(std::vector<CTangentialSpring>::iterator it = TSParticle->get_TangentialSprings().begin(); it!=TSParticle->get_TangentialSprings().end();it++)
207  {
208  //std::cout << it->delta << std::endl;
209  if (!left_wall) {
210  Mdouble normalDistance = Dot(it->delta,normal_left);
211  Mdouble radialDistance = Dot(it->delta,radialAxis_left);
212  it->delta += normalDistance*diff_normal+radialDistance*diff_radial;
213  normalDistance = Dot(it->RollingSpring,normal_left);
214  radialDistance = Dot(it->RollingSpring,radialAxis_left);
215  it->RollingSpring += normalDistance*diff_normal+radialDistance*diff_radial;
216  normalDistance = Dot(it->TorsionSpring,normal_left);
217  radialDistance = Dot(it->TorsionSpring,radialAxis_left);
218  it->TorsionSpring += normalDistance*diff_normal+radialDistance*diff_radial;
219  } else {
220  Mdouble normalDistance = Dot(it->delta,normal_right);
221  Mdouble radialDistance = Dot(it->delta,radialAxis_right);
222  it->delta -= normalDistance*diff_normal+radialDistance*diff_radial;
223  normalDistance = Dot(it->RollingSpring,normal_right);
224  radialDistance = Dot(it->RollingSpring,radialAxis_right);
225  it->RollingSpring -= normalDistance*diff_normal+radialDistance*diff_radial;
226  normalDistance = Dot(it->TorsionSpring,normal_right);
227  radialDistance = Dot(it->TorsionSpring,radialAxis_right);
228  it->TorsionSpring -= normalDistance*diff_normal+radialDistance*diff_radial;
229  }
230  //std::cout << it->delta << std::endl;
231  }
232  }
233 
234  //If Particle is Mdouble shifted, get correct original particle
235  BaseParticle* From=P;
236  while(From->get_PeriodicFromParticle()!=NULL)
237  From=From->get_PeriodicFromParticle();
238  F0->set_periodicFromParticle(From);
239 
240  pH.addObject(F0);
241  return 1;
242  }
243  return 0;
244  }
245 
248  {
249  //std::cout << "checkBoundaryAfterParticleMoved" << std::endl;
250  if (distance(*P)<0)
251  shift_position(P);
252  return false;
253  }
254 
255  private:
256  //values set by the user
260  //values set by the code
261  bool left_wall;
268 };
269 #endif
Vec3D normal_right
outward unit normal vector for right wall
Vec3D radialAxis_right
outward unit normal vector for right wall
BaseParticle * getLargestParticle() const
Gets a pointer to the largest BaseParticle (by interactionRadius) in this ParticleHandler.
const Vec3D & get_Velocity() const
void print(std::ostream &os) const
outputs wall
Mdouble get_InteractionRadius() const
void rotate(const Vec3D &_new)
int createPeriodicParticles(BaseParticle *P, ParticleHandler &pH)
bool left_wall
true if closest wall is the left wall
Defines a pair of periodic walls that are angled around the origin.
virtual AngledPeriodicBoundary * copy() const
BaseBoundary copy method.
BaseParticle * get_PeriodicFromParticle() const
bool checkBoundaryAfterParticleMoved(BaseParticle *P, ParticleHandler &pH UNUSED)
Matrix3D Cross(const Vec3D &A, const Matrix3D &B)
Definition: Matrix.h:198
void read(std::istream &is)
reads wall
Mdouble distance(const Vec3D &P)
Vec3D normal_left
outward unit normal vector for left wall
void set(Vec3D normal_left_, Vec3D normal_right_, Vec3D origin_)
Defines a periodic wall, given a normal vector s.t.
Vec3D origin
common point of both walls
CTangentialSprings & get_TangentialSprings()
void set_periodicFromParticle(BaseParticle *_new)
Mdouble distance(BaseParticle &P)
Returns the distance of the wall to the particle, and sets left_wall = true, if the left wall is the ...
double Mdouble
Definition: ExtendedMath.h:33
virtual void addObject(BaseParticle *P)
Adds a BaseParticle to the ParticleHandler.
void move(const Vec3D &_new)
const Vec3D & get_Position() const
Container to store all BaseParticle.
Vec3D radialAxis_left
outward unit normal vector for left wall
#define UNUSED
Definition: ExtendedMath.h:38
const Vec3D & get_Angle() const
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:40
void accelerate(const Vec3D &_new)
virtual BaseParticle * copy() const
Particle copy method. It calls to copy contrustor of this Particle, usefull for polymorfism.
void shift_position(BaseParticle *P)
shifts the particle (after distance set the left_wall value)