MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FiniteWall.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 
27 #ifndef FINITEWALL_H
28 #define FINITEWALL_H
29 
30 #include "BaseWall.h"
31 #include "InfiniteWall.h"
32 
33 class FiniteWall : public BaseWall
34 {
35  public:
37  {
38  #ifdef CONSTUCTOR_OUTPUT
39  std::cout<<"InfiniteWall () finished"<<std::endl;
40  #endif
41  }
42 
44  virtual FiniteWall* copy() const
45  {
46  return new FiniteWall(*this);
47  }
48 
49  void clear()
50  {
51  indSpecies = 0;
53  finite_walls.clear();
54  }
55 
57  void add_finite_wall(Vec3D normal, Vec3D point) {
58  add_finite_wall(normal,Dot(normal,point));
59  }
61  void add_finite_wall(Vec3D normal_, Mdouble position_)
62  {
63  //n is the index of the new wall
64  int n = finite_walls.size();
65  finite_walls.resize(n+1);
66  finite_walls[n].set(normal_,position_);
67 
68  // AB[n*(n-1)/2+m] is the direction of the intersecting line between walls m and n, m<n
69  // A[n*(n-1)/2+m] is a point on the intersecting line between walls m and n, m<n
70  // See http://www.netcomuk.co.uk/~jenolive/vect18d.html for finding the line where two planes meet
71  AB.resize(n*(n+1)/2);
72  A.resize (n*(n+1)/2);
73  for(int m=0; m<n; m++)
74  {
75  int id = (n-1)*n/2+m;
76  //first we cross the wall normals and normalize to obtain AB
77  AB[id] = Cross(finite_walls[m].get_Normal(), finite_walls[n].get_Normal());
78  AB[id] /= sqrt(AB[id].GetLength2());
79  //then we find a point A (using AB*x=0 as a third plane)
80  Mdouble invdet = 1.0/( +finite_walls[n].get_Normal().X*(finite_walls[m].get_Normal().Y*AB[id].Z-AB[id].Y*finite_walls[m].get_Normal().Z)
81  -finite_walls[n].get_Normal().Y*(finite_walls[m].get_Normal().X*AB[id].Z-finite_walls[m].get_Normal().Z*AB[id].X)
82  +finite_walls[n].get_Normal().Z*(finite_walls[m].get_Normal().X*AB[id].Y-finite_walls[m].get_Normal().Y*AB[id].X));
83  A[id] = Vec3D( +(finite_walls[m].get_Normal().Y*AB[id].Z-AB[id].Y*finite_walls[m].get_Normal().Z)*finite_walls[n].get_Position()
84  -(finite_walls[n].get_Normal().Y*AB[id].Z-finite_walls[n].get_Normal().Z*AB[id].Y)*finite_walls[m].get_Position()
85  +(finite_walls[n].get_Normal().Y*finite_walls[m].get_Normal().Z-finite_walls[n].get_Normal().Z*finite_walls[m].get_Normal().Y)*0.0,
86  -(finite_walls[m].get_Normal().X*AB[id].Z-finite_walls[m].get_Normal().Z*AB[id].X)*finite_walls[n].get_Position()
87  +(finite_walls[n].get_Normal().X*AB[id].Z-finite_walls[n].get_Normal().Z*AB[id].X)*finite_walls[m].get_Position()
88  -(finite_walls[n].get_Normal().X*finite_walls[m].get_Normal().Z-finite_walls[m].get_Normal().X*finite_walls[n].get_Normal().Z)*0.0,
89  +(finite_walls[m].get_Normal().X*AB[id].Y-AB[id].X*finite_walls[m].get_Normal().Y)*finite_walls[n].get_Position()
90  -(finite_walls[n].get_Normal().X*AB[id].Y-AB[id].X*finite_walls[n].get_Normal().Y)*finite_walls[m].get_Position()
91  +(finite_walls[n].get_Normal().X*finite_walls[m].get_Normal().Y-finite_walls[m].get_Normal().X*finite_walls[n].get_Normal().Y)*0.0 ) * invdet;
92  }
93 
94  // C[(n-2)*(n-1)*n/6+(m-1)*m/2+l] is a point intersecting walls l, m and n, l<m<n
95  C.resize((n-1)*n*(n+1)/6);
96  for(int m=0; m<n; m++)
97  {
98  for(int l=0; l<m; l++)
99  {
100  int id = (n-2)*(n-1)*n/6+(m-1)*m/2+l;
101  Mdouble invdet = 1.0/( +finite_walls[n].get_Normal().X*(finite_walls[m].get_Normal().Y*finite_walls[l].get_Normal().Z-finite_walls[l].get_Normal().Y*finite_walls[m].get_Normal().Z)
102  -finite_walls[n].get_Normal().Y*(finite_walls[m].get_Normal().X*finite_walls[l].get_Normal().Z-finite_walls[m].get_Normal().Z*finite_walls[l].get_Normal().X)
103  +finite_walls[n].get_Normal().Z*(finite_walls[m].get_Normal().X*finite_walls[l].get_Normal().Y-finite_walls[m].get_Normal().Y*finite_walls[l].get_Normal().X));
104  C[id] = Vec3D( +(finite_walls[m].get_Normal().Y*finite_walls[l].get_Normal().Z-finite_walls[l].get_Normal().Y*finite_walls[m].get_Normal().Z)*finite_walls[n].get_Position()
105  -(finite_walls[n].get_Normal().Y*finite_walls[l].get_Normal().Z-finite_walls[n].get_Normal().Z*finite_walls[l].get_Normal().Y)*finite_walls[m].get_Position()
106  +(finite_walls[n].get_Normal().Y*finite_walls[m].get_Normal().Z-finite_walls[n].get_Normal().Z*finite_walls[m].get_Normal().Y)*finite_walls[l].get_Position(),
107  -(finite_walls[m].get_Normal().X*finite_walls[l].get_Normal().Z-finite_walls[m].get_Normal().Z*finite_walls[l].get_Normal().X)*finite_walls[n].get_Position()
108  +(finite_walls[n].get_Normal().X*finite_walls[l].get_Normal().Z-finite_walls[n].get_Normal().Z*finite_walls[l].get_Normal().X)*finite_walls[m].get_Position()
109  -(finite_walls[n].get_Normal().X*finite_walls[m].get_Normal().Z-finite_walls[m].get_Normal().X*finite_walls[n].get_Normal().Z)*finite_walls[l].get_Position(),
110  +(finite_walls[m].get_Normal().X*finite_walls[l].get_Normal().Y-finite_walls[l].get_Normal().X*finite_walls[m].get_Normal().Y)*finite_walls[n].get_Position()
111  -(finite_walls[n].get_Normal().X*finite_walls[l].get_Normal().Y-finite_walls[l].get_Normal().X*finite_walls[n].get_Normal().Y)*finite_walls[m].get_Position()
112  +(finite_walls[n].get_Normal().X*finite_walls[m].get_Normal().Y-finite_walls[m].get_Normal().X*finite_walls[n].get_Normal().Y)*finite_walls[l].get_Position() ) * invdet;
113  }
114  }
115  }
116 
117  void create_open_prism_wall(std::vector<Vec3D> Points, Vec3D PrismAxis)
118  {
119  finite_walls.clear();
120  for(unsigned int i=0; i<Points.size()-1; i++)
121  add_finite_wall(Cross(Points[i]-Points[i+1],PrismAxis),Points[i]);
122  }
123 
124  void create_prism_wall(std::vector<Vec3D> Points, Vec3D PrismAxis)
125  {
126  create_open_prism_wall(Points, PrismAxis);
127  add_finite_wall(Cross(Points.back()-Points.front(),PrismAxis),Points.front());
128  }
129 
130  void create_open_prism_wall(std::vector<Vec3D> Points)
131  {
132  Vec3D PrismAxis = Cross(
133  GetUnitVector(Points[1]-Points[0]),
134  GetUnitVector(Points[2]-Points[1]));
135  finite_walls.clear();
136  for(unsigned int i=0; i<Points.size()-1; i++)
137  add_finite_wall(Cross(Points[i]-Points[i+1],PrismAxis),Points[i]);
138  }
139 
140  void create_prism_wall(std::vector<Vec3D> Points)
141  {
142  Vec3D PrismAxis = Cross(
143  GetUnitVector(Points[2]-Points[0]),
144  GetUnitVector(Points[1]-Points[0]));
145  create_open_prism_wall(Points, PrismAxis);
146  add_finite_wall(Cross(Points.back()-Points.front(),PrismAxis),Points.front());
147  }
148 
150  bool get_distance_and_normal(BaseParticle &P, Mdouble &distance, Vec3D &normal_return)
151  {
152  static Mdouble distance_new;
153  static Mdouble distance2;
154  static Mdouble distance3;
155  static int id;
156  static int id2;
157  static int id3;
158 
159  //if we are here, this is a finite wall
160  distance = -1e20;
161  distance2 = -1e20;
162  distance3 = -1e20;
163  //for all finite walls
164  for (unsigned int i=0; i<finite_walls.size(); i++)
165  {
166  //calculate the distance to the particle
167  distance_new = finite_walls[i].get_distance(P.get_Position());
168  //return false if the distance to any one wall is too large (i.e. no contact)
169  if (distance_new>=P.get_WallInteractionRadius()) return false;
170  //store the minimum distance and the respective wall in "distance" and "id"
171  //and store up to two walls (id2, id3) and their distances (distance2, distance3), if the possible contact point is near the intersection between id and id2 (and id3)
172  if (distance_new>distance)
173  {
174  if (distance>-P.get_WallInteractionRadius())
175  {
176  if (distance2>-P.get_WallInteractionRadius()) {distance3 = distance; id3 = id;}
177  else {distance2 = distance; id2 = id;}
178  }
179  distance = distance_new; id = i;
180  } else if (distance_new>-P.get_WallInteractionRadius())
181  {
182  if (distance2>-P.get_WallInteractionRadius()) {distance3 = distance_new; id3 = i;}
183  else {distance2 = distance_new; id2 = i;}
184  }
185  }
186 
187  //if we are here, the closest wall is id;
188  //if distance2>-P.Radius (and distance3>-P.Radius), the possible contact point is near the intersection between id and id2 (and id3)
189  if (distance2>-P.get_WallInteractionRadius())
190  {
191  //D is the point on wall id closest to P
192  Vec3D D = P.get_Position() + finite_walls[id].get_Normal() * distance;
193  //If the distance of D to id2 is positive, the contact is with the intersection
194  bool intersection_with_id2 = (finite_walls[id2].get_distance(D)>0.0);
195 
196  if (distance3>-P.get_WallInteractionRadius()&&(finite_walls[id3].get_distance(D)>0.0))
197  {
198  if (intersection_with_id2)
199  {
200  //possible contact is with intersection of id,id2,id3
201  //we know id2<id3
202  int index =
203  (id<id2)?( (id3-2)*(id3-1)*id3/6+(id2-1)*id2/2+id ):
204  (id<id3)?( (id3-2)*(id3-1)*id3/6+(id -1)*id /2+id2 ):
205  ( (id -2)*(id -1)*id /6+(id3-1)*id3/2+id2 );
206  normal_return = P.get_Position() - C[index];
207  distance = sqrt(normal_return.GetLength2());
208  if (distance>=P.get_WallInteractionRadius()) return false; //no contact
209  normal_return /= -distance;
210  return true; //contact with id,id2,id3
211  } else { intersection_with_id2 = true; distance2 = distance3; id2 = id3; }
212  }
213 
214  if (intersection_with_id2)
215  { //possible contact is with intersection of id,id2
216  int index = (id>id2)?((id-1)*id/2+id2):((id2-1)*id2/2+id);
217  Vec3D AC = P.get_Position() - A[index];
218  normal_return = AC - AB[index] * Dot(AC,AB[index]);
219  distance = sqrt(normal_return.GetLength2());
220  if (distance>=P.get_WallInteractionRadius()) return false; //no contact
221  normal_return /= -distance;
222  return true; //contact with two walls
223  }
224  }
225  //contact is with id
226  normal_return = finite_walls[id].get_Normal();
227  return true;
228 
229  }
230 
231 
233  void read(std::istream& is)
234  {
235  std::string dummy;
236  int n;
237  is >> dummy >> n;
238 
239  Vec3D normal;
240  Mdouble position;
241  for (int i=0; i<n; i++)
242  {
243  is >> dummy >> normal >> dummy >> position;
244  add_finite_wall(normal,position);
245  }
246  is >> dummy >> velocity;
247  }
248 
250  void print(std::ostream& os) const
251  {
252  os << "FiniteWall numFiniteWalls " << finite_walls.size();
253  for (std::vector<InfiniteWall>::const_iterator it = finite_walls.begin(); it!=finite_walls.end(); ++it)
254  {
255  os << " normal " << it->get_Normal() << " position " << it->get_Position();
256  }
257  if (velocity.GetLength2()) os << " velocity " << velocity;
258  }
259 
261  Vec3D get_Velocity() const {return velocity;}
262 
263  private:
264  std::vector<InfiniteWall> finite_walls;
265  std::vector<Vec3D> A; //<A[n*(n-1)/2+m] is a point on the intersecting line between walls m and n, m<n
266  std::vector<Vec3D> AB; //<AB[n*(n-1)/2+m] is the direction of the intersecting line between walls m and n, m<n
267  std::vector<Vec3D> C; //<C[(n-2)*(n-1)*n/6+(m-1)*m/2+l] is a point intersecting walls l, m and n, l<m<n
268 
269 };
270 
271 #endif
void read(std::istream &is)
reads wall
Definition: FiniteWall.h:233
std::vector< Vec3D > C
Definition: FiniteWall.h:267
Vec3D velocity
velocity of the wall (used to calculate the relative velocity in the force calculation) ...
Definition: BaseWall.h:114
virtual FiniteWall * copy() const
Wall copy method. It calls the copy contrustor of this Wall, usefull for polymorfism.
Definition: FiniteWall.h:44
void create_open_prism_wall(std::vector< Vec3D > Points, Vec3D PrismAxis)
Definition: FiniteWall.h:117
Matrix3D Cross(const Vec3D &A, const Matrix3D &B)
Definition: Matrix.h:198
void create_open_prism_wall(std::vector< Vec3D > Points)
Definition: FiniteWall.h:130
void create_prism_wall(std::vector< Vec3D > Points)
Definition: FiniteWall.h:140
friend Mdouble GetLength2(const Vec3D &A)
Definition: Vector.h:183
bool get_distance_and_normal(BaseParticle &P, Mdouble &distance, Vec3D &normal_return)
Since this function should be called before calculating any Particle-Wall interactions, it can also be used to set the normal vector in case of curved walls.
Definition: FiniteWall.h:150
double Mdouble
Definition: ExtendedMath.h:33
Mdouble get_WallInteractionRadius() const
std::vector< Vec3D > A
Definition: FiniteWall.h:265
const Vec3D & get_Position() const
void set_zero()
Definition: Vector.h:55
void add_finite_wall(Vec3D normal, Vec3D point)
Adds a wall to the set of finite walls, given an outward normal vector s.t. normal*x=normal*point.
Definition: FiniteWall.h:57
int indSpecies
Definition: BaseWall.h:36
std::vector< InfiniteWall > finite_walls
Definition: FiniteWall.h:264
std::vector< Vec3D > AB
Definition: FiniteWall.h:266
void clear()
Definition: FiniteWall.h:49
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:40
void print(std::ostream &os) const
outputs wall
Definition: FiniteWall.h:250
Vec3D get_Velocity() const
access function for velocity
Definition: FiniteWall.h:261
void add_finite_wall(Vec3D normal_, Mdouble position_)
Adds a wall to the set of finite walls, given an outward normal vector s. t. normal*x=position.
Definition: FiniteWall.h:61
void create_prism_wall(std::vector< Vec3D > Points, Vec3D PrismAxis)
Definition: FiniteWall.h:124