MercuryDPM  Trunk
 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-2020, 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 "MpiDataClass.h"
30 #include "MpiContainer.h"
31 #include "DPMBase.h"
32 #include "MercuryBase.h"
33 
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  logger(DEBUG, "PeriodicBoundary::PeriodicBoundary() finished");
45 }
46 
51 {
52  logger(DEBUG, "PeriodicBoundary::~PeriodicBoundary() finished");
53 }
54 
59 {
60  return new PeriodicBoundary(*this);
61 }
62 
67  : BasePeriodicBoundary(other)
68 {
69  normal_ = other.normal_;
70  scaleFactor_ = other.scaleFactor_;
73  shift_ = other.shift_;
74 }
75 
84 void PeriodicBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
85 {
86  // factor is used to set normal to unit length
87  scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
88  normal_ = normal * scaleFactor_;
89  distanceLeft_ = distanceLeft * scaleFactor_;
90  distanceRight_ = distanceRight * scaleFactor_;
91  logger.assert_always(distanceRight_ > distanceLeft_,
92  "PeriodicBoundary::set: left distance needs to be smaller than right distance");
94 }
95 
96 void PeriodicBoundary::set(Vec3D normal, Vec3D positionLeft, Vec3D positionRight)
97 {
98  set(normal, Vec3D::dot(positionLeft, normal), Vec3D::dot(positionRight, normal));
99 }
100 
110 void PeriodicBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight, Vec3D shiftDirection)
111 {
112  // factor is used to set normal to unit length
113  scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
114  normal_ = normal * scaleFactor_;
115  distanceLeft_ = distanceLeft * scaleFactor_;
116  distanceRight_ = distanceRight * scaleFactor_;
117  // factor is used to set shift vector to correct length
118  scaleFactor_ = (distanceRight_ - distanceLeft_) * Vec3D::dot(shiftDirection, normal_);
119  shift_ = shiftDirection * scaleFactor_;
120 }
121 
127 {
128  planewiseShift -= Vec3D::dot(planewiseShift, normal_) / Vec3D::dot(normal_, normal_) * normal_;
129  shift_ = normal_ * (distanceRight_ - distanceLeft_) + planewiseShift;
130 }
131 
136 {
137  return normal_;
138 }
139 
144 {
145  return distanceLeft_;
146 }
147 
152 {
153  return distanceRight_;
154 }
155 
160 {
161  return shift_;
162 }
163 
171 {
172  distanceLeft_ = distanceLeft * scaleFactor_;
174 }
175 
183 {
184  distanceRight_ = distanceRight * scaleFactor_;
186 }
187 
198 {
199  return getDistance(p.getPosition());
200 }
201 
208 {
209  Mdouble distanceFromPlaneThroughOrigin = Vec3D::dot(position, normal_);
210  return std::min(distanceFromPlaneThroughOrigin - distanceLeft_,
211  distanceRight_ - distanceFromPlaneThroughOrigin);
212 }
213 
220 {
221  if (isClosestToLeftBoundary(*p))
222  {
223  p->move(shift_);
224  }
225  else
226  {
227  p->move(-shift_);
228  }
229 }
230 
237 {
239  {
240  p += shift_;
241  }
242  else
243  {
244  p -= shift_;
245  }
246 }
247 
248 
255 void PeriodicBoundary::shiftPositions(Vec3D& position1, Vec3D& position2) const
256 {
257  if (isClosestToLeftBoundary(position1))
258  {
259  position1 += shift_;
260  position2 += shift_;
261  }
262  else
263  {
264  position1 -= shift_;
265  position2 -= shift_;
266  }
267 }
268 
269 /*
270  * \details Returns TRUE if particle checked is closest to the 'left'
271  * wall, and FALSE if it is closest to the 'right' wall.
272  * \param[in] p A point to a BaseParticle that is being checked.
273  * \return true if it is closest to the left boundary, false otherwise
274  */
276 {
278 }
279 
280 /*
281  * \details Returns TRUE if position checked is closest to the 'left'
282  * wall, and FALSE if it is closest to the 'right' wall.
283  * \param[in] p A position vector p that is checked.
284  * \return true if it is closest to the left boundary, false otherwise
285  */
287 {
288  const Mdouble distance = Vec3D::dot(p, normal_);
289  return (distanceRight_ - distance > distance - distanceLeft_);
290 }
291 
296 void PeriodicBoundary::read(std::istream& is)
297 {
299  std::string dummy;
300  is >> dummy >> normal_
301  >> dummy >> scaleFactor_
302  >> dummy >> distanceLeft_
303  >> dummy >> distanceRight_
304  >> dummy >> shift_;
305 }
306 
311 void PeriodicBoundary::oldRead(std::istream& is)
312 {
313  std::string dummy;
314  is >> dummy >> normal_
315  >> dummy >> scaleFactor_
316  >> dummy >> distanceLeft_
317  >> dummy >> distanceRight_
318  >> dummy >> shift_;
319 }
320 
325 void PeriodicBoundary::write(std::ostream& os) const
326 {
328  os << " normal " << normal_
329  << " scaleFactor " << scaleFactor_
330  << " distanceLeft " << distanceLeft_
331  << " distanceRight " << distanceRight_
332  << " shift " << shift_;
333 }
334 
339 std::string PeriodicBoundary::getName() const
340 {
341  return "PeriodicBoundary";
342 }
343 
357 {
358  //note that getDistance sets closestToLeftBoundary_ to true or false depending on which side is closest
360  if (getDistance(*p) < maxDistance)
361  {
363  }
364 }
365 
367 {
369 
370  //Step 1: Copy the particle to new ghost particle.
371  BaseParticle* pGhost = pReal->copy();
372 
373  //Step 2: Copy the interactions of the ghost particle.
374  pGhost->copyInteractionsForPeriodicParticles(*pReal);
375 
376  //Step 3: Shift the ghost to the 'reflected' location.
377  shiftPosition(pGhost);
378 
379  //Step 4: If Particle is double shifted, get correct original particle
380  BaseParticle* from = pReal;
381  while (from->getPeriodicFromParticle() != nullptr)
382  from = from->getPeriodicFromParticle();
383  pGhost->setPeriodicFromParticle(from);
384  pGhost->setPeriodicGhostParticle(true);
385 
386  pH.addObject(pGhost);
387 }
388 
402 {
403 #ifdef MERCURY_USE_MPI
404  if (NUMBER_OF_PROCESSORS == 1)
405  {
406 #endif
407  unsigned numberOfParticles = pH.getSize();
408 
409  for (unsigned i = 0; i < numberOfParticles; i++)
410  {
412  }
413 #ifdef MERCURY_USE_MPI
414  }
415 #endif
416 }
417 
427 {
428 #ifdef MERCURY_USE_MPI
429  if (NUMBER_OF_PROCESSORS == 1)
430  {
431 #endif
432  for (auto p = pH.begin(); p != pH.end(); ++p)
433  {
434  if (getDistance((*p)->getPosition()) < 0)
435  {
436  shiftPosition(*p);
438  }
439  }
440 #ifdef MERCURY_USE_MPI
441  }
442 #endif
443 }
444 
445 
446 
447 
448 
449 
450 
451 
452 
453 
454 
455 
456 
457 
458 
459 
Mdouble getDistanceLeft() const
Returns the distance of the left wall to the origin, in normal direction.
void shiftPosition(BaseParticle *p) const override
shifts the particle
BaseParticle * getLargestParticle() const
Returns the pointer of the largest particle in the particle handler. When mercury is running in paral...
void set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
Defines a PeriodicBoundary by its normal and positions.
void write(std::ostream &os) const override
Adds object's id_ to given ostream.
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
void addObject(BaseParticle *P) override
Adds a BaseParticle to the ParticleHandler.
unsigned int getSize() const
Gets the size of the particleHandler (including mpi and periodic particles)
Definition: BaseHandler.h:655
void createPeriodicParticle(BaseParticle *p, ParticleHandler &pH) override
Creates a single periodic particle if required from a given particle.
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
double Mdouble
Definition: GeneralDefine.h:34
Mdouble getMaxInteractionRadius() const
Returns the particle's interaction radius, which might be different from radius_ (e.g., when dealing with wet particles)
Definition: BaseParticle.h:359
std::string getName() const override
Returns the name of the object.
MERCURY_DEPRECATED void oldRead(std::istream &is)
deprecated version of CubeInsertionBoundary::read().
const std::complex< Mdouble > i
Definition: ExtendedMath.h:50
const std::vector< T * >::const_iterator end() const
Gets the end of the const_iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:704
Mdouble scaleFactor_
This is the normal to rescale the normal vector to a unit vectors.
void setPeriodicFromParticle(BaseParticle *p)
Assigns the pointer to the 'original' particle this one's a periodic copy of (used in periodic bounda...
Definition: BaseParticle.h:438
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.
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
Definition: BaseParticle.h:338
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:76
virtual BaseParticle * copy() const =0
Particle copy method. It calls to copy constructor of this Particle, useful for polymorfism.
Mdouble distanceRight_
position of right edge, s.t. normal*x = distanceRight_
Vec3D getNormal() const
returns the vector normal to the periodic boundary
PeriodicBoundary * copy() const override
copy method
PeriodicBoundary()
default constructor
Mdouble getDistance(const BaseParticle &p) const override
Returns the distance of the edge to the particle.
Vec3D getShift() const
Returns the vector going from the left to the right side of the periodic boundary.
Vec3D normal_
outward unit normal vector for right wall
const std::vector< T * >::const_iterator begin() const
Gets the begin of the const_iterator over all Object in this BaseHandler.
Definition: BaseHandler.h:690
Defines a pair of periodic walls. Inherits from BaseBoundary.
void read(std::istream &is) override
Reads the object's id_ from given istream.
void setPlanewiseShift(Vec3D planewiseShift)
Set the planewise shift (projected onto the planewise direction, and zero by default).
void moveLeft(Mdouble distanceLeft)
Sets the distance from the origin of the 'left' periodic wall.
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created...
Definition: DPMBase.h:1329
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
void createGhostParticle(BaseParticle *pReal)
Creates and adds a ghost particle from a give real particle.
virtual bool isClosestToLeftBoundary(const BaseParticle &p) const
Returns TRUE if particle checked is closest to the 'left' edge, and FALSE if it is closest to the 'ri...
void checkBoundaryAfterParticlesMove(ParticleHandler &pH) override
Checks if particle has crossed either boundary wall, and applies a shift if that is the case...
BoundaryHandler * getHandler() const
Returns the boundary's BoundaryHandler.
Mdouble distanceLeft_
position of left edge, s.t. normal*x = distanceLeft_
void copyInteractionsForPeriodicParticles(const BaseInteractable &p)
Copies interactions to this BaseInteractable whenever a periodic copy made.
Container to store all BaseParticle.
#define NUMBER_OF_PROCESSORS
For the MPI communication routines this quantity is often required. defining this macro makes the cod...
Definition: GeneralDefine.h:62
Vec3D shift_
shift from left to right boundary
static Mdouble getLengthSquared(const Vec3D &a)
Calculates the squared length of a Vec3D: .
Definition: Vector.h:316
void setPeriodicGhostParticle(bool flag)
Flags the status of the particle to be a ghost in periodic boundary or not.
virtual void hGridUpdateMove(BaseParticle *, Mdouble)
Definition: DPMBase.cc:1893
Definition: Vector.h:49
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
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
Definition: BaseHandler.h:725
void createPeriodicParticles(ParticleHandler &pH) override
Checks distance of particle to closest wall and creates periodic copy if necessary.
void read(std::istream &is) override
reads boundary properties from istream
~PeriodicBoundary() override
destructor
virtual void shiftPositions(Vec3D &postition1, Vec3D &postion2) const
shifts two positions