MercuryDPM  Beta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Coil.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 "Coil.h"
27 #include "InteractionHandler.h"
28 #include "Particles/BaseParticle.h"
29 
36 {
37  start_.setZero();
38  l_ = 1.0;
39  r_ = 1.0;
40  n_ = 1.0;
41  omega_ = 1.0;
42  offset_ = 0.0;
43  thickness_ = 0.0;
44  logger(DEBUG, "Coil() constructor finished");
45 }
46 
50 Coil::Coil(const Coil& other) : BaseWall(other)
51 {
52  start_ = other.start_;
53  l_ = other.l_;
54  r_ = other.r_;
55  n_ = other.n_;
56  omega_ = other.omega_;
57  offset_ = other.offset_;
58  thickness_ = other.thickness_;
59  logger(DEBUG, "Coil(const Coil&) copy constructor finished");
60 }
61 
72 Coil::Coil(Vec3D start, Mdouble l, Mdouble r, Mdouble n, Mdouble omega, Mdouble thickness)
73 {
74  start_ = start;
75  l_ = l;
76  r_ = r;
77  n_ = n;
78  omega_ = omega;
79  thickness_ = thickness;
80  offset_ = 0.0;
81  logger(DEBUG, "Coil(params) constructor with parameters finished.");
82 }
83 
85 {
86  logger(DEBUG, "~Coil() destructor finished.");
87 }
88 
101 void Coil::set(Vec3D start, Mdouble length, Mdouble radius, Mdouble numberOfRevelations, Mdouble omega, Mdouble thickness)
102 {
103  start_ = start;
104  l_ = length;
105  r_ = radius;
106  n_ = numberOfRevelations;
107  omega_ = omega;
108  thickness_ = thickness;
109  offset_ = 0.0;
110 }
111 
115 Coil* Coil::copy() const
116 {
117  return new Coil(*this);
118 }
119 
131 bool Coil::getDistanceAndNormal(const BaseParticle& p, Mdouble& distance, Vec3D& normal_return) const
132 {
133  Mdouble Rsqr = pow(p.getPosition().X - start_.X, 2) + pow(p.getPosition().Y - start_.Y, 2);
135  {
136  //std::cout<<"Particle is out of first bound checking"<<std::endl;
137  //std::cout<<"Rule 1: "<<pow(r-P.getRadius()-thickness_,2)<<"<"<<Rsqr<<"<"<<pow(r+P.getRadius()+thickness_,2)<<std::endl;
138  //std::cout<<"Rule 2: "<<Start.Z-P.getRadius()-thickness_<<"<"<<P.getPosition().Z<<"<"<<L+Start.Z+P.getRadius()+thickness_<<std::endl;
139  return false;
140  }
141  Mdouble R = sqrt(Rsqr);
142  Mdouble alpha = atan2(p.getPosition().Y - start_.Y, p.getPosition().X - start_.X);
143  Mdouble dz = p.getPosition().Z - start_.Z;
144 
145  //To find the contact point we have to minimize (with respect to q)
146  //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
147  //Using polar coordinated (i.e. x-x0=R*cos(alpha), y-y0=R*sin(alpha) and dz=z-z0)
148  //Distance^2=R^2+r^2-2*R*r*cos(alpha-2*Pi*(offset+N*q))+(dz-q*L)^2
149 
150  //So we have to minimize:
151  //Distance^2=R^2+r^2-2*R*r*cos(alpha-2*Pi*(offset+N*q))+(dz-q*L)^2
152  //For this we use the Euler algoritm
153 
154  Mdouble q; //Current guess
155  Mdouble dd; //Derivative at current guess
156  Mdouble ddd; //Second derivative at current guess
157  Mdouble q0 = dz / l_; //Minimum of the parabolic part
158 
159  //The initial guess will be in the maximum of the cos closest to the minimum of the parabolic part
160  //Minima of the cos are at
161  //alpha-2*Pi*(offset+N*q)=2*k*Pi (k=integer)
162  //q=alpha/(2*Pi*N)-k/N-offset/N (k=integer)
163 
164  Mdouble k = round(alpha / 2.0 / constants::pi - (offset_ + n_ * q0));
165  q = alpha / (2 * constants::pi * n_) - k / n_ - offset_ / n_;
166 
167  //Now apply Newton's method
168  do
169  {
170  dd = -4.0 * R * r_ * constants::pi * n_ * sin(alpha - 2.0 * constants::pi * (n_ * q + offset_)) - 2.0 * l_ * (dz - q * l_);
171  ddd = 8.0 * R * r_ * constants::sqr_pi * n_ * n_ * cos(alpha - 2.0 * constants::pi * (n_ * q + offset_)) + 2.0 * l_ * l_;
172  q -= dd / ddd;
173  } while (fabs(dd / ddd) > 1e-14);
174 
175  //Check if the location is actually on the coil, otherwise a point collision with the end of the coil calculated
176  if (q < 0) //Left boundary of the coil
177  {
178  q = 0;
179  }
180  else if (q > 1) //right boundary of the coil
181  {
182  q = 1;
183  }
184 
185  Mdouble distanceSquared = R * R + r_ * r_ - 2 * R * r_ * cos(alpha - 2 * constants::pi * (offset_ + n_ * q)) + pow(dz - q * l_, 2);
186  //If distance is too large there is no contact
187  if (distanceSquared >= (p.getWallInteractionRadius() + thickness_) * (p.getWallInteractionRadius() + thickness_))
188  {
189  //std::cout<<"Particle is out of second bound checking, distance^2="<<distance<<" max="<<(P.getRadius()+thickness_)*(P.getRadius()+thickness_)<<std::endl;
190  return false;
191  }
192 
193  Vec3D ContactPoint;
194  distance = sqrt(distanceSquared) - thickness_;
195  ContactPoint.X = start_.X + r_ * cos(2.0 * constants::pi * (offset_ + n_ * q));
196  ContactPoint.Y = start_.Y + r_ * sin(2.0 * constants::pi * (offset_ + n_ * q));
197  ContactPoint.Z = start_.Z + q * l_;
198  normal_return = ContactPoint - p.getPosition();
199  normal_return /= normal_return.getLength();
200  return true;
201 }
202 
211 {
212  Mdouble distance;
213  Vec3D normal;
214  if (getDistanceAndNormal(*p,distance,normal))
215  {
216  BaseInteraction* c = interactionHandler->getInteraction(p, this, timeStamp);
217  c->setNormal(-normal);
218  c->setDistance(distance);
219  c->setOverlap(p->getRadius() - distance);
221  c->setContactPoint(p->getPosition() - (p->getRadius()- 0.5 * c->getOverlap()) * c->getNormal());
222  return c;
223  }
224  else
225  {
226  return nullptr;
227  }
228 }
229 
234 {
235  offset_ += omega_ * dt;
236 }
237 
241 void Coil::read(std::istream& is)
242 {
243  BaseWall::read(is);
244  std::string dummy;
245  is >> dummy >> start_
246  >> dummy >> l_
247  >> dummy >> r_
248  >> dummy >> n_
249  >> dummy >> omega_
250  >> dummy >> thickness_
251  >> dummy >> offset_;
252 }
253 
257 void Coil::oldRead(std::istream& is)
258 {
259  std::string dummy;
260  is >> dummy >> start_
261  >> dummy >> l_
262  >> dummy >> r_ >> dummy >> n_
263  >> dummy >> omega_
264  >> dummy >> offset_;
265 }
266 
270 void Coil::write(std::ostream& os) const
271  {
272  BaseWall::write(os);
273  os << " Start " << start_
274  << " Length " << l_
275  << " Radius " << r_
276  << " Revolutions " << n_
277  << " Omega " << omega_
278  << " Thickness " << thickness_
279  << " Offset " << offset_;
280 }
281 
285 std::string Coil::getName() const
286 {
287  return "Coil";
288 }
Vec3D start_
The centre of the lower end of the Coil.
Definition: Coil.h:115
void setNormal(Vec3D normal)
Sets the normal vector between the two interacting objects.
Mdouble X
the vector components
Definition: Vector.h:52
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
void setOverlap(Mdouble overlap)
Set the overlap between the two interacting object.
BaseInteraction * getInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp)
Returns the Interaction between the BaseInteractable's P and I.
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.
void set(Vec3D Start, Mdouble length, Mdouble radius, Mdouble numberOfRevelations, Mdouble omega, Mdouble thickness)
Set all parameters of this Coil.
Definition: Coil.cc:101
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 ...
~Coil()
Default destructor.
Definition: Coil.cc:84
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...
Mdouble offset_
Definition: Coil.h:140
void read(std::istream &is) override
Reads a Coil from an input stream, for example a restart file.
Definition: Coil.cc:241
const Mdouble pi
Definition: ExtendedMath.h:42
void write(std::ostream &os) const override
Writes a Coil to an output stream, for example a restart file.
Definition: Coil.cc:270
bool getDistanceAndNormal(const BaseParticle &P, Mdouble &distance, Vec3D &normal_return) const override
Compute the distance from the Coil for a given BaseParticle and return if there is a collision...
Definition: Coil.cc:131
Container to store Interaction objects.
const Vec3D & getNormal() const
Gets the normal vector between the two interacting objects.
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.
Mdouble Y
Definition: Vector.h:52
Mdouble l_
The length of the Coil.
Definition: Coil.h:120
Mdouble n_
Definition: Coil.h:130
void move_time(Mdouble dt)
Rotate the Coil for a period dt, so that the offset_ changes with omega_*dt.
Definition: Coil.cc:233
Mdouble r_
Definition: Coil.h:125
BaseInteraction * getInteractionWith(BaseParticle *P, Mdouble timeStamp, InteractionHandler *interactionHandler)
Get the interaction between this Coil and given BaseParticle at a given time.
Definition: Coil.cc:210
Coil * copy() const override
Copy this Coil and return a pointer to the copy, useful for polymorphism.
Definition: Coil.cc:115
Coil()
Default constructor, sets a coil with default parameters.
Definition: Coil.cc:35
Mdouble thickness_
Definition: Coil.h:145
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
MERCURY_DEPRECATED void oldRead(std::istream &is)
Reads an old-style Coil from an input stream, for example an old restart file.
Definition: Coil.cc:257
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
This class defines a coil in the z-direction from a (constant) starting point, a (constant) length L...
Definition: Coil.h:40
const Mdouble sqr_pi
Definition: ExtendedMath.h:44
Mdouble omega_
Definition: Coil.h:135
void read(std::istream &is)
Function that reads a BaseWall from an input stream, usually a restart file.
Definition: BaseWall.cc:60
std::string getName() const override
Returns the name of the object, in this case the string "Coil".
Definition: Coil.cc:285