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 
73 void SubcriticalMaserBoundary::set(Vec3D normal, Vec3D planewiseShift, Mdouble distanceLeft, Mdouble distanceRight)
74 {
75  set(normal, distanceLeft, distanceRight);
76  setPlanewiseShift(planewiseShift);
77 }
78 
85 void SubcriticalMaserBoundary::set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
86 {
87  // factor is used to set normal to unit length
88  Mdouble scaleFactor_ = 1. / std::sqrt(Vec3D::dot(normal, normal));
89  normal_ = normal * scaleFactor_;
90  distanceLeft_ = distanceLeft * scaleFactor_;
91  distanceRight_ = distanceRight * scaleFactor_;
93  maserIsActivated_ = false;
94 }
95 
102 {
103  planewiseShift -= Vec3D::dot(planewiseShift, normal_) / Vec3D::dot(normal_, normal_) * normal_;
104  shift_ = normal_ * (distanceRight_ - distanceLeft_) + planewiseShift;
105 }
106 
108 {
109  shift_ = shift;
110 }
111 
116 void SubcriticalMaserBoundary::read(std::istream& is)
117 {
118  BaseBoundary::read(is);
119  std::string dummy;
120  is >> dummy >> normal_
121  >> dummy >> distanceLeft_
122  >> dummy >> distanceRight_
123  >> dummy >> shift_
124  >> dummy >> maserIsActivated_;
125  unsigned int n;
126  is >> dummy >> n;
127  const SpeciesHandler& speciesHandler = getHandler()->getDPMBase()->speciesHandler;
128  for (unsigned int i = 0; i < n; ++i)
129  {
130  unsigned int key;
131  unsigned int value;
132  is >> dummy >> key >> dummy >> value;
133  speciesConversionNormalToMaser_[speciesHandler.getObject(key)] = speciesHandler.getObject(value);
134  speciesConversionMaserToNormal_[speciesHandler.getObject(value)] = speciesHandler.getObject(key);
135  }
136  logger(DEBUG, "Finished reading SubcriticalMaserBoundary. \nNormal: % \nDistanceLeft: % \nDistanceRight: % "
137  ": % \nMaserIsActivated: %", normal_, distanceLeft_, distanceRight_, maserIsActivated_);
138 }
139 
144 void SubcriticalMaserBoundary::write(std::ostream& os) const
145 {
147  os << " normal " << normal_
148  << " distanceLeft " << distanceLeft_
149  << " distanceRight " << distanceRight_
150  << " shift " << shift_
151  << " maserIsActivated " << maserIsActivated_
152  << " numberOfMaserSpecies " << speciesConversionMaserToNormal_.size();
153  for (auto p : speciesConversionNormalToMaser_)
154  {
155  os << " outflowSpeciesIndex " << p.first->getIndex() << " maserSpeciesIndex " << p.second->getIndex();
156  }
157 }
158 
164 {
165  return "SubcriticalMaserBoundary";
166 }
167 
173 {
175  {
176  p->move(-shift_);
177  }
178  else // if closest to right boundary
179  {
180  p->move(shift_);
181  }
182 }
183 
199 {
201  {
202  // check if particle is near the boundaries of the maser domain
203  const Mdouble periodicDistance = p->getMaxInteractionRadius() + 2.0* pH.getLargestParticle()->getMaxInteractionRadius();
204  if (getDistance(p) < periodicDistance)
205  {
206  //furthermore, if the particle is on the right it has to be copied over to the outflow domain
208  {
209  BaseParticle* pGhost = createGhostCopy(p);
210 
211  // shift to the periodic location
212  shiftPosition(pGhost);
213 
214  // add the periodic particle to the handler
215  pH.addObject(pGhost);
216  }
217  else if (!maserIsActivated_)
218  {
219  BaseParticle* pGhost = createGhostCopy(p);
220 
221  // shift to the periodic location
222  shiftPosition(pGhost);
223 
224  // add the periodic particle to the handler
225  pH.addObject(pGhost);
226  }
227  }
228  }
229 }
230 
232 {
233  unsigned numberOfParticles = pH.getSize();
234  for (unsigned i = 0; i < numberOfParticles; i++)
235  {
237  }
238 }
239 
247 {
248  // Copy the particle and its interactions
249  BaseParticle* pGhost = p->copy();
251 
252  //Set the 'last' particle. If Particle is multiply shifted, get correct original particle
253  BaseParticle* last = p;
254  while (last->getPeriodicFromParticle() != nullptr)
255  {
256  last = last->getPeriodicFromParticle();
257  }
258  pGhost->setPeriodicFromParticle(last);
259  return pGhost;
260 }
261 
272 {
273  // check if particle passed either of the boundary walls
274  if (isMaserParticle(p) && getDistance(p) < 0)
275  {
276  // Checks if the particle is closest to the right boundary.
277  // If so, and if the Maser is turned on, then create a 'real'
278  // equivalent and move it over to the outflow domain
280  {
281  BaseParticle* pCopy = p->copy();
282  pCopy->setSpecies(speciesConversionMaserToNormal_.find(p->getSpecies())->second);
283  pH.addObject(pCopy);
284 
285  // If the (original) particle has crossed a right boundary,
286  // then shift that particle periodically.
287  shiftPosition(p);
288  }
289  else if (!maserIsActivated_)
290  {
291  shiftPosition(p);
292  }
293  }
294  return false;
295 }
296 
298 {
299  for (BaseParticle* p : pH)
300  {
302  }
303 }
304 
316 {
317  // check if particle species already known by the maser
318  auto conversion = speciesConversionNormalToMaser_.find(p->getSpecies());
319  if (conversion != speciesConversionNormalToMaser_.end())
320  {
321  //species known and flagged (i.e. 'converted')
322  logger(VERBOSE, "[SubcriticalMaserBoundary::addParticleToMaser()] Species conversion already present");
323  p->setSpecies(conversion->second);
324  }
325  else
326  {
327  SpeciesHandler& speciesHandler = (getHandler()->getDPMBase()->speciesHandler);
328  // species is not yet known by the maser, it has to be added to both maps
329  ParticleSpecies* newSpecies = speciesHandler.copyAndAddObject(*(p->getSpecies()));
331  std::pair<const ParticleSpecies*, const ParticleSpecies*>(p->getSpecies(), newSpecies));
333  std::pair<const ParticleSpecies*, const ParticleSpecies*>(newSpecies, p->getSpecies()));
334  logger(INFO, "[SubcriticalMaserBoundary::addParticleToMaser()] New species conversion created");
335  logger(INFO, "Original species ID: %, new species ID: %", p->getSpecies()->getId(), newSpecies->getId());
336 
337  //Copy over the mixed species. The delete is necessary here since it is overwritten with a copy of the old mixed
338  //species, and otherwise the properties are not copied over correctly.
339  //
340  //setId and setIndex refer to the two different species which are present in this mixed species.
341  //The highest species-index should appear first and is therefore the ID, while the second species-index is the
342  //"index" of the mixed species.
343  for (const BaseSpecies* const s : speciesHandler)
344  {
345  if (s->getId() != newSpecies->getId() && s->getId() != p->getSpecies()->getId())
346  {
347  BaseSpecies* newMixed = speciesHandler.getMixedObject(s->getId(), newSpecies->getId());
348  delete newMixed;
349  const BaseSpecies* const oldMixed = speciesHandler.getMixedObject(s->getId(), p->getSpecies()->getId());
350  newMixed = oldMixed->copy();
351  newMixed->setId(newSpecies->getId());
352  newMixed->setIndex(s->getId());
353  logger(DEBUG, "mixed species of % and % is now \n %, should be \n %", s->getId(), newSpecies->getId(),
354  *newMixed, *oldMixed);
355  }
356  }
357 
358  // now the species IS added, so flag (convert) it!
359  p->setSpecies(newSpecies);
360  }
361 }
362 
364 {
365  auto conversion = speciesConversionMaserToNormal_.find(p->getSpecies());
366  p->setSpecies(conversion->second);
367 }
368 
374 {
375  // Check if the particle is in the Maser, by checking whether its
376  // species is found in the list of maser particle species
377  auto positionMaserSpeciesInMap = speciesConversionMaserToNormal_.find(p->getSpecies());
378  return (positionMaserSpeciesInMap != speciesConversionMaserToNormal_.end()); //Test if it is a maser particle
379 }
380 
386 {
387  auto toFindOutflowSpecies = speciesConversionNormalToMaser_.find(p->getSpecies());
388  return (toFindOutflowSpecies != speciesConversionNormalToMaser_.end());
389 }
390 
395 {
396  activateMaser();
397 }
398 
407 {
408  if (!maserIsActivated_)
409  {
410  logger(INFO, "Going to add particles to the maser and shift the periodic maser boundaries");
412  logger(INFO, "just before particle loop");
413  for (BaseParticle* const p : pH)
414  {
415  if (getDistance(p) > 0)
416  {
418  }
419  }
420  maserIsActivated_ = true;
421  }
422  else
423  {
424  logger(WARN, "Cannot activate the maser boundary twice!");
425  }
426 }
427 
431 {
432  if (maserIsActivated_)
433  {
434  for (BaseParticle* const p : getHandler()->getDPMBase()->particleHandler)
435  {
436  if (getDistance(p) > 0)
437  {
439  }
440  }
441  maserIsActivated_ = false;
442  logger(INFO, "The Maser is no longer copying particles.");
443  }
444  else
445  {
446  logger(WARN, "Cannot close the maser if it is not active");
447  }
448 }
449 
451 {
452  return distanceLeft_;
453 }
454 
456 {
457  return distanceRight_;
458 }
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")
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
Vec3D shift_
Direction in which particles are to be shifted when they cross the boundary.
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
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
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
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 setPlanewiseShift(Vec3D planewiseShift)
Sets a planewise direction to the shift. Doesn't change the normal or the positions.
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:1395
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
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.
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:1385
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 setShift(Vec3D shift)
Sets the shift of the Maser. Usually don't use this directly, use set() or setPlanewiseShift() instea...
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.