MercuryDPM  Trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ConstantMassFlowMaserBoundary.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 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 
28 #include "DPMBase.h"
29 #include <algorithm>
30 
35 {
36 #ifdef MERCURY_USE_MPI
37  logger(WARN,"Make sure the whole maser boundary is on one processor when using parallel code");
38 #endif
39  distanceLeft_ = std::numeric_limits<double>::quiet_NaN();
40  distanceRight_ = std::numeric_limits<double>::quiet_NaN();
41  gapSize_ = std::numeric_limits<double>::quiet_NaN();
42  maserIsActivated_ = false;
43 }
44 
51  periodicBoundary)
52 {
53  logger(INFO, "Constructor ConstantMassFlowMaserBoundary(const PeriodicBoundary&) started\n", Flusher::NO_FLUSH);
54  distanceLeft_ = periodicBoundary.getDistanceLeft();
55  distanceRight_ = periodicBoundary.getDistanceRight();
56  normal_ = periodicBoundary.getNormal();
57  shift_ = periodicBoundary.getShift();
58  gapSize_ = std::numeric_limits<double>::quiet_NaN();
59  maserIsActivated_ = false;
60 
61  logger(INFO, "going to activate the maser");
62  //assume that the maser should be activated immediately when it gets constructed from a periodic boundary
63  activateMaser();
64 }
65 
72 {
73  return new ConstantMassFlowMaserBoundary(*this);
74 }
75 
76 void ConstantMassFlowMaserBoundary::set(Vec3D normal, Vec3D planewiseShift, Mdouble distanceLeft, Mdouble distanceRight)
77 {
78  set(normal, distanceLeft, distanceRight);
79  setPlanewiseShift(planewiseShift);
80 }
81 
82 
89 void ConstantMassFlowMaserBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
90 {
91  // factor is used to set normal to unit length
92  Mdouble scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
93  normal_ = normal * scaleFactor_;
94  distanceLeft_ = distanceLeft * scaleFactor_;
95  distanceRight_ = distanceRight * scaleFactor_;
97  maserIsActivated_ = false;
98 }
99 
106 {
107  planewiseShift -= Vec3D::dot(planewiseShift, normal_) / Vec3D::dot(normal_, normal_) * normal_;
108  shift_ = normal_ * (distanceRight_ - distanceLeft_) + planewiseShift;
109 }
110 
112 {
113  shift_ = shift;
114 }
115 
121 {
122  BaseBoundary::read(is);
123  std::string dummy;
124  is >> dummy >> normal_
125  >> dummy >> distanceLeft_
126  >> dummy >> distanceRight_
127  >> dummy >> shift_
128  >> dummy >> gapSize_
129  >> dummy >> maserIsActivated_;
130  unsigned int n;
131  is >> dummy >> n;
132  const SpeciesHandler& speciesHandler = getHandler()->getDPMBase()->speciesHandler;
133  for (unsigned int i = 0; i < n; ++i)
134  {
135  unsigned int key;
136  unsigned int value;
137  is >> dummy >> key >> dummy >> value;
138  speciesConversionNormalToMaser_[speciesHandler.getObject(key)] = speciesHandler.getObject(value);
139  speciesConversionMaserToNormal_[speciesHandler.getObject(value)] = speciesHandler.getObject(key);
140  }
141  logger(DEBUG, "Finished reading ConstantMassFlowMaserBoundary. \nNormal: % \nDistanceLeft: % \nDistanceRight: % "
142  "\nGapsize: % \nMaserIsActivated: %",
143  normal_, distanceLeft_, distanceRight_, gapSize_, maserIsActivated_);
144 }
145 
150 void ConstantMassFlowMaserBoundary::write(std::ostream& os) const
151 {
153  os << " normal " << normal_
154  << " distanceLeft " << distanceLeft_
155  << " distanceRight " << distanceRight_
156  << " shift " << shift_
157  << " gapSize " << gapSize_
158  << " maserIsActivated " << maserIsActivated_
159  << " numberOfMaserSpecies " << speciesConversionMaserToNormal_.size();
160  for (auto p : speciesConversionNormalToMaser_)
161  {
162  os << " outflowSpeciesIndex " << p.first->getIndex() << " maserSpeciesIndex " << p.second->getIndex();
163  }
164 }
165 
171 {
172  return "ConstantMassFlowMaserBoundary";
173 }
174 
180 {
182  {
183  p->move(-shift_);
184  }
185  else // if closest to right boundary
186  {
187  p->move(shift_);
188  }
189 }
190 
205 {
206  if (isMaserParticle(p))
207  {
208  // check if particle is near the boundaries of the maser domain
210  {
211  BaseParticle* pGhost = createGhostCopy(p);
212 
213  // shift to the periodic location
214  shiftPosition(pGhost);
215 
216  // add the periodic particle to the handler
217  pH.addObject(pGhost);
218 
219  //furthermore, if the particle is on the right it has to be copied over to the outflow domain
221  {
222  // Copy the particle and its interactions if it is a maser particle
223  BaseParticle* pGhostOut = createGhostCopy(p);
224 
225  // shift to the outflow location
226  pGhostOut->move(gapSize_ * normal_);
227  // add the periodic particle to the handler
228  pH.addObject(pGhostOut);
229  }
230  }
231  }
232 }
233 
235 {
236  unsigned numberOfParticles = pH.getSize();
237  for (unsigned i = 0; i < numberOfParticles; i++)
238  {
240  }
241 }
242 
250 {
251  // Copy the particle and its interactions
252  BaseParticle* pGhost = p->copy();
254 
255  //Set the 'last' particle. If Particle is multiply shifted, get correct original particle
256  BaseParticle* last = p;
257  while (last->getPeriodicFromParticle() != nullptr)
258  {
259  last = last->getPeriodicFromParticle();
260  }
261  pGhost->setPeriodicFromParticle(last);
262  return pGhost;
263 }
264 
275 {
276  // check if particle passed either of the boundary walls
277  if (isMaserParticle(p) && getDistance(p) < 0)
278  {
279  // Checks if the particle is closest to the right boundary.
280  // If so, and if the Maser is turned on, then create a 'real'
281  // equivalent and move it over to the outflow domain
283  {
284  BaseParticle* pCopy = p->copy();
285  pCopy->setSpecies(speciesConversionMaserToNormal_.find(p->getSpecies())->second);
286  pCopy->move(gapSize_ * normal_);
287  pH.addObject(pCopy);
288  }
289 
290  // If the (original) particle has crossed a boundary wall (be it left or right),
291  // then shift that particle periodically.
292  shiftPosition(p);
293  }
294  else //remove normal particles trying to enter the gap between the maser and the outflow domain
295  {
296  const Mdouble distance = Vec3D::dot(p->getPosition(), normal_);
297  if (distance < gapSize_ + distanceRight_ && isNormalParticle(p))
298  {
299  pH.removeObject(p->getIndex());
300  return true;
301  }
302  }
303  return false;
304 }
305 
307 {
308  for (auto p = pH.begin(); p != pH.end(); ++p)
309  {
310  //If the particle has interacted with the boundary, change the iterator
312  {
313  p--;
314  }
315  }
316 }
317 
329 {
330  // check if particle species already known by the maser
331  auto conversion = speciesConversionNormalToMaser_.find(p->getSpecies());
332  if (conversion != speciesConversionNormalToMaser_.end())
333  {
334  //species known and flagged (i.e. 'converted')
335  logger(VERBOSE, "[ConstantMassFlowMaserBoundary::addParticleToMaser()] Species conversion already present");
336  p->setSpecies(conversion->second);
337  }
338  else
339  {
340  SpeciesHandler& speciesHandler = (getHandler()->getDPMBase()->speciesHandler);
341  // species is not yet known by the maser, it has to be added to both maps
342  ParticleSpecies* newSpecies = speciesHandler.copyAndAddObject(*(p->getSpecies()));
344  std::pair<const ParticleSpecies*, const ParticleSpecies*>(p->getSpecies(), newSpecies));
346  std::pair<const ParticleSpecies*, const ParticleSpecies*>(newSpecies, p->getSpecies()));
347  logger(INFO, "[ConstantMassFlowMaserBoundary::addParticleToMaser()] New species conversion created\n",
349  logger(INFO, "Original species ID: %, new species ID: %", p->getSpecies()->getId(), newSpecies->getId());
350 
351  //Copy over the mixed species. The delete is necessary here since it is overwritten with a copy of the old mixed
352  //species, and otherwise the properties are not copied over correctly.
353  //
354  //setId and setIndex refer to the two different species which are present in this mixed species.
355  //The highest species-index should appear first andis therefore the ID, while the second species-index is the
356  //"index" of the mixed species.
357  for (const BaseSpecies* const s: speciesHandler)
358  {
359  if (s->getId() != newSpecies->getId() && s->getId() != p->getSpecies()->getId())
360  {
361  BaseSpecies* newMixed = speciesHandler.getMixedObject(s->getId(), newSpecies->getId());
362  const BaseSpecies* const oldMixed = speciesHandler.getMixedObject(s->getId(), p->getSpecies()->getId());
363  oldMixed->copyInto(newMixed);
364  newMixed->setId(newSpecies->getId());
365  newMixed->setIndex(s->getId());
366  logger(DEBUG, "mixed species of % and % is now \n %, should be \n %", s->getId(), newSpecies->getId(),
367  *newMixed, *oldMixed);
368  }
369  }
370 
371  // now the species IS added, so flag (convert) it!
372  p->setSpecies(newSpecies);
373  }
374  p->move(-normal_ * gapSize_);
375 }
376 
378 {
379  auto conversion = speciesConversionMaserToNormal_.find(p->getSpecies());
380  if (conversion != speciesConversionMaserToNormal_.end())
381  {
382  p->setSpecies(conversion->second);
383  p->move(normal_ * gapSize_);
384  }
385 }
386 
392 {
393  // Check if the particle is in the Maser, by checking whether its
394  // species is found in the list of maser particle species
395  auto positionMaserSpeciesInMap = speciesConversionMaserToNormal_.find(p->getSpecies());
396  return (positionMaserSpeciesInMap != speciesConversionMaserToNormal_.end()); //Test if it is a maser particle
397 }
398 
404 {
405  auto toFindOutflowSpecies = speciesConversionNormalToMaser_.find(p->getSpecies());
406  return (toFindOutflowSpecies != speciesConversionNormalToMaser_.end());
407 }
408 
413 {
414  activateMaser();
415 }
416 
426 {
427  if (!maserIsActivated_)
428  {
429  logger(INFO, "Going to add particles to the maser and shift the periodic maser boundaries\n",
433  logger(INFO, "just before particle loop");
434  for (BaseParticle* const p: pH)
435  {
436  if (getDistance(p) > 0)
437  {
439  }
440  }
441 
442 
445  maserIsActivated_ = true;
446 
447  turnOnCopying();
448 
449  logger(INFO, "The Maser has been activated, and is now copying particles.");
450  }
451  else
452  {
453  logger(WARN, "Cannot activate the maser boundary twice!");
454  }
455 }
456 
460 {
461  if (maserIsActivated_)
462  {
463  for (BaseParticle* const p : getHandler()->getDPMBase()->particleHandler)
464  {
465  if (getDistance(p) > 0)
466  {
468  }
469  }
472  maserIsActivated_ = false;
473 
474  turnOffCopying();
475 
476  logger(INFO, "The Maser has been deactivated.");
477  }
478  else
479  {
480  logger(WARN, "Cannot close the maser if it is not active");
481  }
482 }
483 
485 {
486  return maserIsActivated_;
487 }
488 
490 {
491  maserIsCopying_ = true;
492 }
493 
495 {
496  maserIsCopying_ = false;
497 }
498 
499 
501 {
502  if (!isActivated())
503  logger(WARN, "The Maser is closed, so isCopying() is irrelevant.");
504 
505  return maserIsCopying_;
506 }
507 
509 {
510  return distanceLeft_;
511 }
512 
514 {
515  return distanceRight_;
516 }
517 
519 {
520  return gapSize_;
521 }
Mdouble getDistanceLeft() const
Returns the distance of the left wall to the origin, in normal direction.
Container to store all ParticleSpecies.
void activateMaser()
Opens the gap, and transforms particles to maser particles. Also calls turnOnCopying().
void setIndex(unsigned int index)
Allows one to assign an index to an object in the handler/container.
Definition: BaseObject.cc:64
unsigned int getId() const
Returns the unique identifier of any particular object.
Definition: BaseObject.h:125
bool checkBoundaryAfterParticleMoved(BaseParticle *p, ParticleHandler &pH)
Shifts the particle to its 'periodic' position if it is a maser particle and has crossed either of th...
unsigned int getIndex() const
Returns the index of the object in the handler.
Definition: BaseObject.h:118
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
void removeObject(unsigned int index) override
Removes a BaseParticle from the ParticleHandler.
BaseSpecies is the class from which all other species are derived.
Definition: BaseSpecies.h:49
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
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here...
double Mdouble
Definition: GeneralDefine.h:34
const ParticleSpecies * getSpecies() const
Returns a pointer to the species of this BaseInteractable.
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:362
bool isActivated() const
Returns whether the Maser is activated or not.
void removeParticleFromMaser(BaseParticle *p)
Convert a maser particle into a 'normal' particle.
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
void addParticleToMaser(BaseParticle *p)
Converts a 'normal' particle into a maser particle.
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
virtual void copyInto(BaseSpecies *s) const =0
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:441
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:341
void setSpecies(const ParticleSpecies *species)
void read(std::istream &is) override=0
Reads the object's id_ from given istream NB: purely virtual function, overriding the version of Base...
Definition: BaseBoundary.cc:61
Mdouble distanceLeft_
position of left boundary wall, s.t. normal*x=position_left
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 polymorphism.
Vec3D getNormal() const
returns the vector normal to the periodic boundary
Vec3D getShift() const
Returns the vector going from the left to the right side of the periodic boundary.
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.
BaseParticle * createGhostCopy(BaseParticle *p) const
Creates a copy of the input particle, that gets removed again in DPMBase::removeDuplicatePeriodicPart...
Vec3D shift_
Direction in which particles are to be shifted when they cross the boundary.
void setShift(Vec3D shift)
Sets the shift of the Maser. Usually don't use this directly, use set() or setPlanewiseShift() instea...
bool isMaserParticle(BaseParticle *p) const
Returns true if the particle is a Maser particle, and false otherwise.
void turnOffCopying()
Stop copying particles.
bool isNormalParticle(BaseParticle *p) const
Returns true if the particle is a Normal particle, and false otherwise.
Variation on the PeriodicBoundary which also has an outflow part.
void checkBoundaryAfterParticlesMove(ParticleHandler &pH) override
Evaluates what the particles have to do after they have changed position.
bool isClosestToRightBoundary(const BaseParticle *const p) const
Returns whether the given particle is closer to the right boundary of the periodic part...
void read(std::istream &is) override
reads boundary properties from istream
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created...
Definition: DPMBase.h:1395
bool maserIsCopying_
Flag whether or not the Maser is copying particles.
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
void write(std::ostream &os) const override
writes boundary properties to ostream
std::enable_if<!std::is_pointer< U >::value, U * >::type copyAndAddObject(const U &object)
Creates a copy of a Object and adds it to the BaseHandler.
Definition: BaseHandler.h:379
void write(std::ostream &os) const override=0
Adds object's id_ to given ostream NB: purely virtual function, overriding the version of BaseObject...
Definition: BaseBoundary.cc:70
BoundaryHandler * getHandler() const
Returns the boundary's BoundaryHandler.
Mdouble getRadius() const
Returns the particle's radius.
Definition: BaseParticle.h:348
void turnOnCopying()
Start copying particles.
std::map< const ParticleSpecies *, const ParticleSpecies * > speciesConversionMaserToNormal_
List of 'maser' particles' species, and their normal counterparts.
void copyInteractionsForPeriodicParticles(const BaseInteractable &p)
Copies interactions to this BaseInteractable whenever a periodic copy made.
SpeciesHandler speciesHandler
A handler to that stores the species type i.e. LinearViscoelasticSpecies, etc.
Definition: DPMBase.h:1385
ConstantMassFlowMaserBoundary()
MaserBoundary constructor.
std::map< const ParticleSpecies *, const ParticleSpecies * > speciesConversionNormalToMaser_
List of 'normal' particles' species, and their maser counterparts.
Container to store all BaseParticle.
bool maserIsActivated_
Flag whether or not the gap is created and particles transformed already.
Mdouble distanceRight_
position of right boundary wall, s.t. normal*x=position_right
Vec3D normal_
Normal unit vector of both maser walls. Points in the flowing direction.
void closeMaser()
Stops copying particles (and act merely as a chute)
void shiftPosition(BaseParticle *p) const
Shifts the particle to its 'periodic' position.
void createPeriodicParticles(ParticleHandler &pH) override
Mdouble gapSize_
distance between the right side of the periodic domain and the start of the outflow domain...
std::string getName() const override
Returns the name of the object.
Definition: Vector.h:49
virtual void move(const Vec3D &move)
Moves this BaseInteractable by adding an amount to the position.
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
Definition: BaseHandler.h:725
Mdouble getDistance(BaseParticle *p) const
Returns the distance of the wall to the particle.
void setPlanewiseShift(Vec3D planewiseShift)
Sets a planewise direction to the shift. Doesn't change the normal or the positions.
void set(Vec3D normal, Vec3D planewiseShift, Mdouble distanceLeft, Mdouble distanceRight)
Sets all boundary properties at once and adds particles of the handler to the maser. This deactivates the Maser.
void createPeriodicParticle(BaseParticle *p, ParticleHandler &pH) override
Creates periodic particles when the particle is a maser particle and is sufficiently close to one of ...
BaseParticle * getLargestParticleLocal() const
Gets a pointer to the largest BaseParticle (by interactionRadius) in the ParticleHandler of the local...
void setId(unsigned long id)
Assigns a unique identifier to each object in the handler (container) which remains constant even aft...
Definition: BaseObject.cc:72
void actionsBeforeTimeLoop() override
Does everything that needs to be done for this boundary between setupInitialConditions and the time l...
ConstantMassFlowMaserBoundary * copy() const override
Creates a copy of this maser on the heap.
bool isCopying() const
Returns whether the Maser is copying particles or not.