BaseHandler.h
Go to the documentation of this file.
1 //Copyright (c) 2013-2023, 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 
31 #ifndef BASEHANDLER_H
32 #define BASEHANDLER_H
33 
34 #include <vector>
35 #include <type_traits>
36 #include "Math/Helpers.h"
37 #include "Logger.h"
38 
39 class DPMBase;
40 
49 template<typename T>
51 {
52 public:
58 
63 
67  virtual ~BaseHandler();
68 
74 
78  template<typename U>
79  typename std::enable_if<!std::is_pointer<U>::value, U*>::type
80  copyAndAddObject(const U& object);
81 
85  template<typename U>
86  typename std::enable_if<std::is_pointer<U>::value, U>::type
87  copyAndAddObject(const U object);
88 
95  template<typename U>
96  typename std::enable_if<!std::is_pointer<U>::value, U*>::type
97  copyAndAddGhostObject(const U& object);
98 
105  template<typename U>
106  typename std::enable_if<std::is_pointer<U>::value, U>::type
107  copyAndAddGhostObject(const U object);
108 
113  virtual void addExistingObject(T* O);
114 
118  virtual void addObject(T* object);
119 
124  virtual void addGhostObject(T* O);
125 
126  void removeIf(const std::function<bool(T*)> cond);
127 
131  virtual void removeObject(unsigned const int index);
132 
137 
141  virtual void clear();
142 
147  virtual void readAndAddObject(std::istream& is) = 0;
148 
152  void read(std::istream& is);
153 
157  T* getObjectById(const unsigned int id);
158 
162  std::vector<T*> getObjectsById(const unsigned int id);
163 
167  T* getObject(const unsigned int id);
168 
172  const T* getObject(const unsigned int id) const;
173 
178 
182  const T* getLastObject() const;
183 
187  virtual unsigned int getNumberOfObjects() const;
188 
192  unsigned int getSize() const;
193 
197  unsigned int getStorageCapacity() const;
198 
202  void setStorageCapacity(const unsigned int N);
203 
207  void resize(const unsigned int N, const T& obj);
208 
212  const typename std::vector<T*>::const_iterator begin() const;
213 
217  const typename std::vector<T*>::iterator begin();
218 
222  const typename std::vector<T*>::const_iterator end() const;
223 
227  const typename std::vector<T*>::iterator end();
228 
234 
238  void setId(T* object, unsigned int id)
239  {
240  object->setId(id);
241  if (nextId_ <= id)
242  {
243  nextId_ = id + 1;
244  }
245  }
246 
247  /*
248  * \brief This function updates the iD counter by one
249  * \details Function used in parallel to keep the Id's unique over all processors
250  */
251  void increaseId()
252  {
253  nextId_++;
254  }
255 
256  unsigned int getNextId()
257  {
258  return nextId_;
259  }
260 
261  void setNextId(unsigned int id)
262  {
263  nextId_ = id;
264  }
265 
270 
274  DPMBase* getDPMBase() const;
275 
279  virtual std::string getName() const = 0;
280 
285  [[deprecated]]
286  virtual void writeVTK() const
287  {};
288 
293  unsigned getNextGroupId() { return nextGroupId_++; }
294 
295 protected:
302  std::vector<T*> objects_;
303 
304 private:
308  unsigned int maxObjects_;
309 
313  unsigned int nextId_;
314 
320  unsigned nextGroupId_ = 1;
321 
329 };
330 
334 template<typename T>
336 {
337  DPMBase_ = nullptr;
338  clear();
339  logger(DEBUG, "BaseHandler<T>::BaseHandler() finished");
340 }
341 
349 template<typename T>
351 {
352  DPMBase_ = nullptr;
353  clear();
354  copyContentsFromOtherHandler(BH);
355  logger(DEBUG, "BaseHandler<T>::BaseHandler(const BaseHandler &BH) finished");
356 }
357 
358 template<typename T>
360 {
361  clear();
362  logger(DEBUG, "BaseHandler<T>::~BaseHandler() finished");
363 }
364 
366 template<typename T>
368 {
369  for (const T* const obj : BH.objects_)
370  {
371  addObject(obj->copy());
372  }
373 }
374 
376 template<typename T>
377 template<typename U>
378 typename std::enable_if<!std::is_pointer<U>::value, U*>::type
380 {
381  U* oCopy = object.copy();
382  addObject(oCopy);
383  return oCopy;
384 }
385 
387 template<typename T>
388 template<typename U>
389 typename std::enable_if<std::is_pointer<U>::value, U>::type
391 {
392  return copyAndAddObject(*object);
393 }
394 
396 template<class T>
397 template<class U>
398 typename std::enable_if<!std::is_pointer<U>::value, U*>::type
400 {
401  U* oCopy = object.copy();
402  addGhostObject(oCopy);
403  return oCopy;
404 }
405 
407 template<class T>
408 template<class U>
409 typename std::enable_if<std::is_pointer<U>::value, U>::type
411 {
412  return copyAndAddGhostObject(*object);
413 }
414 
416 template<class T>
418 {
419  objects_.push_back(O);
420  //Set the index of the particle
421  getLastObject()->setIndex(getSize() - 1);
422  //Adjust the nextId_ value
423  if (O->getId() + 1 > nextId_)
424  {
425  nextId_ = O->getId() + 1;
426  }
427 }
428 
430 template<class T>
432 {
433  objects_.push_back(object);
434  //Set the index of the particle
435  getLastObject()->setIndex(getSize() - 1);
436  //set the non changing particle identifier
437  getLastObject()->setId(nextId_);
438  //Update Id for next particle
439  nextId_++;
440 }
441 
443 template<class T>
445 {
446  objects_.push_back(O);
447  //Set the index of the particle
448  getLastObject()->setIndex(getSize() - 1);
449 }
450 
451 //\todo should this function ever be used?
452 template<class T>
453 void BaseHandler<T>::removeIf(const std::function<bool(T*)> cond)
454 {
455  for (int i = 0; i < objects_.size(); ++i) {
456  if (cond(objects_[i]))
457  {
458  //objects_(i)->actionsOnErase();
459  removeObject(i);
460  --i;
461  }
462  }
463 }
464 
471 template<typename T>
472 void BaseHandler<T>::removeObject(const unsigned int index)
473 {
474  logger.assert_debug(index < getSize(),
475  "In: void %::removeObject(const unsigned int index) const, "
476  "no object exists with index %, number of objects is %",
477  getName(), index, getSize());
478 
479  //Removing a particle within the list is not efficient.
480  //Swap with last element and then perform the deletion
481  const unsigned int lastIndex = objects_.size() - 1;
482 
483  T* const objectToDelete = objects_[index];
484 
485  //No swapping required if it is the last object
486  if (index != lastIndex)
487  {
488 
489  T* const objectToMove = objects_[lastIndex];
490 
491  objects_[index] = objectToMove; //place it back
492  objects_[lastIndex] = objectToDelete; //Just to make sure.
493 
494  //and notify it of the change.
495  objects_[index]->moveInHandler(index);
496  //Even though we are going to delete this particle,
497  //we still need to keep it consistent.
498  objects_[lastIndex]->moveInHandler(lastIndex);
499  }
500 
501 
502  //And clear it from the backing container.
503  objects_.pop_back();
504  //And _NOW_ we delete it.
505 
506  delete objectToDelete;
507 
508 }
509 
510 template<typename T>
512 {
513  if (getSize() == 0)
514  {
515  logger(WARN, "In: void %::removeLastObject, no Object exists in this BaseHandler.", getName());
516  return;
517  }
518  T* const object = objects_.back();
519  //Remove the (now double) reference to that last Object
520  objects_.pop_back();
521  //Physically removes Object
522  delete object;
523 }
524 
527 template<typename T>
529 {
530 
531  for (T* const obj : objects_)
532  {
533  delete obj;
534  }
535  objects_.clear();
536 
537  nextId_ = 0;
538  maxObjects_ = 0;
539 }
540 
542 template<typename T>
543 void BaseHandler<T>::read(std::istream& is)
544 {
545  clear();
546  unsigned int N;
547  std::string dummy;
548  is >> dummy;
549  std::stringstream line;
551  line >> N;
552  logger(VERBOSE, "In %::read(is): reading in % objects.", getName(), N);
553  setStorageCapacity(N);
554  for (unsigned int i = 0; i < N; i++)
555  {
556  readAndAddObject(is);
557  }
558 }
559 
564 template<typename T>
565 T* BaseHandler<T>::getObjectById(const unsigned int id)
566 {
567  // Usually, the id and the index into the backing storage matches
568  // So check this position first!
569  // dducks: Can't we guarantee more? That should speed up searches.
570  if (id < objects_.size() && objects_[id]->getId() == id)
571  {
572  return objects_[id]; //There is a hit, return early
573  }
574 
575  for (T* obj : objects_) //Search for the correct id, since it wasn't where
576  { // we expected it. Just use a linear search..
577  if (obj->getId() == id) //Found it, so return!
578  return obj;
579  }
580 #ifndef MERCURYDPM_USE_MPI
581  logger(ERROR, "[BaseHandler::getObjectById()] in Object* %: Object with ID % could not be found.", getName(), id);
582 #endif
583  return nullptr;
584 }
585 
592 template<typename T>
593 std::vector<T*> BaseHandler<T>::getObjectsById(const unsigned int id)
594 {
595  std::vector<T*> list;
596  for (T* obj : objects_)
597  {
598  if (obj->getId() == id)
599  {
600  list.push_back(obj);
601  }
602  }
603 #ifndef MERCURYDPM_USE_MPI
604  logger(ERROR, "[BaseHandler::getObjectById()] in Object* %: Object with ID % could not be found.", getName(), id);
605 #endif
606  return list;
607 
608 }
609 
612 template<typename T>
613 T* BaseHandler<T>::getObject(const unsigned int index)
614 {
615  logger.assert_debug(index < getSize(),
616  "[%::getObject()] Object couldn't be found because index (%) is higher than number of objects (%).",
617  getName(), index, getSize());
618  return objects_[index];
619 }
620 
623 template<typename T>
624 const T* BaseHandler<T>::getObject(const unsigned int index) const
625 {
626  logger.assert_debug(index < getSize(),
627  "[%::getObject() const] Object couldn't be found because index (%) is higher than number of objects (%).",
628  getName(), index, getSize());
629  return objects_[index];
630 }
631 
633 template<typename T>
635 {
636  return objects_.back();
637 }
638 
640 template<typename T>
642 {
643  return objects_.back();
644 }
645 
647 template<typename T>
649 {
650  return objects_.size();
651 }
652 
654 template<class T>
655 unsigned int BaseHandler<T>::getSize() const
656 {
657  return objects_.size();
658 }
659 
661 template<typename T>
663 {
664  return objects_.capacity();
665 }
666 
668 template<typename T>
669 void BaseHandler<T>::setStorageCapacity(const unsigned int N)
670 {
671  objects_.reserve(N);
672 }
673 
678 template<class T>
679 void BaseHandler<T>::resize(const unsigned int N, const T& obj)
680 {
681  //objects_.resize(N,obj); //doesn't work because the handler stores pointers only (data needs to be allocated);
682  while (getSize() < N)
683  copyAndAddObject(obj);
684  while (getSize() > N)
685  removeLastObject();
686 }
687 
689 template<typename T>
690 const typename std::vector<T*>::const_iterator BaseHandler<T>::begin() const
691 {
692  return objects_.begin();
693 }
694 
696 template<typename T>
697 const typename std::vector<T*>::iterator BaseHandler<T>::begin()
698 {
699  return objects_.begin();
700 }
701 
703 template<typename T>
704 const typename std::vector<T*>::const_iterator BaseHandler<T>::end() const
705 {
706  return objects_.end();
707 }
708 
710 template<typename T>
711 const typename std::vector<T*>::iterator BaseHandler<T>::end()
712 {
713  return objects_.end();
714 }
715 
717 template<typename T>
719 {
720  DPMBase_ = DPMBase;
721 }
722 
724 template<typename T>
726 {
727  return DPMBase_;
728 }
729 
731 template<typename T>
733 {
734  return DPMBase_;
735 }
736 
737 #endif
738 
std::string getName(int argc, char *argv[])
Definition: CombineParallelDataFiles.cpp:12
LL< Log::VERBOSE > VERBOSE
Verbose information.
Definition: Logger.cc:57
LL< Log::DEBUG > DEBUG
Debug information.
Definition: Logger.cc:58
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
LL< Log::ERROR > ERROR
Error log level.
Definition: Logger.cc:53
LL< Log::WARN > WARN
Warning log level.
Definition: Logger.cc:54
void addObject(CGHandler &cg, std::string coordinate)
Definition: MercuryCG.cpp:40
Container to store the pointers to all objects that one creates in a simulation.
Definition: BaseHandler.h:51
virtual void removeObject(unsigned const int index)
Removes an Object from the BaseHandler.
Definition: BaseHandler.h:472
DPMBase * DPMBase_
A pointer back to the DPMBase class.
Definition: BaseHandler.h:328
BaseHandler()
Default BaseHandler constructor, it creates an empty BaseHandler and assigns DPMBase_ to a null point...
Definition: BaseHandler.h:335
void setDPMBase(DPMBase *DPMBase)
Sets the problem that is solved using this handler.
Definition: BaseHandler.h:718
void read(std::istream &is)
Reads all objects from restart data.
Definition: BaseHandler.h:543
const std::vector< T * >::iterator end()
Gets the end of the iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:711
const T * getObject(const unsigned int id) const
Gets a constant pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:624
const T * getLastObject() const
Gets a constant pointer to the last Object in this BaseHandler.
Definition: BaseHandler.h:641
unsigned nextGroupId_
value of the next BaseObject::groupId_. Value increased by one each time a groupId is assigned....
Definition: BaseHandler.h:320
virtual unsigned int getNumberOfObjects() const
Gets the number of real Object in this BaseHandler. (i.e. no mpi or periodic particles)
Definition: BaseHandler.h:648
virtual std::string getName() const =0
Gets the name of this handler.
std::enable_if<!std::is_pointer< U >::value, U * >::type copyAndAddGhostObject(const U &object)
Creates a copy of a Object and adds it to the BaseHandler. This is one locally for inserting mpi part...
Definition: BaseHandler.h:399
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:390
std::vector< T * > objects_
The actual list of Object pointers.
Definition: BaseHandler.h:302
virtual void writeVTK() const
now empty function for writing VTK files.
Definition: BaseHandler.h:286
unsigned getNextGroupId()
Should be called each time you assign a groupId. Returns the value of nextGroupId_ and increases next...
Definition: BaseHandler.h:293
DPMBase * getDPMBase() const
Gets the problem that is solved using this handler and does not change the class.
Definition: BaseHandler.h:732
virtual void clear()
Empties the whole BaseHandler by removing all Objects and setting all other variables to 0.
Definition: BaseHandler.h:528
virtual void readAndAddObject(std::istream &is)=0
Reads Object into the BaseHandler from restart data.
void setStorageCapacity(const unsigned int N)
Sets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:669
virtual void addObject(T *object)
Adds a new Object to the BaseHandler.
Definition: BaseHandler.h:431
unsigned int getNextId()
Definition: BaseHandler.h:256
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
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
unsigned int getStorageCapacity() const
Gets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:662
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
void setId(T *object, unsigned int id)
Definition: BaseHandler.h:238
unsigned int getSize() const
Gets the size of the particleHandler (including mpi and periodic particles)
Definition: BaseHandler.h:655
void resize(const unsigned int N, const T &obj)
Resizes the container to contain N elements.
Definition: BaseHandler.h:679
void setNextId(unsigned int id)
Definition: BaseHandler.h:261
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
Definition: BaseHandler.h:725
void removeIf(const std::function< bool(T *)> cond)
Definition: BaseHandler.h:453
BaseHandler(const BaseHandler< T > &BH)
Constructor that copies the objects of the given handler into itself and sets other variables to 0/nu...
Definition: BaseHandler.h:350
const std::vector< T * >::iterator begin()
Gets the begin of the iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:697
unsigned int maxObjects_
An integer to keep track of the largest number of objects ever stored in this BaseHandler.
Definition: BaseHandler.h:308
std::vector< T * > getObjectsById(const unsigned int id)
Gets a vector of pointers to the objects with the specific id.
Definition: BaseHandler.h:593
virtual void addGhostObject(T *O)
Adds a new Object to the BaseHandler. called by the to avoid increasing the id.
Definition: BaseHandler.h:444
void copyContentsFromOtherHandler(const BaseHandler< T > &BH)
Function that copies the contents (vector of pointers, maxObject_, nextId_, DPMBase_) from one handle...
Definition: BaseHandler.h:367
void increaseId()
Definition: BaseHandler.h:251
unsigned int nextId_
identifier for next object created
Definition: BaseHandler.h:313
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
virtual ~BaseHandler()
Destructor, it destructs the BaseHandler and all Object it contains.
Definition: BaseHandler.h:359
T * getObjectById(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:565
void removeLastObject()
Removes the last Object from the BaseHandler.
Definition: BaseHandler.h:511
virtual void addExistingObject(T *O)
Adds an existing object to the BaseHandler without changing the id of the object.
Definition: BaseHandler.h:417
std::enable_if< std::is_pointer< U >::value, U >::type copyAndAddGhostObject(const U object)
Creates a copy of a Object and adds it to the BaseHandler. This is one locally for inserting mpi part...
Definition: BaseHandler.h:410
T * getLastObject()
Gets a pointer to the last Object in this BaseHandler.
Definition: BaseHandler.h:634
The DPMBase header includes quite a few header files, defining all the handlers, which are essential....
Definition: DPMBase.h:77
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
void getLineFromStringStream(std::istream &in, std::stringstream &out)
Reads a line from one stringstream into another, and prepares the latter for reading in.
Definition: StringHelpers.cc:62