MercuryDPM  Trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SubcriticalMaserBoundary.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 
27 #include "DPMBase.h"
29 
34 {
35 #ifdef MERCURY_USE_MPI
36  logger(WARN,"Make sure the whole maser boundary is on one processor when using parallel code");
37 #endif
38  distanceLeft_ = std::numeric_limits<double>::quiet_NaN();
39  distanceRight_ = std::numeric_limits<double>::quiet_NaN();
40  maserIsActivated_ = false;
41 }
42 
49  periodicBoundary)
50 {
51  logger(INFO, "Constructor SubcriticalMaserBoundary(const PeriodicBoundary&) started");
52  distanceLeft_ = periodicBoundary.getDistanceLeft();
53  distanceRight_ = periodicBoundary.getDistanceRight();
54  normal_ = periodicBoundary.getNormal();
55  shift_ = periodicBoundary.getShift();
56  maserIsActivated_ = false;
57 
58  logger(INFO, "going to activate the maser");
59  //assume that the maser should be activated immediately when it gets constructed from a periodic boundary
60  activateMaser();
61 }
62 
69 {
70  return new SubcriticalMaserBoundary(*this);
71 }
72 
79 void SubcriticalMaserBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
80 {
81  // factor is used to set normal to unit length
82  Mdouble scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
83  normal_ = normal * scaleFactor_;
84  distanceLeft_ = distanceLeft * scaleFactor_;
85  distanceRight_ = distanceRight * scaleFactor_;
87  maserIsActivated_ = false;
88 }
89 
94 void SubcriticalMaserBoundary::read(std::istream& is)
95 {
97  std::string dummy;
98  is >> dummy >> normal_
99  >> dummy >> distanceLeft_
100  >> dummy >> distanceRight_
101  >> dummy >> shift_
102  >> dummy >> maserIsActivated_;
103  unsigned int n;
104  is >> dummy >> n;
105  const SpeciesHandler& speciesHandler = getHandler()->getDPMBase()->speciesHandler;
106  for (unsigned int i = 0; i < n; ++i)
107  {
108  unsigned int key;
109  unsigned int value;
110  is >> dummy >> key >> dummy >> value;
111  speciesConversionNormalToMaser_[speciesHandler.getObject(key)] = speciesHandler.getObject(value);
112  speciesConversionMaserToNormal_[speciesHandler.getObject(value)] = speciesHandler.getObject(key);
113  }
114  logger(DEBUG, "Finished reading SubcriticalMaserBoundary. \nNormal: % \nDistanceLeft: % \nDistanceRight: % "
115  ": % \nMaserIsActivated: %", normal_, distanceLeft_, distanceRight_, maserIsActivated_);
116 }
117 
122 void SubcriticalMaserBoundary::write(std::ostream& os) const
123 {
125  os << " normal " << normal_
126  << " distanceLeft " << distanceLeft_
127  << " distanceRight " << distanceRight_
128  << " shift " << shift_
129  << " maserIsActivated " << maserIsActivated_
130  << " numberOfMaserSpecies " << speciesConversionMaserToNormal_.size();
131  for (auto p : speciesConversionNormalToMaser_)
132  {
133  os << " outflowSpeciesIndex " << p.first->getIndex() << " maserSpeciesIndex " << p.second->getIndex();
134  }
135 }
136 
142 {
143  return "SubcriticalMaserBoundary";
144 }
145 
151 {
153  {
154  p->move(-shift_);
155  }
156  else // if closest to right boundary
157  {
158  p->move(shift_);
159  }
160 }
161 
177 {
179  {
180  // check if particle is near the boundaries of the maser domain
181  const Mdouble periodicDistance = p->getMaxInteractionRadius() + 2.0* pH.getLargestParticle()->getMaxInteractionRadius();
182  if (getDistance(p) < periodicDistance)
183  {
184  //furthermore, if the particle is on the right it has to be copied over to the outflow domain
186  {
187  BaseParticle* pGhost = createGhostCopy(p);
188 
189  // shift to the periodic location
190  shiftPosition(pGhost);
191 
192  // add the periodic particle to the handler
193  pH.addObject(pGhost);
194  }
195  else if (!maserIsActivated_)
196  {
197  BaseParticle* pGhost = createGhostCopy(p);
198 
199  // shift to the periodic location
200  shiftPosition(pGhost);
201 
202  // add the periodic particle to the handler
203  pH.addObject(pGhost);
204  }
205  }
206  }
207 }
208 
210 {
211  unsigned numberOfParticles = pH.getSize();
212  for (unsigned i = 0; i < numberOfParticles; i++)
213  {
215  }
216 }
217 
225 {
226  // Copy the particle and its interactions
227  BaseParticle* pGhost = p->copy();
229 
230  //Set the 'last' particle. If Particle is multiply shifted, get correct original particle
231  BaseParticle* last = p;
232  while (last->getPeriodicFromParticle() != nullptr)
233  {
234  last = last->getPeriodicFromParticle();
235  }
236  pGhost->setPeriodicFromParticle(last);
237  return pGhost;
238 }
239 
250 {
251  // check if particle passed either of the boundary walls
252  if (isMaserParticle(p) && getDistance(p) < 0)
253  {
254  // Checks if the particle is closest to the right boundary.
255  // If so, and if the Maser is turned on, then create a 'real'
256  // equivalent and move it over to the outflow domain
258  {
259  BaseParticle* pCopy = p->copy();
260  pCopy->setSpecies(speciesConversionMaserToNormal_.find(p->getSpecies())->second);
261  pH.addObject(pCopy);
262 
263  // If the (original) particle has crossed a right boundary,
264  // then shift that particle periodically.
265  shiftPosition(p);
266  }
267  else if (!maserIsActivated_)
268  {
269  shiftPosition(p);
270  }
271  }
272  return false;
273 }
274 
276 {
277  for (BaseParticle* p : pH)
278  {
280  }
281 }
282 
294 {
295  // check if particle species already known by the maser
296  auto conversion = speciesConversionNormalToMaser_.find(p->getSpecies());
297  if (conversion != speciesConversionNormalToMaser_.end())
298  {
299  //species known and flagged (i.e. 'converted')
300  logger(VERBOSE, "[SubcriticalMaserBoundary::addParticleToMaser()] Species conversion already present");
301  p->setSpecies(conversion->second);
302  }
303  else
304  {
305  SpeciesHandler& speciesHandler = (getHandler()->getDPMBase()->speciesHandler);
306  // species is not yet known by the maser, it has to be added to both maps
307  ParticleSpecies* newSpecies = speciesHandler.copyAndAddObject(*(p->getSpecies()));
309  std::pair<const ParticleSpecies*, const ParticleSpecies*>(p->getSpecies(), newSpecies));
311  std::pair<const ParticleSpecies*, const ParticleSpecies*>(newSpecies, p->getSpecies()));
312  logger(INFO, "[SubcriticalMaserBoundary::addParticleToMaser()] New species conversion created");
313  logger(INFO, "Original species ID: %, new species ID: %", p->getSpecies()->getId(), newSpecies->getId());
314 
315  //Copy over the mixed species. The delete is necessary here since it is overwritten with a copy of the old mixed
316  //species, and otherwise the properties are not copied over correctly.
317  //
318  //setId and setIndex refer to the two different species which are present in this mixed species.
319  //The highest species-index should appear first and is therefore the ID, while the second species-index is the
320  //"index" of the mixed species.
321  for (const BaseSpecies* const s : speciesHandler)
322  {
323  if (s->getId() != newSpecies->getId() && s->getId() != p->getSpecies()->getId())
324  {
325  BaseSpecies* newMixed = speciesHandler.getMixedObject(s->getId(), newSpecies->getId());
326  delete newMixed;
327  const BaseSpecies* const oldMixed = speciesHandler.getMixedObject(s->getId(), p->getSpecies()->getId());
328  newMixed = oldMixed->copy();
329  newMixed->setId(newSpecies->getId());
330  newMixed->setIndex(s->getId());
331  logger(DEBUG, "mixed species of % and % is now \n %, should be \n %", s->getId(), newSpecies->getId(),
332  *newMixed, *oldMixed);
333  }
334  }
335 
336  // now the species IS added, so flag (convert) it!
337  p->setSpecies(newSpecies);
338  }
339 }
340 
342 {
343  auto conversion = speciesConversionMaserToNormal_.find(p->getSpecies());
344  p->setSpecies(conversion->second);
345 }
346 
352 {
353  // Check if the particle is in the Maser, by checking whether its
354  // species is found in the list of maser particle species
355  auto positionMaserSpeciesInMap = speciesConversionMaserToNormal_.find(p->getSpecies());
356  return (positionMaserSpeciesInMap != speciesConversionMaserToNormal_.end()); //Test if it is a maser particle
357 }
358 
364 {
365  auto toFindOutflowSpecies = speciesConversionNormalToMaser_.find(p->getSpecies());
366  return (toFindOutflowSpecies != speciesConversionNormalToMaser_.end());
367 }
368 
373 {
374  activateMaser();
375 }
376 
385 {
386  if (!maserIsActivated_)
387  {
388  logger(INFO, "Going to add particles to the maser and shift the periodic maser boundaries");
390  logger(INFO, "just before particle loop");
391  for (BaseParticle* const p : pH)
392  {
393  if (getDistance(p) > 0)
394  {
396  }
397  }
398  maserIsActivated_ = true;
399  }
400  else
401  {
402  logger(WARN, "Cannot activate the maser boundary twice!");
403  }
404 }
405 
409 {
410  if (maserIsActivated_)
411  {
412  for (BaseParticle* const p : getHandler()->getDPMBase()->particleHandler)
413  {
414  if (getDistance(p) > 0)
415  {
417  }
418  }
419  maserIsActivated_ = false;
420  logger(INFO, "The Maser is no longer copying particles.");
421  }
422  else
423  {
424  logger(WARN, "Cannot close the maser if it is not active");
425  }
426 }
427 
429 {
430  return distanceLeft_;
431 }
432 
434 {
435  return distanceRight_;
436 }
Mdouble getDistanceLeft() const
Returns the distance of the left wall to the origin, in normal direction.
Container to store all ParticleSpecies.
BaseParticle * getLargestParticle() const
Returns the pointer of the largest particle in the particle handler. When mercury is running in paral...
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
void actionsBeforeTimeLoop() override
Does everything that needs to be done for this boundary between setupInitialConditions and the time l...
BaseSpecies is the class from which all other species are derived.
Definition: BaseSpecies.h:49
bool isNormalParticle(BaseParticle *p) const
Returns true if the particle is a Normal particle, and false otherwise.
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
Vec3D shift_
Direction in which particles are to be shifted when they cross the boundary.
const std::complex< Mdouble > i
Definition: ExtendedMath.h:50
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
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
Variation on the PeriodicBoundary which also has an outflow part.
Vec3D getShift() const
Returns the vector going from the left to the right side of the periodic boundary.
SubcriticalMaserBoundary()
MaserBoundary constructor.
Defines a pair of periodic walls. Inherits from BaseBoundary.
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
bool isClosestToRightBoundary(const BaseParticle *const p) const
Returns whether the given particle is closer to the right boundary of the periodic part...
SubcriticalMaserBoundary * copy() const override
Creates a copy of this maser on the heap.
Vec3D normal_
Normal unit vector of both maser walls. Points in the flowing direction.
void checkBoundaryAfterParticlesMove(ParticleHandler &pH) override
Evaluates what the particles have to do after they have changed position.
void set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
Sets all boundary properties at once and adds particles of the handler to the maser.
std::map< const ParticleSpecies *, const ParticleSpecies * > speciesConversionNormalToMaser_
List of 'normal' particles' species, and their maser counterparts.
bool checkBoundaryAfterParticleMoved(BaseParticle *p, ParticleHandler &pH) const
Shifts the particle to its 'periodic' position if it is a maser particle and has crossed either of th...
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
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.
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
Container to store all BaseParticle.
void createPeriodicParticle(BaseParticle *p, ParticleHandler &pH) override
Creates periodic particles when the particle is a maser particle and is sufficiently close to one of ...
void addParticleToMaser(BaseParticle *p)
Converts a 'normal' particle into a maser particle.
bool isMaserParticle(BaseParticle *p) const
Returns true if the particle is a Maser particle, and false otherwise.
std::map< const ParticleSpecies *, const ParticleSpecies * > speciesConversionMaserToNormal_
List of 'maser' particles' species, and their normal counterparts.
Mdouble getDistance(BaseParticle *p) const
Returns the distance of the wall to the particle.
void write(std::ostream &os) const override
writes boundary properties to ostream
void shiftPosition(BaseParticle *p) const
Shifts the particle to its 'periodic' position.
virtual BaseSpecies * copy() const =0
Creates a deep copy of the object from which it is called.
BaseParticle * createGhostCopy(BaseParticle *p) const
Creates a copy of the input particle, that gets removed again in DPMBase::removeDuplicatePeriodicPart...
void read(std::istream &is) override
reads boundary properties from istream
Mdouble distanceLeft_
position of left boundary wall, s.t. normal*x=position_left
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
void deactivateMaser()
Stops copying particles (and act merely as a chute)
void removeParticleFromMaser(BaseParticle *p)
Convert a maser particle into a 'normal' particle.
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 createPeriodicParticles(ParticleHandler &pH) override
std::string getName() const override
Returns the name of the object.