MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PeriodicBoundary.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2017, 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 provid->d 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 provid->d 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 "PeriodicBoundary.h"
27 #include "ParticleHandler.h"
28 #include "Particles/BaseParticle.h"
29 #include "DPMBase.h"
30 
31 //TODO below is for debugging purposes
32 #include <unistd.h>
33 
38  : BaseBoundary()
39 {
40  distanceLeft_ = std::numeric_limits<double>::quiet_NaN();
41  distanceRight_ = std::numeric_limits<double>::quiet_NaN();
42  scaleFactor_ = std::numeric_limits<double>::quiet_NaN();
43 
44 #ifdef MERCURY_USE_MPI
45  MPIContainer& communicator = MPIContainer::Instance();
46  if (communicator.getNumberOfProcessors() > 1)
47  {
48  logger(WARN,"PeriodicBoundaries are currently not implemented in parallel MercuryDPM");
49  }
50 #endif
51  logger(DEBUG, "PeriodicBoundary::PeriodicBoundary() finished");
52  logger(DEBUG, "PeriodicBoundary::PeriodicBoundary() finished");
53 }
54 
59 {
60  logger(DEBUG, "PeriodicBoundary::~PeriodicBoundary() finished");
61 }
62 
67 {
68  return new PeriodicBoundary(*this);
69 }
70 
79 void PeriodicBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
80 {
81  // factor is used to set normal to unit length
82  scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
83  normal_ = normal * scaleFactor_;
84  distanceLeft_ = distanceLeft * scaleFactor_;
85  distanceRight_ = distanceRight * scaleFactor_;
86  logger.assert_always(distanceRight_ > distanceLeft_,
87  "PeriodicBoundary::set: left distance needs to be smaller than right distance");
89 }
90 
91 void PeriodicBoundary::set(Vec3D normal, Vec3D positionLeft, Vec3D positionRight)
92 {
93  set(normal, Vec3D::dot(positionLeft,normal), Vec3D::dot(positionRight,normal));
94 }
95 
105 void PeriodicBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight, Vec3D shiftDirection)
106 {
107  // factor is used to set normal to unit length
108  scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
109  normal_ = normal * scaleFactor_;
110  distanceLeft_ = distanceLeft * scaleFactor_;
111  distanceRight_ = distanceRight * scaleFactor_;
112  // factor is used to set shift vector to correct length
113  scaleFactor_ = (distanceRight_ - distanceLeft_) * Vec3D::dot(shiftDirection, normal_);
114  shift_ = shiftDirection * scaleFactor_;
115 }
116 
121 {
122  return normal_;
123 }
124 
129 {
130  return distanceLeft_;
131 }
132 
137 {
138  return distanceRight_;
139 }
140 
145 {
146  return shift_;
147 }
148 
156 {
157  distanceLeft_ = distanceLeft * scaleFactor_;
159 }
160 
168 {
169  distanceRight_ = distanceRight * scaleFactor_;
171 }
172 
183 {
184  return getDistance(p.getPosition());
185 }
186 
193 {
194  Mdouble distanceFromPlaneThroughOrigin = Vec3D::dot(position, normal_);
195  return std::min(distanceFromPlaneThroughOrigin - distanceLeft_, distanceRight_ - distanceFromPlaneThroughOrigin);
196 }
197 
204 {
205  if (isClosestToLeftBoundary(*p))
206  {
207  p->move(shift_);
208  }
209  else
210  {
211  p->move(-shift_);
212  }
213 }
214 
215 /*
216  Vec3D PeriodicBoundary::getShiftedPosition(Vec3D &position)
217  {
218  if (left_wall)
219  {
220  return position + shift_;
221  }
222  else
223  {
224  return position - shift_;
225  }
226  }
227  */
228 
235 void PeriodicBoundary::shiftPositions(Vec3D& position1, Vec3D& position2) const
236 {
237  if (isClosestToLeftBoundary(position1))
238  {
239  position1 += shift_;
240  position2 += shift_;
241  }
242  else
243  {
244  position1 -= shift_;
245  position2 -= shift_;
246  }
247 }
248 
249 /*
250  * \details Returns TRUE if last particle checked is closest to the 'left'
251  * wall, and FALSE if it is closest to the 'right' wall.
252  * \return true if it is closest to the left boundary, false otherwise
253  */
255 {
257 }
258 
259 /*
260  * \details Returns TRUE if last position checked is closest to the 'left'
261  * wall, and FALSE if it is closest to the 'right' wall.
262  * \return true if it is closest to the left boundary, false otherwise
263  */
265 {
266  const Mdouble distance = Vec3D::dot(p, normal_);
267  return (distanceRight_ - distance > distance - distanceLeft_);
268 }
269 
270 /*
271  void PeriodicBoundary::getCloseTogether(Vec3D &P, Vec3D &Q)
272  {
273  Mdouble PQdotn = Vec3D::Dot(P - Q, normal_);
274  Mdouble shift_norm2 = shift.GetLength2();
275  //Check if P is so far from Q that a shift would move it closer
276  if (mathsFunc::square(PQdotn) > .25 * shift_norm2)
277  {
278  //Now determine the direction of the shift
279  if (PQdotn > 0.0)
280  P -= shift;
281  else
282  P += shift;
283  }
284  }
285  */
286 
291 void PeriodicBoundary::read(std::istream& is)
292 {
293  BaseBoundary::read(is);
294  std::string dummy;
295  is >> dummy >> normal_
296  >> dummy >> scaleFactor_
297  >> dummy >> distanceLeft_
298  >> dummy >> distanceRight_
299  >> dummy >> shift_;
300 }
301 
306 void PeriodicBoundary::oldRead(std::istream& is)
307 {
308  std::string dummy;
309  is >> dummy >> normal_
310  >> dummy >> scaleFactor_
311  >> dummy >> distanceLeft_
312  >> dummy >> distanceRight_
313  >> dummy >> shift_;
314 }
315 
320 void PeriodicBoundary::write(std::ostream& os) const
321 {
323  os << " normal " << normal_
324  << " scaleFactor " << scaleFactor_
325  << " distanceLeft " << distanceLeft_
326  << " distanceRight " << distanceRight_
327  << " shift " << shift_;
328 }
329 
334 std::string PeriodicBoundary::getName() const
335 {
336  return "PeriodicBoundary";
337 }
338 
339 /*
340  Vec3D& PeriodicBoundary::getNormal()
341  {
342  return normal_;
343  }
344  */
345 
359 {
360  //note that getDistance sets closestToLeftBoundary_ to true or false depending on which side is closest
362  {
363  //Step 1: Copy the particle to new ghost particle.
364  BaseParticle* pGhost = p->copy();
365 
366  //Step 2: Copy the interactions of the ghost particle.
368 
369  //Step 3: Shift the ghost to the 'reflected' location.
370  shiftPosition(pGhost);
371 
372  //Step 4: If Particle is double shifted, get correct original particle
373  BaseParticle* from = p;
374  while (from->getPeriodicFromParticle() != nullptr)
375  from = from->getPeriodicFromParticle();
376  pGhost->setPeriodicFromParticle(from);
377 
378  pH.addObject(pGhost);
379  }
380 }
381 
392 {
393  if (getDistance(*p) < 0)
394  {
395  shiftPosition(p);
396  }
397  return false;
398 }
Mdouble getDistanceLeft() const
Returns the distance of the left wall to the origin, in normal direction.
BaseParticle * getLargestParticle() const
Gets a pointer to the largest BaseParticle (by interactionRadius) in this ParticleHandler.
void set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
Defines a periodic wall.
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
virtual std::string getName() const override
Returns the name of the object.
MERCURY_DEPRECATED void oldRead(std::istream &is)
deprecated version of CubeInsertionBoundary::read().
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
double Mdouble
Mdouble scaleFactor_
This is the normal to rescale the normal vector to a unit vectors.
void createPeriodicParticles(BaseParticle *p, ParticleHandler &pH)
Checks distance of particle to closest wall and creates periodic copy if necessary.
void setPeriodicFromParticle(BaseParticle *p)
Assigns the pointer to the 'original' particle this one's a periodic copy of.
void moveRight(Mdouble distanceRight)
Sets the distance from the origin of the 'right' periodic wall.
Mdouble getDistanceRight() const
Returns the distance of the right wall to the origin, in normal direction.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:167
Mdouble distanceRight_
position of right wall, s.t. normal*x=position_right
Vec3D getNormal() const
returns the vector normal to the periodic boundary
PeriodicBoundary * copy() const override
copy method
PeriodicBoundary()
default constructor
Vec3D getShift() const
Returns the vector going from the left to the right side of the periodic boundary.
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Vec3D normal_
outward unit normal vector for right wall
~PeriodicBoundary()
destructor
Defines a pair of periodic walls. Inherits from BaseBoundary.
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
bool checkBoundaryAfterParticleMoved(BaseParticle *p, ParticleHandler &pH UNUSED)
Checks if particle has crossed either boundary wall, and applies a shift if that is the case...
Mdouble getDistance(const BaseParticle &p) const
Returns the distance of the wall to the particle.
void moveLeft(Mdouble distanceLeft)
Sets the distance from the origin of the 'left' periodic wall.
bool isClosestToLeftBoundary(const BaseParticle &p) const
Returns TRUE if last particle/position checked is closest to the 'left' wall, and FALSE if it is clos...
virtual void addObject(BaseParticle *P)
Adds a BaseParticle to the ParticleHandler.
void shiftPosition(BaseParticle *p) const
shifts the particle
#define UNUSED
Definition: GeneralDefine.h:39
Mdouble distanceLeft_
position of left wall, s.t. normal*x=position_left
void copyInteractionsForPeriodicParticles(const BaseInteractable &p)
Copies interactions to this BaseInteractable whenever a periodic copy made.
Container to store all BaseParticle.
Vec3D shift_
shift from left to right boundary
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 write(std::ostream &os) const override
writes boundary properties to ostream
Mdouble getInteractionRadius() const
Returns the particle's interaction radius, which might be different from radius_ (e.g., when dealing with wet particles)
void read(std::istream &is) override
reads boundary properties from istream
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 shiftPositions(Vec3D &postition1, Vec3D &postion2) const
shifts two positions