MercuryDPM  Beta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Screw.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 
26 #include "Screw.h"
27 #include "InteractionHandler.h"
28 #include "Math/ExtendedMath.h"
29 #include "Particles/BaseParticle.h"
30 
37 {
38  start_.setZero();
39  l_ = 1.0;
40  maxR_ = 1.0;
41  n_ = 1.0;
42  omega_ = 1.0;
43  offset_ = 0.0;
44  thickness_ = 0.0;
45  logger(DEBUG, "Screw() constructor finished.");
46 }
47 
51 Screw::Screw(const Screw& other)
52  : BaseWall(other)
53 {
54  start_ = other.start_;
55  l_ = other.l_;
56  maxR_ = other.maxR_;
57  n_ = other.n_;
58  omega_ = other.omega_;
59  thickness_ = other.thickness_;
60  offset_ = other.offset_;
61  logger(DEBUG, "Screw(const Screw&) copy constructor finished.");
62 }
63 
74 Screw::Screw(Vec3D start, Mdouble l, Mdouble r, Mdouble n, Mdouble omega, Mdouble thickness)
75 {
76  start_ = start;
77  l_ = l;
78  maxR_ = r;
79  n_ = n;
80  omega_ = omega;
81  thickness_ = thickness;
82  offset_ = 0.0;
83  logger(DEBUG, "Screw(Vec3D, Mdouble, Mdouble, Mdouble, Mdouble, Mdouble) constructor finished.");
84 }
85 
87 {
88  logger(DEBUG, "~Screw() finished, destroyed the Screw.");
89 }
90 
95 {
96  return new Screw(*this);
97 }
98 
110 bool Screw::getDistanceAndNormal(const BaseParticle& p, Mdouble& distance, Vec3D& normal_return) const
111 {
112  Mdouble Rsqr = pow(p.getPosition().X - start_.X, 2) + pow(p.getPosition().Y - start_.Y, 2);
114  {
115  //std::cout<<"Particle is out of first bound checking"<<std::endl;
116  //std::cout<<"Rule 1: "<<Rsqr<<"<"<<pow(r+P.getRadius()+thickness_,2)<<std::endl;
117  //std::cout<<"Rule 2: "<<Start.Z-P.getRadius()-thickness_<<"<"<<P.getPosition().Z<<"<"<<L+Start.Z+P.getRadius()+thickness_<<std::endl;
118  return false;
119  }
120  Mdouble R = sqrt(Rsqr);
121  Mdouble alpha = atan2(p.getPosition().Y - start_.Y, p.getPosition().X - start_.X);
122  Mdouble dz = p.getPosition().Z - start_.Z;
123 
124  //To find the contact point we have to minimize (with respect to r and q)
125  //Distance^2=(x-x0-r*cos(2*Pi*(offset+N*q)))^2+(y-y0-r*sin(2*Pi*(offset+N*q)))^2+(z-z0-q*L)^2
126  //Using polar coordinated (i.e. x-x0=R*cos(alpha), y-y0=R*sin(alpha) and dz=z-z0)
127  //Distance^2=R^2+r^2-2*R*r*cos(alpha-2*Pi*(offset+N*q))+(dz-q*L)^2
128 
129  //Differentiation with respect to r and solve for zero:
130  //0=2*r-2*R*cos(alpha-2*Pi*(offset+N*q)
131  //r=R*cos(alpha-2*Pi*(offset+N*q))
132 
133  //Substitue back
134  //Distance^2=R^2+R^2*cos^2(alpha-2*Pi*(offset+N*q))-2*R^2*cos(alpha-2*Pi*(offset+N*q))*cos(alpha-2*Pi*(offset+N*q))+(dz-q*L)^2
135  //Distance^2=R^2*sin^2(alpha-2*Pi*(offset+N*q))+(dz-q*L)^2
136 
137  //So we have to minimize:
138  //Distance^2=R^2*sin^2(alpha-2*Pi*(offset+N*q))^2+(dz-q*L)^2
139  //For this we use the Euler algoritm
140 
141  Mdouble q; //Current guess
142  Mdouble dd; //Derivative at current guess
143  Mdouble ddd; //Second derivative at current guess
144  Mdouble q0 = dz / l_; //Minimum of the parabolic part
145 
146  //The initial guess will be in the minimum of the sin closest to the minimum of the parabolic part
147  //Minima of the sin are at
148  //alpha-2*Pi*(offset+N*q)=k*Pi (k=integer)
149  //q=alpha/(2*Pi*N)-k/(2*N)-offset/N (k=integer)
150 
151  Mdouble k = round(alpha / constants::pi - 2.0 * (offset_ + n_ * q0));
152  q = alpha / (2.0 * constants::pi * n_) - k / (2.0 * n_) - offset_ / n_;
153 
154  //Now apply Newton's method
155  do
156  {
157  dd = -2.0 * Rsqr * constants::pi * n_ * sin(2.0 * alpha - 4.0 * constants::pi * (n_ * q + offset_)) - 2.0 * l_ * (dz - q * l_);
158  ddd = 8.0 * Rsqr * constants::sqr_pi * n_ * n_ * cos(2.0 * alpha - 4.0 * constants::pi * (n_ * q + offset_)) + 2.0 * l_ * l_;
159  q -= dd / ddd;
160  } while (fabs(dd / ddd) > 1e-14);
161 
162  //Calculate r
163  Mdouble r = R * cos(2.0 * constants::pi * (offset_ + n_ * q) - alpha);
164 
165  //Check if the location is actually on the screw:
166  //First posibility is that the radius is to large:
167  if (fabs(r) > maxR_) //Left boundary of the coil
168  {
169  r = mathsFunc::sign(r) * maxR_;
170  unsigned int steps = 0;
171  //This case reduces to the coil problem
172  do
173  {
174  dd = -4.0 * R * r * constants::pi * n_ * sin(alpha - 2.0 * constants::pi * (n_ * q + offset_)) - 2.0 * l_ * (dz - q * l_);
175  ddd = 8.0 * R * r * constants::sqr_pi * n_ * n_ * cos(alpha - 2.0 * constants::pi * (n_ * q + offset_)) + 2.0 * l_ * l_;
176  q -= dd / ddd;
177  steps++;
178  } while (fabs(dd / ddd) > 1e-14);
179  }
180  //Second possibility is that it occured before the start of after the end
181  if (q < 0)
182  {
183  q = 0;
184  r = R * cos(alpha - 2.0 * constants::pi * (offset_ + q * n_));
185  if (fabs(r) > maxR_)
186  {
187  r = mathsFunc::sign(r) * maxR_;
188  }
189  }
190  else if (q > 1)
191  {
192  q = 1;
193  r = R * cos(alpha - 2.0 * constants::pi * (offset_ + q * n_));
194  if (fabs(r) > maxR_)
195  {
196  r = mathsFunc::sign(r) * maxR_;
197  }
198  }
199 
200  distance = R * R * pow(sin(alpha - 2 * constants::pi * (offset_ + n_ * q)), 2) + pow(dz - q * l_, 2);
201  //If distance is to large there is no contact
203  {
204  return false;
205  }
206 
207  Vec3D ContactPoint;
208  distance = sqrt(distance) - thickness_;
209  ContactPoint.X = start_.X + r * cos(2.0 * constants::pi * (offset_ + n_ * q));
210  ContactPoint.Y = start_.Y + r * sin(2.0 * constants::pi * (offset_ + n_ * q));
211  ContactPoint.Z = start_.Z + q * l_;
212  normal_return = ContactPoint - p.getPosition();
213  normal_return /= normal_return.getLength();
214  return true;
215 }
216 
221 {
222  offset_ += omega_ * dt;
223 }
224 
228 void Screw::read(std::istream& is)
229 {
230  BaseWall::read(is);
231  std::string dummy;
232  is >> dummy >> start_
233  >> dummy >> l_
234  >> dummy >> maxR_
235  >> dummy >> n_
236  >> dummy >> omega_
237  >> dummy >> thickness_
238  >> dummy >> offset_;
239 }
240 
247 void Screw::oldRead(std::istream& is)
248 {
249  std::string dummy;
250  is >> dummy >> start_
251  >> dummy >> l_
252  >> dummy >> maxR_
253  >> dummy >> n_
254  >> dummy >> omega_
255  >> dummy >> offset_;
256 }
257 
261 void Screw::write(std::ostream& os) const
262 {
263  BaseWall::write(os);
264  os << " start " << start_
265  << " Length " << l_
266  << " Radius " << maxR_
267  << " Revolutions " << n_
268  << " Omega " << omega_
269  << " Thickness " << thickness_
270  << " Offset " << offset_;
271 }
272 
276 std::string Screw::getName() const
277 {
278  return "Screw";
279 }
280 
289 {
290  Mdouble distance;
291  Vec3D normal;
292 
293  if (getDistanceAndNormal(*p,distance,normal))
294  {
295  BaseInteraction* c = interactionHandler->getInteraction(p, this, timeStamp);
296  c->setNormal(-normal);
297  c->setDistance(distance);
298  c->setOverlap(p->getRadius() - distance);
300  c->setContactPoint(p->getPosition()-(p->getRadius() - 0.5 * c->getOverlap()) * c->getNormal());
301  return c;
302  }
303  else
304  {
305  return nullptr;
306  }
307 }
void setNormal(Vec3D normal)
Sets the normal vector between the two interacting objects.
Mdouble X
the vector components
Definition: Vector.h:52
void read(std::istream &is) override
Reads a Screw from an input stream, for example a restart file.
Definition: Screw.cc:228
Mdouble maxR_
The outer radius of the Screw.
Definition: Screw.h:114
This function defines an Archimedes' screw in the z-direction from a (constant) starting point...
Definition: Screw.h:38
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
void setOverlap(Mdouble overlap)
Set the overlap between the two interacting object.
bool getDistanceAndNormal(const BaseParticle &P, Mdouble &distance, Vec3D &normal_return) const final
Compute the distance from the Screw for a given BaseParticle and return if there is a collision...
Definition: Screw.cc:110
BaseInteraction * getInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp)
Returns the Interaction between the BaseInteractable's P and I.
~Screw()
Default destructor.
Definition: Screw.cc:86
double Mdouble
void setZero()
Sets all elements to zero.
Definition: Vector.cc:52
void setContactPoint(Vec3D contactPoint)
Set the location of the contact point between the two interacting objects.
int sign(T val)
This is a sign function, it returns -1 for negative numbers, 1 for positive numbers and 0 for 0...
Definition: ExtendedMath.h:83
void move_time(Mdouble dt)
Rotate the Screw for a period dt, so that the offset_ changes with omega_*dt.
Definition: Screw.cc:220
void setDistance(Mdouble distance)
Sets the interaction distance between the two interacting objects.
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
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:427
Mdouble getWallInteractionRadius() const
Returns the interaction radius for interaction with walls. See also BaseParticle::getInteractionRadiu...
std::string getName() const final
Returns the name of the object, here the string "Screw".
Definition: Screw.cc:276
Vec3D start_
The centre of the lower end of the screw.
Definition: Screw.h:106
Mdouble offset_
The angle that describes how much the Screw has turned, going from 0 to 1 for a rotation.
Definition: Screw.h:126
const Mdouble pi
Definition: ExtendedMath.h:42
Container to store Interaction objects.
const Vec3D & getNormal() const
Gets the normal vector between the two interacting objects.
Mdouble l_
The length of the Screw.
Definition: Screw.h:110
Screw * copy() const final
Copy this screw and return a pointer to the copy.
Definition: Screw.cc:94
Mdouble getRadius() const
Returns the particle's radius_.
Basic class for walls.
Definition: BaseWall.h:39
Mdouble getOverlap() const
Returns a Mdouble with the current overlap between the two interacting objects.
void write(std::ostream &os) const override
Writes this Screw to an output stream, for example a restart file.
Definition: Screw.cc:261
Mdouble Y
Definition: Vector.h:52
BaseInteraction * getInteractionWith(BaseParticle *p, Mdouble timeStamp, InteractionHandler *interactionHandler) final
Get the interaction between this Screw and given BaseParticle at a given time.
Definition: Screw.cc:288
Mdouble n_
The number of revelations.
Definition: Screw.h:118
Screw()
Default constructor: make a screw with default parameters.
Definition: Screw.cc:36
Mdouble thickness_
The thickness of the Screw.
Definition: Screw.h:130
Mdouble omega_
Rotation speed in rev/s.
Definition: Screw.h:122
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
void write(std::ostream &os) const
Function that writes a BaseWall to an output stream, usually a restart file.
Definition: BaseWall.cc:68
Mdouble Z
Definition: Vector.h:52
const Mdouble sqr_pi
Definition: ExtendedMath.h:44
void oldRead(std::istream &is)
Reads a Screw in the old style from an input stream, for example a restart file old style...
Definition: Screw.cc:247
void read(std::istream &is)
Function that reads a BaseWall from an input stream, usually a restart file.
Definition: BaseWall.cc:60