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");
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 
82 void ConstantMassFlowMaserBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
83 {
84  // factor is used to set normal to unit length
85  Mdouble scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
86  normal_ = normal * scaleFactor_;
87  distanceLeft_ = distanceLeft * scaleFactor_;
88  distanceRight_ = distanceRight * scaleFactor_;
90  maserIsActivated_ = false;
91 }
92 
98 {
100  std::string dummy;
101  is >> dummy >> normal_
102  >> dummy >> distanceLeft_
103  >> dummy >> distanceRight_
104  >> dummy >> shift_
105  >> dummy >> gapSize_
106  >> dummy >> maserIsActivated_;
107  unsigned int n;
108  is >> dummy >> n;
109  const SpeciesHandler& speciesHandler = getHandler()->getDPMBase()->speciesHandler;
110  for (unsigned int i = 0; i < n; ++i)
111  {
112  unsigned int key;
113  unsigned int value;
114  is >> dummy >> key >> dummy >> value;
115  speciesConversionNormalToMaser_[speciesHandler.getObject(key)] = speciesHandler.getObject(value);
116  speciesConversionMaserToNormal_[speciesHandler.getObject(value)] = speciesHandler.getObject(key);
117  }
118  logger(DEBUG, "Finished reading ConstantMassFlowMaserBoundary. \nNormal: % \nDistanceLeft: % \nDistanceRight: % "
119  "\nGapsize: % \nMaserIsActivated: %", normal_, distanceLeft_, distanceRight_, gapSize_,
120  maserIsActivated_);
121 }
122 
127 void ConstantMassFlowMaserBoundary::write(std::ostream& os) const
128 {
130  os << " normal " << normal_
131  << " distanceLeft " << distanceLeft_
132  << " distanceRight " << distanceRight_
133  << " shift " << shift_
134  << " gapSize " << gapSize_
135  << " maserIsActivated " << maserIsActivated_
136  << " numberOfMaserSpecies " << speciesConversionMaserToNormal_.size();
137  for (auto p : speciesConversionNormalToMaser_)
138  {
139  os << " outflowSpeciesIndex " << p.first->getIndex() << " maserSpeciesIndex " << p.second->getIndex();
140  }
141 }
142 
148 {
149  return "ConstantMassFlowMaserBoundary";
150 }
151 
157 {
159  {
160  p->move(-shift_);
161  }
162  else // if closest to right boundary
163  {
164  p->move(shift_);
165  }
166 }
167 
182 {
183  if (isMaserParticle(p))
184  {
185  // check if particle is near the boundaries of the maser domain
187  {
188  BaseParticle* pGhost = createGhostCopy(p);
189 
190  // shift to the periodic location
191  shiftPosition(pGhost);
192 
193  // add the periodic particle to the handler
194  pH.addObject(pGhost);
195 
196  //furthermore, if the particle is on the right it has to be copied over to the outflow domain
198  {
199  // Copy the particle and its interactions if it is a maser particle
200  BaseParticle* pGhostOut = createGhostCopy(p);
201 
202  // shift to the outflow location
203  pGhostOut->move(gapSize_ * normal_);
204  // add the periodic particle to the handler
205  pH.addObject(pGhostOut);
206  }
207  }
208  }
209 }
210 
212 {
213  unsigned numberOfParticles = pH.getSize();
214  for (unsigned i = 0; i < numberOfParticles; i++)
215  {
217  }
218 }
219 
227 {
228  // Copy the particle and its interactions
229  BaseParticle* pGhost = p->copy();
231 
232  //Set the 'last' particle. If Particle is multiply shifted, get correct original particle
233  BaseParticle* last = p;
234  while (last->getPeriodicFromParticle() != nullptr)
235  {
236  last = last->getPeriodicFromParticle();
237  }
238  pGhost->setPeriodicFromParticle(last);
239  return pGhost;
240 }
241 
252 {
253  // check if particle passed either of the boundary walls
254  if (isMaserParticle(p) && getDistance(p) < 0)
255  {
256  // Checks if the particle is closest to the right boundary.
257  // If so, and if the Maser is turned on, then create a 'real'
258  // equivalent and move it over to the outflow domain
260  {
261  BaseParticle* pCopy = p->copy();
262  pCopy->setSpecies(speciesConversionMaserToNormal_.find(p->getSpecies())->second);
263  pCopy->move(gapSize_ * normal_);
264  pH.addObject(pCopy);
265  }
266 
267  // If the (original) particle has crossed a boundary wall (be it left or right),
268  // then shift that particle periodically.
269  shiftPosition(p);
270  }
271  else //remove normal particles trying to enter the gap between the maser and the outflow domain
272  {
273  const Mdouble distance = Vec3D::dot(p->getPosition(), normal_);
274  if (distance < gapSize_ + distanceRight_ && isNormalParticle(p))
275  {
276  pH.removeObject(p->getIndex());
277  return true;
278  }
279  }
280  return false;
281 }
282 
284 {
285  for (auto p = pH.begin(); p != pH.end(); ++p)
286  {
287  //If the particle has interacted with the boundary, change the iterator
289  {
290  p--;
291  }
292  }
293 }
294 
306 {
307  // check if particle species already known by the maser
308  auto conversion = speciesConversionNormalToMaser_.find(p->getSpecies());
309  if (conversion != speciesConversionNormalToMaser_.end())
310  {
311  //species known and flagged (i.e. 'converted')
312  logger(VERBOSE, "[ConstantMassFlowMaserBoundary::addParticleToMaser()] Species conversion already present");
313  p->setSpecies(conversion->second);
314  }
315  else
316  {
317  SpeciesHandler& speciesHandler = (getHandler()->getDPMBase()->speciesHandler);
318  // species is not yet known by the maser, it has to be added to both maps
319  ParticleSpecies* newSpecies = speciesHandler.copyAndAddObject(*(p->getSpecies()));
321  std::pair<const ParticleSpecies*, const ParticleSpecies*>(p->getSpecies(), newSpecies));
323  std::pair<const ParticleSpecies*, const ParticleSpecies*>(newSpecies, p->getSpecies()));
324  logger(INFO, "[ConstantMassFlowMaserBoundary::addParticleToMaser()] New species conversion created");
325  logger(INFO, "Original species ID: %, new species ID: %", p->getSpecies()->getId(), newSpecies->getId());
326 
327  //Copy over the mixed species. The delete is necessary here since it is overwritten with a copy of the old mixed
328  //species, and otherwise the properties are not copied over correctly.
329  //
330  //setId and setIndex refer to the two different species which are present in this mixed species.
331  //The highest species-index should appear first andis therefore the ID, while the second species-index is the
332  //"index" of the mixed species.
333  for (const BaseSpecies* const s : speciesHandler)
334  {
335  if (s->getId() != newSpecies->getId() && s->getId() != p->getSpecies()->getId())
336  {
337  BaseSpecies* newMixed = speciesHandler.getMixedObject(s->getId(), newSpecies->getId());
338  const BaseSpecies* const oldMixed = speciesHandler.getMixedObject(s->getId(), p->getSpecies()->getId());
339  oldMixed->copyInto(newMixed);
340  newMixed->setId(newSpecies->getId());
341  newMixed->setIndex(s->getId());
342  logger(DEBUG, "mixed species of % and % is now \n %, should be \n %", s->getId(), newSpecies->getId(),
343  *newMixed, *oldMixed);
344  }
345  }
346 
347  // now the species IS added, so flag (convert) it!
348  p->setSpecies(newSpecies);
349  }
350  p->move(-normal_ * gapSize_);
351 }
352 
354 {
355  auto conversion = speciesConversionMaserToNormal_.find(p->getSpecies());
356  if (conversion != speciesConversionMaserToNormal_.end())
357  {
358  p->setSpecies(conversion->second);
359  p->move(normal_ * gapSize_);
360  }
361 }
362 
368 {
369  // Check if the particle is in the Maser, by checking whether its
370  // species is found in the list of maser particle species
371  auto positionMaserSpeciesInMap = speciesConversionMaserToNormal_.find(p->getSpecies());
372  return (positionMaserSpeciesInMap != speciesConversionMaserToNormal_.end()); //Test if it is a maser particle
373 }
374 
380 {
381  auto toFindOutflowSpecies = speciesConversionNormalToMaser_.find(p->getSpecies());
382  return (toFindOutflowSpecies != speciesConversionNormalToMaser_.end());
383 }
384 
389 {
390  activateMaser();
391 }
392 
402 {
403  if (!maserIsActivated_)
404  {
405  logger(INFO, "Going to add particles to the maser and shift the periodic maser boundaries");
408  logger(INFO, "just before particle loop");
409  for (BaseParticle* const p : pH)
410  {
411  if (getDistance(p) > 0)
412  {
414  }
415  }
416 
417 
420  maserIsActivated_ = true;
421 
422  turnOnCopying();
423 
424  logger(INFO, "The Maser has been activated, and is now copying particles.");
425  }
426  else
427  {
428  logger(WARN, "Cannot activate the maser boundary twice!");
429  }
430 }
431 
435 {
436  if (maserIsActivated_)
437  {
438  for (BaseParticle* const p : getHandler()->getDPMBase()->particleHandler)
439  {
440  if (getDistance(p) > 0)
441  {
443  }
444  }
447  maserIsActivated_ = false;
448 
449  turnOffCopying();
450 
451  logger(INFO, "The Maser has been deactivated.");
452  }
453  else
454  {
455  logger(WARN, "Cannot close the maser if it is not active");
456  }
457 }
458 
460 {
461  return maserIsActivated_;
462 }
463 
465 {
466  maserIsCopying_ = true;
467 }
468 
470 {
471  maserIsCopying_ = false;
472 }
473 
474 
476 {
477  if (!isActivated())
478  logger(WARN, "The Maser is closed, so isCopying() is irrelevant.");
479 
480  return maserIsCopying_;
481 }
482 
484 {
485  return distanceLeft_;
486 }
487 
489 {
490  return distanceRight_;
491 }
492 
494 {
495  return gapSize_;
496 }
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")
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:359
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:50
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:438
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
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 polymorfism.
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.
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:1329
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 set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
Sets all boundary properties at once and adds particles of the handler to the maser.
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:345
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:1319
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 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.