Domain Class Referencefinal

The simulation can be subdivided into Domain's used in parallel code. More...

#include <Domain.h>

+ Inheritance diagram for Domain:

Public Member Functions

 Domain ()
 Default Domain constructor. More...
 
 Domain (std::vector< unsigned > globalMeshIndex)
 Constructs an empty domain with a globalMeshIndex. More...
 
 Domain (const Domain &d)
 Constructor that copies the domain range and rank from a given domain. More...
 
 ~Domain () override
 Destructor, destroys the domain. More...
 
void constructor ()
 contructor of a domain More...
 
virtual Domaincopy () const
 Function that creates a copy of this current domain, using the copy constructor. More...
 
void read (std::istream &is) override
 This function does nothing. More...
 
void write (std::ostream &os) const override
 This function does nothing. More...
 
std::string getName () const override
 Returns the name of the object. More...
 
void setRange (Direction direction, Mdouble min, Mdouble max)
 Sets the domain range in a given direction. More...
 
void setBounds (std::vector< double > domainLeft, std::vector< double > domainRight, bool computeMiddle)
 Sets the domain bounds. More...
 
std::vector< doublegetDomainMin ()
 Gets the minimum domain bounds. More...
 
std::vector< doublegetDomainMax ()
 Gets the maximum domain bounds. More...
 
int getRank ()
 Gets the rank associated with the assigned processorID. More...
 
void setRank (int rank)
 Sets the rank associated with the assigned processorID. More...
 
void setHandler (DomainHandler *handler)
 Sets the domainHandler. More...
 
DomainHandlergetHandler () const
 Gets the domainHandler. More...
 
int getGlobalIndex ()
 Gets the global index of the domain. More...
 
std::vector< unsignedgetGlobalMeshIndex ()
 Gets the global mesh index of the domain. More...
 
void setGlobalMeshIndex (std::vector< unsigned > globalMeshIndex)
 Sets the global mesh index of the domain. More...
 
void disableBoundary (unsigned localIndex)
 Disables a boundary of the domain with a neighbouring domain. More...
 
void disableBoundaries ()
 disables all domain boundaries that have no neighbour More...
 
std::vector< boolgetActiveBoundaryList ()
 Returns a list of boundaries that are active in mpi communication. More...
 
bool containsParticle (BaseParticle *particle, Mdouble offset=0.0)
 Check to see if a given particle is within the current domain. More...
 
bool isInGreaterDomain (BaseParticle *particle)
 Check to see if a given particle is in the current domain or in neighbouring communication zones. More...
 
bool isInInnerDomain (BaseParticle *particle)
 Check if the particle is in the current domain but not in the communication zone. More...
 
bool isInCommunicationZone (BaseParticle *particle)
 Check if the particle is in the communication zone of the current domain. More...
 
void createLookUpTable ()
 Create a look up table between local index system to global index system. More...
 
int getLocalIndex (int i, int j, int k)
 return the local index of a domain given local mesh indices i,j and k More...
 
int getLocalIndex (std::vector< int > localMeshIndex)
 return the local index of a domain given the localMeshIndex vector More...
 
std::vector< intgetLocalIndexInverse (int localMeshIndex)
 
BaseParticlefindParticleInList (unsigned int identification, std::vector< BaseParticle * > particleList)
 Searches for a particle with a specific id in a list of particles. More...
 
std::vector< intfindNearbyBoundaries (BaseParticle *particle, Mdouble offset=0)
 This function finds if a given particle is close to a given boundary. More...
 
bool inBoundary (BaseParticle *particle, int localIndex)
 
void addParticlesToLists (BaseParticle *particle, std::vector< std::vector< BaseParticle * > > &list)
 Function that adds the particles to the appropriate boundary list. More...
 
void findNewMPIParticles (const ParticleHandler &particleHandler)
 Function that finds new particles in the particle handler that should be added to the communication lists. More...
 
void findNewMPIParticle (BaseParticle *particle)
 Function that check if a given particle should be added to the communication lists. More...
 
bool isInNewBoundaryParticleList (BaseParticle *object, int localIndex) const
 
void findNewMPIInteractions ()
 Finds interactions that have to be send over to another domain. More...
 
void collectBoundaryParticleData (int localIndex)
 collects the data of a particle that has to be communicated to other processors More...
 
void collectInteractionData (int localIndex)
 Collects the data of an interaction that has to be communicated to other processors. More...
 
void processReceivedBoundaryParticleData (unsigned index, std::vector< BaseParticle * > &newParticles)
 Function that copies the mpi data format of a base particle to a real particle and adds it to the particleHandler. More...
 
void processSentBoundaryParticles (unsigned index)
 Bookkeep the newly send particles. More...
 
void processReceivedInteractionData (unsigned index, std::vector< BaseParticle * > &newParticles)
 Processes the received interactions from newly added mpi particles
More...
 
void debugInformation ()
 
void sendAndReceiveCount (MercuryMPITag tag, unsigned &countReceive, unsigned &countSend, unsigned localIndexNeighbour)
 A symmetric communication between two domains exchanging a send/receive count. More...
 
void prepareBoundaryDataTransmission ()
 Prepares the MPI transmission of particle and interaction data from particles in particleHandler. More...
 
void prepareBoundaryDataTransmission (BaseParticle *particle)
 Prepares the MPI transmission of a single particle and its interactions. More...
 
void performBoundaryDataTransmission ()
 Collects data to be transmitted and then performs the transmission of the data. More...
 
void finaliseBoundaryDataTransmission ()
 This function processes the transmitted data. More...
 
void updateParticles (std::set< BaseParticle * > &ghostParticlesToBeDeleted)
 This step updates all communication lists and particles in the communication zone. More...
 
void updateParticlePosition (int localIndex)
 Updates the position of particles which are flagged as MPIParticles. More...
 
void updateParticleVelocity (int localIndex)
 Updates the velocity of particles which are flagged as MPIParticles. More...
 
void preparePositionAndVelocityUpdate ()
 Function that sends particle position and velocity data for ghost particles to other processors. More...
 
void finalisePositionAndVelocityUpdate (std::set< BaseParticle * > &ghostParticlesToBeDeleted)
 processes position and velocity data for ghost particles More...
 
void prepareVelocityUpdate ()
 Function that sends particle velocity data for ghost particles. More...
 
void finaliseVelocityUpdate ()
 Processes particle velocity data for ghost particles. More...
 
template<typename T >
void sendAndReceiveMPIData (MercuryMPITag tag, MercuryMPIType type, T *receiveData, unsigned receiveCount, T *sendData, unsigned sendCount, unsigned localIndexNeighbour)
 Function that sends transmissionData/positionData/velocityData to other processors. More...
 
void addNewParticles ()
 Initialises the MPIParticles by communicating newly found particles. More...
 
void addParticle (BaseParticle *particle)
 Initialises a single particle which is added during the simulation. More...
 
void updateStatus (std::set< BaseParticle * > &ghostParticlesToBeDeleted)
 Updates particles that are not in the current domain and communicates newly added particles. More...
 
void updateVelocity ()
 Updates MPI particle velocity at the half-time step. More...
 
unsigned int getNumberOfMPIParticles ()
 Obtains the number of particles in the particleHandler that are MPIParticles. More...
 
unsigned int getNumberOfTrueMPIParticles ()
 Obtains the number of particles in the particleHandler that are MPIParticles, but NOT periodic particles. More...
 
void flushParticles (std::set< BaseParticle * > &toBeDeletedList)
 Particles that are going to be deleted from the simulation are flushed out of the communication boundaries. More...
 
void flushParticlesFromList (std::vector< BaseParticle * > &list, std::set< BaseParticle * > &toBeDeletedList)
 Particles that are going to be deleted from the simulation are flushed out of a give communication boundary. More...
 
Vec3D getMiddle () const
 Gives the middle of the domain. More...
 
void cleanCommunicationLists ()
 Removes nullptrs from boundaryParticleList_ and boundaryParticleListNeighbour_. More...
 
void cleanCommunicationList (std::vector< BaseParticle * > &list)
 Removes nullptr's from a given particle list. More...
 
- Public Member Functions inherited from BaseObject
 BaseObject ()=default
 Default constructor. More...
 
 BaseObject (const BaseObject &p)=default
 Copy constructor, copies all the objects BaseObject contains. More...
 
virtual ~BaseObject ()=default
 virtual destructor More...
 
virtual void moveInHandler (unsigned int index)
 Except that it is virtual, it does the same thing as setIndex() does. More...
 
void setIndex (unsigned int index)
 Allows one to assign an index to an object in the handler/container. More...
 
void setId (unsigned long id)
 Assigns a unique identifier to each object in the handler (container) which remains constant even after the object is deleted from the container/handler. More...
 
unsigned int getIndex () const
 Returns the index of the object in the handler. More...
 
unsigned int getId () const
 Returns the unique identifier of any particular object. More...
 
void setGroupId (unsigned groupId)
 
unsigned getGroupId () const
 

Private Attributes

DomainHandlerdomainHandler_
 Pointer to the domain's DomainHandler container. More...
 
std::vector< doubledomainMin_
 Minimum domain bounds in the x,y and z direction. More...
 
std::vector< doubledomainMax_
 Maximum domain bounds in the x,y and z direction. More...
 
Vec3D middle_
 Middle of the closed domain. More...
 
int globalIndex_
 Global index of the domain in the mesh. More...
 
std::vector< unsignedglobalMeshIndex_
 Vector containing the global mesh indices i,j,k. More...
 
std::vector< intlocalIndexToGlobalIndexTable_
 look-up table to get the global index given a local domain index More...
 
std::vector< intlocalIndexToProcessorList_
 look-up table to get the processor of the domain given a local domain index More...
 
std::vector< boolactiveBoundaryList_
 A list of flags corresponding to an inactive or active boundary. More...
 
std::vector< intboundaryList_
 A list of indices of all the active boundaries. More...
 
std::vector< std::vector< BaseParticle * > > boundaryParticleList_
 A list of boundary particles in the communication zone that are ghost particles on other domains. More...
 
std::vector< std::vector< BaseParticle * > > boundaryParticleListNeighbour_
 a list of ghost particles on the current domain, which are real on the neighbour domain More...
 
std::vector< std::vector< BaseParticle * > > newBoundaryParticleList_
 Array that queues particles that need to be transmitted. More...
 
std::vector< std::vector< BaseInteraction * > > newInteractionList_
 Array that queues interactions that need to be transmitted. More...
 
std::vector< unsignednumberOfParticlesSend_
 Counter that keeps track of the number of particles that are being send to other domains. More...
 
std::vector< unsignednumberOfParticlesReceive_
 Counter that keeps track of the number of particles that are being received by this domain. More...
 
std::vector< unsignednumNewInteractionsSend_
 Counter that keeps track of the number of interactions that are being send to other domains. More...
 
std::vector< unsignednumNewInteractionsReceive_
 Counter that keeps track of the number of interactions that are being received by this domain. More...
 
std::vector< std::vector< MPIParticle > > boundaryParticleDataSend_
 Container that keeps a list of MPIParticles that are being send to other domains. More...
 
std::vector< std::vector< MPIParticle > > boundaryParticleDataReceive_
 Container that keeps a list of MPIParticles that are being received by this domain. More...
 
std::vector< std::vector< MPIParticlePosition > > updatePositionDataSend_
 Container that keeps a list of MPIParticlePositions that are being send to other domains. More...
 
std::vector< std::vector< MPIParticlePosition > > updatePositionDataReceive_
 Container that keeps a list of MPIParticlePositions that are being received by this domain. More...
 
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataSend_
 Container that keeps a list of MPIParticleVelocities that are being send to other domains. More...
 
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataReceive_
 Container that keeps a list of MPIParticleVelocities that are being received by this domain. More...
 
std::vector< void * > interactionDataSend_
 Container that keeps a void array of all the interaction data that are being send to other domains, interpretation is done by the interaction handler. More...
 
std::vector< void * > interactionDataReceive_
 Container that keeps a void array of all the interaction data that is being received by this domain, interpretation is done by the interaction handler. More...
 
int rank_
 Rank of the domain which identifies to which processor it belongs. More...
 

Detailed Description

The simulation can be subdivided into Domain's used in parallel code.

The domain class defines a region in the simulation domain, given by a min vector and a max vector. The domain also as a processorID assigned to it. It has a check to see whether a given particle is in the domain or not.

Constructor & Destructor Documentation

◆ Domain() [1/3]

Domain::Domain ( )

Default Domain constructor.

Constructs an empty domain.

Constructor of the domain class. It creates a domain with infinite bounds and no processor or domainHandler assigned to it and initialises all communication lists

28 {
29  constructor();
30 #ifdef DEBUG_CONSTRUCTOR
31  std::cout<<"Domain::Domain() finished"<<std::endl;
32 #endif
33 }
void constructor()
contructor of a domain
Definition: Domain.cc:112

References constructor().

Referenced by copy().

◆ Domain() [2/3]

Domain::Domain ( std::vector< unsigned globalMeshIndex)
explicit

Constructs an empty domain with a globalMeshIndex.

Constructor of the domain class. It creates a domain with infinite bounds and no processor or domainHandler assigned to it and initialises all communication lists

41  : globalMeshIndex_(std::move(globalMeshIndex))
42 {
43  constructor();
44 #ifdef DEBUG_CONSTRUCTOR
45  std::cout<<"Domain::Domain() finished"<<std::endl;
46 #endif
47 }
std::vector< unsigned > globalMeshIndex_
Vector containing the global mesh indices i,j,k.
Definition: Domain.h:452

References constructor().

◆ Domain() [3/3]

Domain::Domain ( const Domain b)

Constructor that copies the domain range and rank from a given domain.

Copies a domain.

Parameters
[in]PHThe domain that has to be copied.

This constructor copies all the private variables of the current domain into the input domain.

56  : BaseObject(b)
57 {
58  rank_ = b.rank_;
59  domainHandler_ = b.domainHandler_;
60  domainMin_ = b.domainMin_;
61  domainMax_ = b.domainMax_;
62  globalMeshIndex_ = b.globalMeshIndex_;
63  middle_ = b.middle_;
64 
65  //A cube has 3^3=27 neighbours
66  unsigned long numberOfNeighbours = 27;
67 
68  //Create all lists
69  localIndexToGlobalIndexTable_ = std::vector<int>(numberOfNeighbours);
70  localIndexToProcessorList_ = std::vector<int>(numberOfNeighbours);
71  boundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours, std::vector<BaseParticle*>(0));
72  boundaryParticleListNeighbour_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours,
73  std::vector<BaseParticle*>(0));
74  newBoundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours,
75  std::vector<BaseParticle*>(0));
76  newInteractionList_ = std::vector<std::vector<BaseInteraction*> >(numberOfNeighbours,
77  std::vector<BaseInteraction*>(0));
78  numberOfParticlesSend_ = std::vector<unsigned>(numberOfNeighbours);
79  numberOfParticlesReceive_ = std::vector<unsigned>(numberOfNeighbours);
80  numNewInteractionsSend_ = std::vector<unsigned>(numberOfNeighbours);
81  numNewInteractionsReceive_ = std::vector<unsigned>(numberOfNeighbours);
82  boundaryParticleDataSend_ = std::vector<std::vector<MPIParticle> >(numberOfNeighbours);
83  boundaryParticleDataReceive_ = std::vector<std::vector<MPIParticle> >(numberOfNeighbours);
84  updatePositionDataSend_ = std::vector<std::vector<MPIParticlePosition> >(numberOfNeighbours);
85  updatePositionDataReceive_ = std::vector<std::vector<MPIParticlePosition> >(numberOfNeighbours);
86  updateVelocityDataSend_ = std::vector<std::vector<MPIParticleVelocity> >(numberOfNeighbours);
87  updateVelocityDataReceive_ = std::vector<std::vector<MPIParticleVelocity> >(numberOfNeighbours);
88  interactionDataSend_ = std::vector<void*>(numberOfNeighbours);
89  interactionDataReceive_ = std::vector<void*>(numberOfNeighbours);
90  activeBoundaryList_ = std::vector<bool>(numberOfNeighbours, true);
91  boundaryList_ = std::vector<int>(0);
92 #ifdef DEBUG_CONSTRUCTOR
93  std::cout<<"Domain::Domain(const Domain &b) finished"<<std::endl;
94 #endif
95 }
Scalar * b
Definition: benchVecAdd.cpp:17
BaseObject()=default
Default constructor.
std::vector< unsigned > numberOfParticlesReceive_
Counter that keeps track of the number of particles that are being received by this domain.
Definition: Domain.h:505
std::vector< void * > interactionDataReceive_
Container that keeps a void array of all the interaction data that is being received by this domain,...
Definition: Domain.h:555
std::vector< unsigned > numNewInteractionsSend_
Counter that keeps track of the number of interactions that are being send to other domains.
Definition: Domain.h:510
std::vector< bool > activeBoundaryList_
A list of flags corresponding to an inactive or active boundary.
Definition: Domain.h:469
DomainHandler * domainHandler_
Pointer to the domain's DomainHandler container.
Definition: Domain.h:426
std::vector< std::vector< MPIParticle > > boundaryParticleDataSend_
Container that keeps a list of MPIParticles that are being send to other domains.
Definition: Domain.h:520
std::vector< std::vector< BaseInteraction * > > newInteractionList_
Array that queues interactions that need to be transmitted.
Definition: Domain.h:495
std::vector< std::vector< MPIParticle > > boundaryParticleDataReceive_
Container that keeps a list of MPIParticles that are being received by this domain.
Definition: Domain.h:525
std::vector< std::vector< BaseParticle * > > boundaryParticleListNeighbour_
a list of ghost particles on the current domain, which are real on the neighbour domain
Definition: Domain.h:485
std::vector< std::vector< BaseParticle * > > boundaryParticleList_
A list of boundary particles in the communication zone that are ghost particles on other domains.
Definition: Domain.h:480
int rank_
Rank of the domain which identifies to which processor it belongs.
Definition: Domain.h:560
std::vector< unsigned > numberOfParticlesSend_
Counter that keeps track of the number of particles that are being send to other domains.
Definition: Domain.h:500
std::vector< double > domainMin_
Minimum domain bounds in the x,y and z direction.
Definition: Domain.h:431
std::vector< int > localIndexToProcessorList_
look-up table to get the processor of the domain given a local domain index
Definition: Domain.h:464
std::vector< std::vector< MPIParticlePosition > > updatePositionDataReceive_
Container that keeps a list of MPIParticlePositions that are being received by this domain.
Definition: Domain.h:535
std::vector< double > domainMax_
Maximum domain bounds in the x,y and z direction.
Definition: Domain.h:436
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataSend_
Container that keeps a list of MPIParticleVelocities that are being send to other domains.
Definition: Domain.h:540
std::vector< int > localIndexToGlobalIndexTable_
look-up table to get the global index given a local domain index
Definition: Domain.h:458
Vec3D middle_
Middle of the closed domain.
Definition: Domain.h:441
std::vector< unsigned > numNewInteractionsReceive_
Counter that keeps track of the number of interactions that are being received by this domain.
Definition: Domain.h:515
std::vector< void * > interactionDataSend_
Container that keeps a void array of all the interaction data that are being send to other domains,...
Definition: Domain.h:550
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataReceive_
Container that keeps a list of MPIParticleVelocities that are being received by this domain.
Definition: Domain.h:545
std::vector< std::vector< BaseParticle * > > newBoundaryParticleList_
Array that queues particles that need to be transmitted.
Definition: Domain.h:490
std::vector< std::vector< MPIParticlePosition > > updatePositionDataSend_
Container that keeps a list of MPIParticlePositions that are being send to other domains.
Definition: Domain.h:530
std::vector< int > boundaryList_
A list of indices of all the active boundaries.
Definition: Domain.h:475

References activeBoundaryList_, b, boundaryList_, boundaryParticleDataReceive_, boundaryParticleDataSend_, boundaryParticleList_, boundaryParticleListNeighbour_, domainHandler_, domainMax_, domainMin_, globalMeshIndex_, interactionDataReceive_, interactionDataSend_, localIndexToGlobalIndexTable_, localIndexToProcessorList_, middle_, newBoundaryParticleList_, newInteractionList_, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, rank_, updatePositionDataReceive_, updatePositionDataSend_, updateVelocityDataReceive_, and updateVelocityDataSend_.

◆ ~Domain()

Domain::~Domain ( )
override

Destructor, destroys the domain.

Destructor

101 {
102 #ifdef DEBUG_DESTRUCTOR
103  std::cout << "Domain::~Domain() finished"<<std::endl;
104 #endif
105 }

Member Function Documentation

◆ addNewParticles()

void Domain::addNewParticles ( )

Initialises the MPIParticles by communicating newly found particles.

Adds new MPI ghost particles to the simulation. This is done in a three stage process where first the particles are located that generate ghosts, secondly their data is transmitted to the correct processor and thirdly that data is then used to create ghost particles.

1568 {
1569  //Step 1: For every MPIDomain boundary, create a list of particles that have to be transmitted
1570  //queue send and receive instructions for the number of particles
1573 
1574  //Step 2: queue send and receive of data
1577 
1578  //Step 3: Add the received particles to the particleHandler of the current domain
1580 }
void performBoundaryDataTransmission()
Collects data to be transmitted and then performs the transmission of the data.
Definition: Domain.cc:1200
void prepareBoundaryDataTransmission()
Prepares the MPI transmission of particle and interaction data from particles in particleHandler.
Definition: Domain.cc:1125
void finaliseBoundaryDataTransmission()
This function processes the transmitted data.
Definition: Domain.cc:1241
static MPIContainer & Instance()
fetch the instance to be used for communication
Definition: MpiContainer.h:113
void sync()
Process all pending asynchronous communication requests before continuing.
Definition: MpiContainer.h:131

References finaliseBoundaryDataTransmission(), MPIContainer::Instance(), performBoundaryDataTransmission(), prepareBoundaryDataTransmission(), and MPIContainer::sync().

Referenced by DomainHandler::addNewParticles().

◆ addParticle()

void Domain::addParticle ( BaseParticle particle)

Initialises a single particle which is added during the simulation.

Initialises a single particle which was added by the user after the domain creation.

This function is used when a single particle is added during the simulation In that case it has to be added to the mpi domains manually using this function. Examples are insertion boundaries that occasionally add particles to the domain

Parameters
[in]particleThe single particle that has to be inserted into the domain
1590 {
1591  //Step1: check if the particle has to be sent to other processors
1594 
1595  //Step2: queue send and receive data. Note for an inserted particle, no interactions should be required
1598 
1599  //Step3: Add the received particles to the particleHandler of the current domain
1602 }

References finaliseBoundaryDataTransmission(), MPIContainer::Instance(), performBoundaryDataTransmission(), prepareBoundaryDataTransmission(), and MPIContainer::sync().

Referenced by DPMBase::insertGhostParticle().

◆ addParticlesToLists()

void Domain::addParticlesToLists ( BaseParticle particle,
std::vector< std::vector< BaseParticle * > > &  list 
)

Function that adds the particles to the appropriate boundary list.

Function that adds the particles to the appropriate boundary lists.

This function computes the complexity of the particle. The complexity is defined by the number of boundaries the particle is close-by. Depending on this complexity value the particle has to be added to different boundary lists.

Parameters
[in]particlepointer to base particle
[in,out]lista list of lists of particles which the particle might be added to
681 {
682  std::vector<int> boundaryIndex = findNearbyBoundaries(particle);
683 
684  //Compute and set complexity of the particle
685  unsigned int complexity = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
686  unsigned int list_complexity = 0;
687  for (int d = 0; d < 3; d++) //Loop over all directions
688  {
689  list_complexity += std::abs(boundaryIndex[d]);
690  }
691  particle->setCommunicationComplexity(complexity);
692  //particle->setCommunicationComplexity(list_complexity);
693 
694  //Based on the complexity of the particle, add it to the appropriate list
695  switch (list_complexity)
696  {
697  //The particle is not close at all
698  case 0:
699  break;
700  //The particle is close to one side
701  // 1 side contribution
702  case 1 :
703  //Add the side contribution
704  list[getLocalIndex(boundaryIndex)].push_back(particle);
705  break;
706  //The particle is close to two neighbouring directions
707  //2 side and 1 rib contribution
708  case 2 :
709  {
710  //Add the two side contributions
711  for (int d = 0; d < 3; d++)
712  {
713  std::vector<int> localMeshIndex = {0, 0, 0};
714  localMeshIndex[d] = boundaryIndex[d];
715  //Avoid adding the particle in the wrong direction by excluding localMeshIndex[d] = 0
716  if (localMeshIndex[d] != 0)
717  {
718  list[getLocalIndex(localMeshIndex)].push_back(particle);
719  }
720  }
721  }
722  //Add the rib contribution
723  list[getLocalIndex(boundaryIndex)].push_back(particle);
724  break;
725 
726  //The particle is close to three neighbouring directions
727  // 3 side, 3 rib and 1 corner contribution
728  case 3 :
729  {
730  //Add the three side contributions
731  for (int d = 0; d < 3; d++)
732  {
733  std::vector<int> localMeshIndex = {0, 0, 0};
734  //Reset index vector
735  localMeshIndex[d] = boundaryIndex[d];
736  list[getLocalIndex(localMeshIndex)].push_back(particle);
737  }
738 
739  //Add the three rib contributions
740  for (int d = 0; d < 3; d++)
741  {
742  std::vector<int> localMeshIndex = boundaryIndex;
743  //All rib boundary indices are given by the boundaryIndex and setting one of the components to zero
744  localMeshIndex[d] = 0;
745  list[getLocalIndex(localMeshIndex)].push_back(particle);
746  }
747  }
748 
749  //Add the corner contribution
750  list[getLocalIndex(boundaryIndex)].push_back(particle);
751  break;
752 
753  default :
754  logger(INFO, "boundaryIndex : %,%,% | list_complexity: %", boundaryIndex[0], boundaryIndex[1], boundaryIndex[2],
755  list_complexity);
756  logger(ERROR, "Particle is in contact with the wrong number of boundaries");
757  break;
758  }
759 }
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
Logger< MERCURYDPM_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here.
@ INFO
@ ERROR
void setCommunicationComplexity(unsigned complexity)
Set the communication complexity of the particle.
Definition: BaseParticle.cc:179
std::vector< int > findNearbyBoundaries(BaseParticle *particle, Mdouble offset=0)
This function finds if a given particle is close to a given boundary.
Definition: Domain.cc:533
int getLocalIndex(int i, int j, int k)
return the local index of a domain given local mesh indices i,j and k
Definition: Domain.cc:477
default
Definition: calibrate.py:45

References abs(), calibrate::default, ERROR, findNearbyBoundaries(), getLocalIndex(), INFO, logger, and BaseParticle::setCommunicationComplexity().

Referenced by findNewMPIParticle().

◆ cleanCommunicationList()

void Domain::cleanCommunicationList ( std::vector< BaseParticle * > &  list)

Removes nullptr's from a given particle list.

Removes nullptrs from a list of base particles efficiently by replacing the last entry to an empty nullptr space.m

Parameters
[in]listThe list that needs to be cleansed from nullptrs
1737 {
1738  for (int i = 0; i < list.size(); i++)
1739  {
1740  if (list[i] == nullptr)
1741  {
1742  list[i] = list.back();
1743  list.pop_back();
1744  i--;
1745  }
1746  }
1747 }
int i
Definition: BiCGSTAB_step_by_step.cpp:9

References i.

Referenced by cleanCommunicationLists().

◆ cleanCommunicationLists()

void Domain::cleanCommunicationLists ( )

Removes nullptrs from boundaryParticleList_ and boundaryParticleListNeighbour_.

After particles have been updated, the communication lists contains nullptrs, remove these from the boundaryParticleList and boundaryParticleListNeighbour

1722 {
1723  //For all active boundaries
1724  for (int i : boundaryList_)
1725  {
1728  }
1729 }
void cleanCommunicationList(std::vector< BaseParticle * > &list)
Removes nullptr's from a given particle list.
Definition: Domain.cc:1736

References boundaryList_, boundaryParticleList_, boundaryParticleListNeighbour_, cleanCommunicationList(), and i.

Referenced by DPMBase::checkInteractionWithBoundaries(), PeriodicBoundaryHandler::clearCommunicationLists(), and DPMBase::deleteGhostParticles().

◆ collectBoundaryParticleData()

void Domain::collectBoundaryParticleData ( int  localIndex)

collects the data of a particle that has to be communicated to other processors

collects the data of a particles that has to be communicated to other processors

Only the relevant data of a baseParticle is being send to other processors, therefore this function collects the relevant data and puts it in a format compatible with data transmission

Parameters
[in]localIndexthe local index of a boundary
889 {
890  //For all particles
891  for (BaseParticle* particle : newBoundaryParticleList_[localIndex])
892  {
893  //Add the data to the transmission list
894  boundaryParticleDataSend_[localIndex].push_back(copyDataFromParticleToMPIParticle(particle));
895  }
896 }
MPIParticle copyDataFromParticleToMPIParticle(BaseParticle *p)
Copies data from a NonSphericalParticle to an MPIParticle class and returns this.
Definition: MpiDataClass.cc:103
Definition: BaseParticle.h:33

References boundaryParticleDataSend_, copyDataFromParticleToMPIParticle(), and newBoundaryParticleList_.

Referenced by performBoundaryDataTransmission().

◆ collectInteractionData()

void Domain::collectInteractionData ( int  localIndex)

Collects the data of an interaction that has to be communicated to other processors.

Interactions have to be reformatted in an MPI-suitable format to transmit over to other processors

Parameters
[in]localIndexThe local index of a boundary
904 {
905  //Copy interactions to the data array
906  unsigned int indexInteraction = 0;
907  for (BaseInteraction* interaction : newInteractionList_[localIndex])
908  {
909  interaction->getMPIInteraction(interactionDataSend_[localIndex], indexInteraction);
910  indexInteraction++;
911  }
912 }
Stores information about interactions between two interactable objects; often particles but could be ...
Definition: BaseInteraction.h:39

References interactionDataSend_, and newInteractionList_.

Referenced by performBoundaryDataTransmission().

◆ constructor()

void Domain::constructor ( )

contructor of a domain

constructs the domain

the boundaries are set to infinity, no processor is assigned. all lists that require a full 3D domain element to function are created

113 {
115  domainHandler_ = nullptr;
118 
119  //A cube has 3^3=27 neighbours
120  int numberOfNeighbours = 27;
121 
122  //Create all lists
123  localIndexToGlobalIndexTable_ = std::vector<int>(numberOfNeighbours);
124  localIndexToProcessorList_ = std::vector<int>(numberOfNeighbours);
125  boundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours, std::vector<BaseParticle*>(0));
126  boundaryParticleListNeighbour_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours,
127  std::vector<BaseParticle*>(0));
128  newBoundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours,
129  std::vector<BaseParticle*>(0));
130  newInteractionList_ = std::vector<std::vector<BaseInteraction*> >(numberOfNeighbours,
131  std::vector<BaseInteraction*>(0));
132  numberOfParticlesSend_ = std::vector<unsigned>(numberOfNeighbours);
133  numberOfParticlesReceive_ = std::vector<unsigned>(numberOfNeighbours);
134  numNewInteractionsSend_ = std::vector<unsigned>(numberOfNeighbours);
135  numNewInteractionsReceive_ = std::vector<unsigned>(numberOfNeighbours);
136  boundaryParticleDataSend_ = std::vector<std::vector<MPIParticle> >(numberOfNeighbours);
137  boundaryParticleDataReceive_ = std::vector<std::vector<MPIParticle> >(numberOfNeighbours);
138  updatePositionDataSend_ = std::vector<std::vector<MPIParticlePosition> >(numberOfNeighbours);
139  updatePositionDataReceive_ = std::vector<std::vector<MPIParticlePosition> >(numberOfNeighbours);
140  updateVelocityDataSend_ = std::vector<std::vector<MPIParticleVelocity> >(numberOfNeighbours);
141  updateVelocityDataReceive_ = std::vector<std::vector<MPIParticleVelocity> >(numberOfNeighbours);
142  interactionDataSend_ = std::vector<void*>(numberOfNeighbours);
143  interactionDataReceive_ = std::vector<void*>(numberOfNeighbours);
144  activeBoundaryList_ = std::vector<bool>(numberOfNeighbours, true);
145  boundaryList_ = std::vector<int>(0);
146 }
const Mdouble inf
Definition: GeneralDefine.h:23
const int intMax
Definition: GeneralDefine.h:24

References activeBoundaryList_, boundaryList_, boundaryParticleDataReceive_, boundaryParticleDataSend_, boundaryParticleList_, boundaryParticleListNeighbour_, domainHandler_, domainMax_, domainMin_, constants::inf, interactionDataReceive_, interactionDataSend_, constants::intMax, localIndexToGlobalIndexTable_, localIndexToProcessorList_, newBoundaryParticleList_, newInteractionList_, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, rank_, updatePositionDataReceive_, updatePositionDataSend_, updateVelocityDataReceive_, and updateVelocityDataSend_.

Referenced by Domain().

◆ containsParticle()

bool Domain::containsParticle ( BaseParticle particle,
Mdouble  offset = 0.0 
)

Check to see if a given particle is within the current domain.

Checks if a particle is in the domain.

Checks if the particle is in the domain, but with an offset. this offset is set to zero standard

Parameters
[in]particlePointer to a particle
[in]offsetoffset from the domain boundary
Returns
True if the particle is in the domain. False if it is outside
380 {
381  for (unsigned i = 0; i < 3; i++)
382  {
383  if (!(((domainMin_[i] + offset) < particle->getPosition().getComponent(i))
384  &&
385  ((domainMax_[i] - offset) >= particle->getPosition().getComponent(i)))
386  )
387  {
388  return false;
389  }
390  }
391  return true;
392 }
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:197
Mdouble getComponent(int index) const
Returns the requested component of this Vec3D.
Definition: Vector.cc:174

References domainMax_, domainMin_, Vec3D::getComponent(), BaseInteractable::getPosition(), and i.

Referenced by isInCommunicationZone(), isInGreaterDomain(), isInInnerDomain(), prepareBoundaryDataTransmission(), and updateParticles().

◆ copy()

Domain * Domain::copy ( ) const
virtual

Function that creates a copy of this current domain, using the copy constructor.

Copy method.

Uses copy constructor to create a copy on the heap. Useful for polymorphism.

Returns
pointer to the domain's copy
155 {
156  return new Domain(*this);
157 }
Domain()
Default Domain constructor.
Definition: Domain.cc:27

References Domain().

◆ createLookUpTable()

void Domain::createLookUpTable ( )

Create a look up table between local index system to global index system.

Function that creates a lookup table from the local index system to the global index system

431 {
432  int localIndex;
433  int globalIndex;
434  //Get the global decomposition vector, (nx,ny,nz) and compute the mesh multipliers: (1,nx,nx*ny)
435  std::vector<unsigned> numberOfDomains = domainHandler_->getNumberOfDomains();
436  std::vector<unsigned> globalMeshMultiplier = {1,
437  numberOfDomains[Direction::XAXIS],
438  numberOfDomains[Direction::XAXIS] *
439  numberOfDomains[Direction::YAXIS]};
440 
441  //Compute the globalIndex of this domain
443  globalMeshMultiplier[Direction::YAXIS] * globalMeshIndex_[Direction::YAXIS] +
444  globalMeshMultiplier[Direction::ZAXIS] * globalMeshIndex_[Direction::ZAXIS];
445 
446  //Create the lookup table from localIndex to globalIndex of the neighbours
447  for (int i = -1; i < 2; i++)
448  {
449  for (int j = -1; j < 2; j++)
450  {
451  for (int k = -1; k < 2; k++)
452  {
453  //Get the local index
454  localIndex = i + 3 * j + 9 * k + 13;
455  //Compute the global index
456  globalIndex = globalMeshMultiplier[Direction::XAXIS] * (globalMeshIndex_[Direction::XAXIS] + i) +
457  globalMeshMultiplier[Direction::YAXIS] * (globalMeshIndex_[Direction::YAXIS] + j) +
458  globalMeshMultiplier[Direction::ZAXIS] * (globalMeshIndex_[Direction::ZAXIS] + k);
459  //Fill in the look-up table
460  localIndexToGlobalIndexTable_[localIndex] = globalIndex;
461  }
462  }
463  }
464  //Create the lookup table from localIndex to processorRank
467 }
@ YAXIS
Definition: GeneralDefine.h:57
@ XAXIS
Definition: GeneralDefine.h:57
@ ZAXIS
Definition: GeneralDefine.h:57
std::vector< unsigned > getNumberOfDomains()
Gets the number of domains in the domain handler.
Definition: DomainHandler.cc:265
int globalIndex_
Global index of the domain in the mesh.
Definition: Domain.h:447
char char char int int * k
Definition: level2_impl.h:374
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References domainHandler_, DomainHandler::getNumberOfDomains(), globalIndex_, globalMeshIndex_, i, j, k, localIndexToGlobalIndexTable_, localIndexToProcessorList_, rank_, XAXIS, YAXIS, and ZAXIS.

◆ debugInformation()

void Domain::debugInformation ( )
1075  {
1076  std::stringstream s;
1077  std::stringstream m;
1078  for (auto p : getHandler()->getDPMBase()->particleHandler) {
1079  if (p->isMPIParticle())
1080  m << std::setw(4) << p->getId();
1081  else
1082  s << std::setw(4) << p->getId();
1083  }
1084  logger(INFO,"Particles %, MPI %",s.str(),m.str());
1085 }
float * p
Definition: Tutorial_Map_using.cpp:9
DomainHandler * getHandler() const
Gets the domainHandler.
Definition: Domain.cc:1557
RealScalar s
Definition: level1_cplx_impl.h:130
int * m
Definition: level2_cplx_impl.h:294

References getHandler(), INFO, logger, m, p, and s.

◆ disableBoundaries()

void Domain::disableBoundaries ( )

disables all domain boundaries that have no neighbour

This function can only disable a square mesh. If you want to make a concave mesh then this function has to be adapted, especially for the case when the numberOfDomains[d] = 1.

577 {
578  std::vector<unsigned> numberOfDomains = domainHandler_->getNumberOfDomains();
579  std::vector<int> localMeshIndex(3);
580  int localIndex;
581 
582  //disable own list
583  activeBoundaryList_[13] = false;
584 
585  //Special case when numberOfDomains[d] = 1 -> disable all d direction boundaries
586  for (unsigned d = 0; d < 3; d++) //Loop over all dimensions
587  {
588  //If there is only one domain in the d-direction, take action
589  if (numberOfDomains[d] == 1)
590  {
591  //Loop over all localIndices
592  for (int i = -1; i < 2; i++)
593  {
594  localMeshIndex[Direction::XAXIS] = i;
595  for (int j = -1; j < 2; j++)
596  {
597  localMeshIndex[Direction::YAXIS] = j;
598  for (int k = -1; k < 2; k++)
599  {
600  localMeshIndex[Direction::ZAXIS] = k;
601  //Disable all boundaries that are not in the "middle" of the mesh in the d-direction
602  // i.e. a localMeshIndex[d] = -1 is a neighbour in the d-direction, however there is only one
603  // element in that direction so it can't be a real neighbour.
604  if (localMeshIndex[d] != 0)
605  {
606  //Disable the boundary
607  localIndex = getLocalIndex(localMeshIndex);
608  activeBoundaryList_[localIndex] = false;
609  }
610  }
611  }
612  }
613  }
614  }
615 
616  //Compute the boundaryIndex for all other cases where numberOfDomains is larger than 1
617  std::vector<int> boundaryIndex(3);
618  for (int d = 0; d < 3; d++)
619  {
620  //Check if the domain is on the simulationDomainMin boundary
621  if (globalMeshIndex_[d] == 0)
622  {
623  //Update boundary index
624  boundaryIndex[d] = -1;
625  }
626  //Check if the domain is on the simulationDomainMax boundary
627  else if (globalMeshIndex_[d] == (numberOfDomains[d] - 1))
628  {
629  //Update boundary index
630  boundaryIndex[d] = 1;
631  }
632  }
633 
634  //Disable the boundaries that are on the edge of the simulation domain
635  for (int d = 0; d < 3; d++)
636  {
637  //If boundary is on the edge of the simulation domain
638  if (boundaryIndex[d] != 0)
639  {
640  //Loop over all local indices
641  for (int i = -1; i < 2; i++)
642  {
643  for (int j = -1; j < 2; j++)
644  {
645  for (int k = -1; k < 2; k++)
646  {
647  localMeshIndex = {i, j, k};
648  //Set the localMeshIndex to the boundaryIndex in the d-direction
649  //Since we are only interested in the domains on this boundary
650  localMeshIndex[d] = boundaryIndex[d];
651  //Disable the boundary
652  localIndex = getLocalIndex(localMeshIndex);
653  activeBoundaryList_[localIndex] = false;
654  }
655  }
656  }
657  }
658  }
659 
660  //Create a list of the active boundaries
661  localIndex = 0;
662  for (bool active : activeBoundaryList_)
663  {
664  if (active)
665  {
666  boundaryList_.push_back(localIndex);
667  }
668  localIndex++;
669  }
670 }

References activeBoundaryList_, boundaryList_, domainHandler_, getLocalIndex(), DomainHandler::getNumberOfDomains(), globalMeshIndex_, i, j, k, XAXIS, YAXIS, and ZAXIS.

◆ disableBoundary()

void Domain::disableBoundary ( unsigned  localIndex)

Disables a boundary of the domain with a neighbouring domain.

This function disables the communication of a boundary. Each domain in the parallel code has 27 boundaries: (6 sides, 12 ribs, 8 corners) and for convenience one is associated with the domain itself (used for local indexing). Boundaries that are inactive, such as domains that extend to infinity, do not need to be considered in the parallel computation. This function disables that boundary.

Parameters
[in]localIndexThe local index of a neighbour of the current domain
358 {
359  activeBoundaryList_[localIndex] = false;
360 }

References activeBoundaryList_.

◆ finaliseBoundaryDataTransmission()

void Domain::finaliseBoundaryDataTransmission ( )

This function processes the transmitted data.

copies the received mpi data into the particles/interactions and adds them to the particleHandler/interactionHandler All vectors that have been used in transmitting data are then cleaned up

Parameters
[in,out]particleHandlerHandles all particles in the current domain, on output contains the newly received particles
[in,out]interactionHandlerHandles all interactions in the current domain, on output contains the newly received interactions
1242  {
1243  //For all boundaries
1244  for (int localIndex : boundaryList_)
1245  {
1246  //copy the received data into the particleHandler and neighbour particle list
1247  std::vector<BaseParticle*> newParticles;
1248  processReceivedBoundaryParticleData(localIndex, newParticles);
1249  //All particles in the current domain that have been send to the other domains need to be flagged as communicating particles
1250  processSentBoundaryParticles(localIndex);
1251  //copy the received interaction data into the standard dpm structure
1252  processReceivedInteractionData(localIndex, newParticles);
1253 
1254  //Delete all send/receive data
1255  boundaryParticleDataSend_[localIndex].clear();
1256  boundaryParticleDataReceive_[localIndex].clear();
1259  interactionDataReceive_[localIndex]);
1260 
1261  //Reset all counters
1262  numberOfParticlesSend_[localIndex] = 0;
1263  numberOfParticlesReceive_[localIndex] = 0;
1264  numNewInteractionsSend_[localIndex] = 0;
1265  numNewInteractionsReceive_[localIndex] = 0;
1266 
1267  //Reset all lists
1268  newBoundaryParticleList_[localIndex].clear();
1269  newInteractionList_[localIndex].clear();
1270  }
1271  }
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
Definition: BaseHandler.h:733
InteractionHandler interactionHandler
An object of the class InteractionHandler.
Definition: DPMBase.h:1473
void processReceivedBoundaryParticleData(unsigned index, std::vector< BaseParticle * > &newParticles)
Function that copies the mpi data format of a base particle to a real particle and adds it to the par...
Definition: Domain.cc:920
void processReceivedInteractionData(unsigned index, std::vector< BaseParticle * > &newParticles)
Processes the received interactions from newly added mpi particles
Definition: Domain.cc:978
void processSentBoundaryParticles(unsigned index)
Bookkeep the newly send particles.
Definition: Domain.cc:956
void deleteMPIInteractionDataArray(void *dataArray)
deletes an MPIInteractionDataArray
Definition: InteractionHandler.cc:207

References boundaryList_, boundaryParticleDataReceive_, boundaryParticleDataSend_, InteractionHandler::deleteMPIInteractionDataArray(), BaseHandler< T >::getDPMBase(), getHandler(), interactionDataReceive_, interactionDataSend_, DPMBase::interactionHandler, newBoundaryParticleList_, newInteractionList_, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, processReceivedBoundaryParticleData(), processReceivedInteractionData(), and processSentBoundaryParticles().

Referenced by addNewParticles(), and addParticle().

◆ finalisePositionAndVelocityUpdate()

void Domain::finalisePositionAndVelocityUpdate ( std::set< BaseParticle * > &  ghostParticlesToBeDeleted)

processes position and velocity data for ghost particles

After the data has been received from other processors, this function will update the ghost particles with the new position and velocity data. Afterwards the status of the particles will be updated based on their new positions. Sometimes a particle needs to be removed from the simulation, however since this particle might still be active in the periodic boundary it is not deleted straight away but stored in ghostParticlesToBeDeleted. Finally the communication data is removed.

Parameters
[in,out]ghostParticlesToBeDeletedA vector containing particles that need to be removed from the simulation
1481 {
1482 
1483  //For all active boundaries
1484  for (int localIndex : boundaryList_)
1485  {
1486  updateParticlePosition(localIndex);
1487  updateParticleVelocity(localIndex);
1488  }
1489 
1490  //Based on the new position, update the particle lists.
1491  //Remove particles that left the communication zone, they will be re-communicated in a later step
1492  updateParticles(ghostParticlesToBeDeleted);
1493 
1494  //For all active boundaries clear the data lists
1495  for (int localIndex : boundaryList_)
1496  {
1497  updatePositionDataSend_[localIndex].clear();
1498  updateVelocityDataSend_[localIndex].clear();
1499  updatePositionDataReceive_[localIndex].clear();
1500  updateVelocityDataReceive_[localIndex].clear();
1501  }
1502 
1503 }
void updateParticles(std::set< BaseParticle * > &ghostParticlesToBeDeleted)
This step updates all communication lists and particles in the communication zone.
Definition: Domain.cc:1287
void updateParticlePosition(int localIndex)
Updates the position of particles which are flagged as MPIParticles.
Definition: Domain.cc:1391
void updateParticleVelocity(int localIndex)
Updates the velocity of particles which are flagged as MPIParticles.
Definition: Domain.cc:1420

References boundaryList_, updateParticlePosition(), updateParticles(), updateParticleVelocity(), updatePositionDataReceive_, updatePositionDataSend_, updateVelocityDataReceive_, and updateVelocityDataSend_.

Referenced by updateStatus().

◆ finaliseVelocityUpdate()

void Domain::finaliseVelocityUpdate ( )

Processes particle velocity data for ghost particles.

This function is not in use

1537 {
1538  //For all active boundaries
1539  for (int localIndex : boundaryList_)
1540  {
1541  updateParticleVelocity(localIndex);
1542  }
1543 
1544  //For all active boundaries clear the data lists
1545  for (int localIndex : boundaryList_)
1546  {
1547  updateVelocityDataSend_[localIndex].clear();
1548  updateVelocityDataReceive_[localIndex].clear();
1549  }
1550 }

References boundaryList_, updateParticleVelocity(), updateVelocityDataReceive_, and updateVelocityDataSend_.

Referenced by updateVelocity().

◆ findNearbyBoundaries()

std::vector< int > Domain::findNearbyBoundaries ( BaseParticle particle,
Mdouble  offset = 0 
)

This function finds if a given particle is close to a given boundary.

This function detects in how many boundaries the particle is located and is stored in the boundaryIndex. The boundary Index in the x-direction: a) -1 if the particle is at the left boundary b) 0 if the particle is not at a boundary c) 1 if the particle is at the right boundary The same holds for the y and z direction as well

Parameters
[in]particlea base particle
[out]offsetthe L1 distance between the domain boundary and the wanted boundary
Returns
boundaryIndex a vector indicating at which boundary the particle is
534 {
535  std::vector<int> boundaryIndex(3);
536  Mdouble interactionDistance = domainHandler_->getInteractionDistance();
537 
538  //for x,y,z directions, find if the particle is close to the left or right wall or not at all
539  for (int d = 0; d < 3; d++)
540  {
541  //Check if the particle is close to Lx
542  if ((particle->getPosition().getComponent(d)) < (domainMin_[d] + interactionDistance + offset))
543  {
544  //Update switch
545  boundaryIndex[d] = -1;
546  }
547  //Check if particle is close to Rx
548  else if ((particle->getPosition().getComponent(d)) >= (domainMax_[d] - interactionDistance - offset))
549  {
550  //Update switch
551  boundaryIndex[d] = 1;
552  }
553  }
554  return boundaryIndex;
555 }
Mdouble getInteractionDistance()
Gets the interaction distance of the domain handler.
Definition: DomainHandler.cc:302

References domainHandler_, domainMax_, domainMin_, Vec3D::getComponent(), DomainHandler::getInteractionDistance(), and BaseInteractable::getPosition().

Referenced by addParticlesToLists(), inBoundary(), and updateParticles().

◆ findNewMPIInteractions()

void Domain::findNewMPIInteractions ( )

Finds interactions that have to be send over to another domain.

Finds interactions that have to be sent over to another domain.

Newly added particles to the communication lists might have history interactions with the particles already there. The other domains need to be aware of these history interactions and this function collects the relevant interactions.

804  {
805  //For all active boundaries
806  for (int localIndex : boundaryList_)
807  {
808  //Check all newly added particles for interactions with already known particles
809  for (BaseParticle* newBoundaryParticle : newBoundaryParticleList_[localIndex])
810  {
811  //Loop over all interactions of the new particle
812  std::vector<BaseInteraction*> interactions = newBoundaryParticle->getInteractions();
813  for (BaseInteraction* interaction : interactions)
814  {
815  //Find out what the new particle is interacting with
816  BaseParticle* particleP = dynamic_cast<BaseParticle*>(interaction->getP());
817  BaseParticle* objectI = dynamic_cast<BaseParticle*>(interaction->getI());
818 
819  //If the P in the interaction structure is the new particle, find I
820  if (newBoundaryParticle == particleP)
821  {
822  //Check if the new particle is interacting with a wall
823  if (!objectI)
824  {
825  //Check if the interaction is still valid
826  BaseWall* wall = dynamic_cast<BaseWall*>(interaction->getI());
827  Mdouble distance;
828  Vec3D normal;
829  wall->getDistanceAndNormal(*particleP, distance, normal);
830  if (distance <= particleP->getMaxInteractionRadius())
831  {
832  //Add the interaction to the list if there are still in contact (hence the if statement)
833  newInteractionList_[localIndex].push_back(interaction);
834  }
835  }
836  else //is I a particle
837  {
838  //check if particle is in mpi domain OR (TODO) if it is in the newBoundaryParticleList_
839  if (objectI->isInMPIDomain() || isInNewBoundaryParticleList(objectI, localIndex))
840  {
841  // iff the interaction partner of the new particle is in the communication zone, transmit the interaction
842  if (inBoundary(objectI,localIndex))
843  {
844  //Is the particle still interacting after the position update?
845  Vec3D branchVector = particleP->getPosition() - objectI->getPosition();
846  //Get the square of the distance between particle i and particle j
847  Mdouble distanceSquared = Vec3D::getLengthSquared(branchVector);
848  Mdouble sumOfInteractionRadii =
849  objectI->getSumOfInteractionRadii(particleP);
850  if (distanceSquared < (sumOfInteractionRadii * sumOfInteractionRadii))
851  {
852  //Add the interaction to the list
853  newInteractionList_[localIndex].push_back(interaction);
854  }
855  }
856  }
857  }
858  }
859  else //newBoundaryParticle is I in the interaction, P can only be a particle
860  {
861  //it is "I" in the interaction structure, check if it is in the mpi domain
862  if (particleP->isInMPIDomain() || isInNewBoundaryParticleList(particleP, localIndex))
863  {
864  //Is the particle still interacting after the position update?
865  Vec3D branchVector = particleP->getPosition() - objectI->getPosition();
866  //Get the square of the distance between particle i and particle j
867  Mdouble distanceSquared = Vec3D::getLengthSquared(branchVector);
868  Mdouble sumOfInteractionRadii =
869  objectI->getSumOfInteractionRadii(particleP);
870  if (distanceSquared < (sumOfInteractionRadii * sumOfInteractionRadii))
871  {
872  //Add the interaction to the list
873  newInteractionList_[localIndex].push_back(interaction);
874  }
875  }
876  }
877  }
878  }
879  }
880 }
bool isInMPIDomain()
Indicates if the particle is in the communication zone of the mpi domain.
Definition: BaseParticle.cc:259
Mdouble getSumOfInteractionRadii(const BaseParticle *particle) const
returns the sum of the radii plus the interactionDistance
Definition: BaseParticle.h:362
Basic class for walls.
Definition: BaseWall.h:28
virtual bool getDistanceAndNormal(const BaseParticle &P, Mdouble &distance, Vec3D &normal_return) const =0
Pure virtual function that computes the distance of a BaseParticle to this wall and returns the norma...
bool inBoundary(BaseParticle *particle, int localIndex)
Definition: Domain.cc:557
bool isInNewBoundaryParticleList(BaseParticle *object, int localIndex) const
Definition: Domain.cc:788
Definition: Kernel/Math/Vector.h:30
Mdouble getLengthSquared() const
Calculates the squared length of this Vec3D: .
Definition: Vector.cc:164
void normal(const Vector< double > &x, Vector< double > &normal)
Definition: free_surface_rotation.cc:65

References boundaryList_, BaseWall::getDistanceAndNormal(), Vec3D::getLengthSquared(), BaseInteractable::getPosition(), BaseParticle::getSumOfInteractionRadii(), inBoundary(), BaseParticle::isInMPIDomain(), isInNewBoundaryParticleList(), newBoundaryParticleList_, newInteractionList_, and WallFunction::normal().

Referenced by prepareBoundaryDataTransmission().

◆ findNewMPIParticle()

void Domain::findNewMPIParticle ( BaseParticle particle)

Function that check if a given particle should be added to the communication lists.

Function that checks if a given particle should be added to the communication lists and adds it accordingly.

Parameters
[in]particlepoint to a particle that is being checked if it should be added to the communication lists
780 {
781  //If the particle is an MPI particle
782  if (!particle->isInMPIDomain() && !particle->isPeriodicGhostParticle())
783  {
785  }
786 }
bool isPeriodicGhostParticle() const
Indicates if this particle is a ghost in the periodic boundary.
Definition: BaseParticle.cc:280
void addParticlesToLists(BaseParticle *particle, std::vector< std::vector< BaseParticle * > > &list)
Function that adds the particles to the appropriate boundary list.
Definition: Domain.cc:680

References addParticlesToLists(), BaseParticle::isInMPIDomain(), BaseParticle::isPeriodicGhostParticle(), and newBoundaryParticleList_.

Referenced by findNewMPIParticles(), and prepareBoundaryDataTransmission().

◆ findNewMPIParticles()

void Domain::findNewMPIParticles ( const ParticleHandler particleHandler)

Function that finds new particles in the particle handler that should be added to the communication lists.

Parameters
[in]particleHandlerthe container that contains all particles
766 {
767  //For all particles inside the given domain, loop over all the particles to
768  //see if we have to add the particles to the new particle list
769  for (BaseParticle* particle : particleHandler)
770  {
771  findNewMPIParticle(particle);
772  }
773 }
void findNewMPIParticle(BaseParticle *particle)
Function that check if a given particle should be added to the communication lists.
Definition: Domain.cc:779

References findNewMPIParticle().

Referenced by prepareBoundaryDataTransmission().

◆ findParticleInList()

BaseParticle * Domain::findParticleInList ( unsigned int  identification,
std::vector< BaseParticle * >  particleList 
)

Searches for a particle with a specific id in a list of particles.

When interactions are copied over MPI from an MPI particle, the unique id of the particles they interact with need to be looked up. This functions searches for the correct particle

Todo:
MX: This is probably not the fastest method
Parameters
[in]identificationThe unique ID of a particle
[in]particleListList of particles
Returns
Either the particle with the id identification or a nullptr when the particle has not been found
509 {
510  for (BaseParticle* particle : particleList)
511  {
512  if (particle->getId() == identification)
513  {
514  return particle;
515  }
516  }
517  return nullptr;
518 }

◆ flushParticles()

void Domain::flushParticles ( std::set< BaseParticle * > &  toBeFlushedList)

Particles that are going to be deleted from the simulation are flushed out of the communication boundaries.

Parameters
[in]toBeFlushedListA list of particles that is going to be deleted
1678 {
1679  //For all active boundaries
1680  for (int localIndex : boundaryList_)
1681  {
1682  flushParticlesFromList(boundaryParticleList_[localIndex], toBeFlushedList);
1683  flushParticlesFromList(boundaryParticleListNeighbour_[localIndex], toBeFlushedList);
1684  }
1685 }
void flushParticlesFromList(std::vector< BaseParticle * > &list, std::set< BaseParticle * > &toBeDeletedList)
Particles that are going to be deleted from the simulation are flushed out of a give communication bo...
Definition: Domain.cc:1687

References boundaryList_, boundaryParticleList_, boundaryParticleListNeighbour_, and flushParticlesFromList().

Referenced by DPMBase::checkInteractionWithBoundaries(), PeriodicBoundaryHandler::clearCommunicationLists(), and DPMBase::deleteGhostParticles().

◆ flushParticlesFromList()

void Domain::flushParticlesFromList ( std::vector< BaseParticle * > &  list,
std::set< BaseParticle * > &  toBeDeletedList 
)

Particles that are going to be deleted from the simulation are flushed out of a give communication boundary.

1688 {
1689  //Firstly: turn all particles that need to be flushed into nullptrs
1690  for (auto& p : list)
1691  {
1692  if (p != nullptr)
1693  {
1694  BaseParticle* particle1 = p;
1695  for (BaseParticle* particle2 : toBeFlushedList)
1696  {
1697  //If the particle was found in the list, make a nullptr
1698  if (particle1 == particle2)
1699  {
1700  logger(VERBOSE, "Removing particle from mpi domain at: %", particle1->getPosition());
1701  p = nullptr;
1702  }
1703  }
1704  }
1705  }
1706 }
@ VERBOSE

References BaseInteractable::getPosition(), logger, p, and VERBOSE.

Referenced by flushParticles().

◆ getActiveBoundaryList()

std::vector< bool > Domain::getActiveBoundaryList ( )

Returns a list of boundaries that are active in mpi communication.

Returns a list of boundaries that are active in mpi communication

Returns
List of active mpi communication boundaries
367 {
368  return activeBoundaryList_;
369 }

References activeBoundaryList_.

◆ getDomainMax()

std::vector< double > Domain::getDomainMax ( )

Gets the maximum domain bounds.

Gets the domain's maximum domain bounds

Returns
Maximum bounds of the domain
299 {
300  return domainMax_;
301 }

References domainMax_.

◆ getDomainMin()

std::vector< double > Domain::getDomainMin ( )

Gets the minimum domain bounds.

Gets the domain's minimum domain bounds

Returns
Minimum bounds of the domain
290 {
291  return domainMin_;
292 }

References domainMin_.

◆ getGlobalIndex()

int Domain::getGlobalIndex ( )

Gets the global index of the domain.

Returns the global index of the domain in the whole simulation domain

Returns
Returns the global index of the domain
326 {
327  return globalIndex_;
328 }

References globalIndex_.

◆ getGlobalMeshIndex()

std::vector< unsigned > Domain::getGlobalMeshIndex ( )

Gets the global mesh index of the domain.

returns a vector with the global mesh indices (i,j,k)

Returns
global mesh indices i,j and k
335 {
336  return globalMeshIndex_;
337 }

References globalMeshIndex_.

◆ getHandler()

DomainHandler * Domain::getHandler ( ) const

Gets the domainHandler.

Returns the pointer to the DomainHandler the domain belongs to

Returns
pointer to the handler
1558 {
1559  return domainHandler_;
1560 }

References domainHandler_.

Referenced by debugInformation(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), prepareBoundaryDataTransmission(), processReceivedBoundaryParticleData(), processReceivedInteractionData(), setBounds(), setRange(), and updateParticlePosition().

◆ getLocalIndex() [1/2]

int Domain::getLocalIndex ( int  i,
int  j,
int  k 
)

return the local index of a domain given local mesh indices i,j and k

Given i,j,k (where i=0,j=0,k=0 is the current domain), get the local index of a neighbouring domain

Parameters
[in]iIndex in the x-direction with i=0 corresponding to the current domain
[in]jIndex in the y-direction with j=0 corresponding to the current domain
[in]kIndex in the z-direction with k=0 corresponding to the current domain
Returns
The localIndex of the neighbour is returned.
478 {
479  return i + 3 * j + 9 * k + 13;
480 }

References i, j, and k.

Referenced by addParticlesToLists(), and disableBoundaries().

◆ getLocalIndex() [2/2]

int Domain::getLocalIndex ( std::vector< int localMeshIndex)

return the local index of a domain given the localMeshIndex vector

Given i,j,k (where i=0,j=0,k=0 is the current domain), get the local index of a neighbouring domain

Parameters
[in]localMeshIndex(i,j,k) where (0,0,0) corresponds to the current domain
Returns
The localIndex of the neighbour is returned.
489 {
490  return localMeshIndex[Direction::XAXIS] + 3 * localMeshIndex[Direction::YAXIS] +
491  9 * localMeshIndex[Direction::ZAXIS] + 13;
492 }

References XAXIS, YAXIS, and ZAXIS.

◆ getLocalIndexInverse()

std::vector< int > Domain::getLocalIndexInverse ( int  localMeshIndex)

Does the inverse action of getLocalIndex (un-bundles the localIndex into the three dimensions)

494  {
495  localIndex -= 13;
496  return {localIndex%3, (localIndex/3)%3, (localIndex/9)%3};
497 }

Referenced by inBoundary().

◆ getMiddle()

Vec3D Domain::getMiddle ( ) const

Gives the middle of the domain.

Returns the middle of this square domain, required for periodic particles

Returns
middle_ The middle position of a cubic domain
1713 {
1714  return middle_;
1715 }

References middle_.

Referenced by PeriodicBoundaryHandler::findTargetProcessor(), and ForceLawsMPI2Test::printTime().

◆ getName()

std::string Domain::getName ( ) const
overridevirtual

Returns the name of the object.

Returns the object's class name (i.e. 'DeletionBoundary').

Returns
the object's class name

Implements BaseObject.

187 {
188  return "Domain";
189 }

◆ getNumberOfMPIParticles()

unsigned int Domain::getNumberOfMPIParticles ( )

Obtains the number of particles in the particleHandler that are MPIParticles.

All the MPIParticles are located in the neighbour lists and we only need to take a sum of these lists to obtain the number of MPIParticles. This function is required to keep track of the number of real particles in the domain.

1644 {
1645  unsigned int count = 0;
1646  for (auto& index : boundaryParticleListNeighbour_)
1647  {
1648  count += index.size();
1649  }
1650  return count;
1651 }

References boundaryParticleListNeighbour_.

◆ getNumberOfTrueMPIParticles()

unsigned int Domain::getNumberOfTrueMPIParticles ( )

Obtains the number of particles in the particleHandler that are MPIParticles, but NOT periodic particles.

All the MPIParticles are located in the neighbour lists and we only need to take a sum of these lists to obtain the number of MPIParticles. This function is required to keep track of the number of real particles in the domain.

1659 {
1660  unsigned int count = 0;
1661  for (auto& index : boundaryParticleListNeighbour_)
1662  {
1663  for (auto& p : index)
1664  {
1665  if (!p->isPeriodicGhostParticle())
1666  {
1667  count++;
1668  }
1669  }
1670  }
1671  return count;
1672 }

References boundaryParticleListNeighbour_, and p.

Referenced by ParticleHandler::getNumberOfRealObjectsLocal().

◆ getRank()

int Domain::getRank ( )

Gets the rank associated with the assigned processorID.

Gets the domain's rank, corresponding to a processorID.

Returns
rank of the domain
308 {
309  return rank_;
310 }

References rank_.

◆ inBoundary()

bool Domain::inBoundary ( BaseParticle particle,
int  localIndex 
)

checks whether the particle is in the localIndex zone.

557  {
558  std::vector<int> boundaryIndex = findNearbyBoundaries(particle);
559  std::vector<int> localIndex = getLocalIndexInverse(localIndex_);
560  // if the particle is in the boundary zone into which we want to transmit
561  for (int i = 0; i < 3; ++i)
562  {
563  if (localIndex[i]!=0 && boundaryIndex[i]!=localIndex[i]) {
564  return false;
565  }
566  }
567  return true;
568 }
std::vector< int > getLocalIndexInverse(int localMeshIndex)
Definition: Domain.cc:494

References findNearbyBoundaries(), getLocalIndexInverse(), and i.

Referenced by findNewMPIInteractions().

◆ isInCommunicationZone()

bool Domain::isInCommunicationZone ( BaseParticle particle)

Check if the particle is in the communication zone of the current domain.

Check if the particle is inside the communication zone

Parameters
[in]particlePointer to a particle
Returns
True if the particle is in the communication zone, i.e. in the domain, but not in the inner domain. False if it is outside the communication zone.
421 {
422  //First check if the particle is actually in the domain
423  //Secondly check if the particle is in the inner domain
424  return containsParticle(particle) && !(isInInnerDomain(particle));
425 }
bool isInInnerDomain(BaseParticle *particle)
Check if the particle is in the current domain but not in the communication zone.
Definition: Domain.cc:409
bool containsParticle(BaseParticle *particle, Mdouble offset=0.0)
Check to see if a given particle is within the current domain.
Definition: Domain.cc:379

References containsParticle(), and isInInnerDomain().

Referenced by DPMBase::mpiIsInCommunicationZone().

◆ isInGreaterDomain()

bool Domain::isInGreaterDomain ( BaseParticle particle)

Check to see if a given particle is in the current domain or in neighbouring communication zones.

Check if the particle is inside the domain + the communication zone around it

Parameters
[in]particlePointer to a particle
Returns
True if the particle is in the domain or the whole communication zone around it. False if it is outside
400 {
402 }

References containsParticle(), domainHandler_, and DomainHandler::getInteractionDistance().

◆ isInInnerDomain()

bool Domain::isInInnerDomain ( BaseParticle particle)

Check if the particle is in the current domain but not in the communication zone.

Parameters
[in]particlePointer to a particle
Returns
Returns true if the particle is in the inner domain (i.e. not in the communication zone of the domain)
410 {
412 }

References containsParticle(), domainHandler_, and DomainHandler::getInteractionDistance().

Referenced by isInCommunicationZone().

◆ isInNewBoundaryParticleList()

bool Domain::isInNewBoundaryParticleList ( BaseParticle object,
int  localIndex 
) const

Checks whether a particle is in the list of new particles received by this thread

789 {
790  for (BaseParticle *q : newBoundaryParticleList_[localIndex]) {
791  if (q == objectI)
792  return true;
793  }
794  return false;
795 }
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:2019

References newBoundaryParticleList_, and Eigen::numext::q.

Referenced by findNewMPIInteractions().

◆ performBoundaryDataTransmission()

void Domain::performBoundaryDataTransmission ( )

Collects data to be transmitted and then performs the transmission of the data.

The particles and interactions are copied into a data class that can be transmitted to other processors. The data is then accordingly send to the appropriate processors

Parameters
[in]interactionHandlerHandler that contains all interactions, required to collect interaction data
1201  {
1202  //For all active boundaries
1203  for (int localIndex : boundaryList_)
1204  {
1205  //make sure enough memory is reserved to receive the data
1206  boundaryParticleDataReceive_[localIndex].resize(numberOfParticlesReceive_[localIndex]);
1207 
1208  //Collect the particle data
1209  collectBoundaryParticleData(localIndex);
1210 
1211  //Send the data
1213  boundaryParticleDataReceive_[localIndex].data(), numberOfParticlesReceive_[localIndex],
1214  boundaryParticleDataSend_[localIndex].data(), numberOfParticlesSend_[localIndex],
1215  localIndex);
1216 
1217 
1218  //create arrays for sending and receiving interaction data
1220  numNewInteractionsSend_[localIndex]);
1222  numNewInteractionsReceive_[localIndex]);
1223 
1224  //Collect the interaction data
1225  collectInteractionData(localIndex);
1226 
1227  //Send the data
1229  interactionDataReceive_[localIndex], numNewInteractionsReceive_[localIndex],
1230  interactionDataSend_[localIndex], numNewInteractionsSend_[localIndex], localIndex);
1231  }
1232  }
int data[]
Definition: Map_placement_new.cpp:1
@ INTERACTION_DATA
Definition: MpiContainer.h:63
@ PARTICLE_DATA
Definition: MpiContainer.h:58
@ INTERACTION
Definition: MpiContainer.h:46
@ PARTICLE
Definition: MpiContainer.h:46
void sendAndReceiveMPIData(MercuryMPITag tag, MercuryMPIType type, T *receiveData, unsigned receiveCount, T *sendData, unsigned sendCount, unsigned localIndexNeighbour)
Function that sends transmissionData/positionData/velocityData to other processors.
Definition: Domain.h:347
void collectBoundaryParticleData(int localIndex)
collects the data of a particle that has to be communicated to other processors
Definition: Domain.cc:888
void collectInteractionData(int localIndex)
Collects the data of an interaction that has to be communicated to other processors.
Definition: Domain.cc:903
void * createMPIInteractionDataArray(unsigned int numberOfInteractions) const
creates an empty MPIInteractionDataArray
Definition: InteractionHandler.cc:191

References boundaryList_, boundaryParticleDataReceive_, boundaryParticleDataSend_, collectBoundaryParticleData(), collectInteractionData(), InteractionHandler::createMPIInteractionDataArray(), data, BaseHandler< T >::getDPMBase(), getHandler(), INTERACTION, INTERACTION_DATA, interactionDataReceive_, interactionDataSend_, DPMBase::interactionHandler, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, PARTICLE, PARTICLE_DATA, and sendAndReceiveMPIData().

Referenced by addNewParticles(), and addParticle().

◆ prepareBoundaryDataTransmission() [1/2]

void Domain::prepareBoundaryDataTransmission ( )

Prepares the MPI transmission of particle and interaction data from particles in particleHandler.

This function checks all the particles in the particle handler to see if they have moved in the communication domain. If that is the case they are added to a list of particles that need to be send. After all particles are evaluated the number of new particles to be send is send to the appropriate processors The same is being done to the interactions of the newly found particles

Parameters
[in]particleHandlerhandles all the particles in the current domain
1126  {
1127  //Find new particles that have entered the communication zone
1128  findNewMPIParticles(getHandler()->getDPMBase()->particleHandler);
1129 
1130  //Find interactions between new particles and other particles in the communication zone
1132 
1133  //Compute number of particles to send
1134  //For all boundaries
1135  for (int localIndex : boundaryList_)
1136  {
1137  numberOfParticlesSend_[localIndex] = newBoundaryParticleList_[localIndex].size();
1138  numNewInteractionsSend_[localIndex] = newInteractionList_[localIndex].size();
1139  }
1140 
1141  //For all active boundaries
1142  for (int localIndex : boundaryList_)
1143  {
1144  //Send and receive the number of new boundary particles
1146  (numberOfParticlesSend_[localIndex]), localIndex);
1147 
1148  //Send and receive the new interactions
1150  (numNewInteractionsSend_[localIndex]), localIndex);
1151  }
1152  }
@ INTERACTION_COUNT
Definition: MpiContainer.h:62
@ PARTICLE_COUNT
Definition: MpiContainer.h:57
void sendAndReceiveCount(MercuryMPITag tag, unsigned &countReceive, unsigned &countSend, unsigned localIndexNeighbour)
A symmetric communication between two domains exchanging a send/receive count.
Definition: Domain.cc:1098
void findNewMPIInteractions()
Finds interactions that have to be send over to another domain.
Definition: Domain.cc:803
void findNewMPIParticles(const ParticleHandler &particleHandler)
Function that finds new particles in the particle handler that should be added to the communication l...
Definition: Domain.cc:765

References boundaryList_, findNewMPIInteractions(), findNewMPIParticles(), getHandler(), INTERACTION_COUNT, newBoundaryParticleList_, newInteractionList_, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, PARTICLE_COUNT, and sendAndReceiveCount().

Referenced by addNewParticles(), and addParticle().

◆ prepareBoundaryDataTransmission() [2/2]

void Domain::prepareBoundaryDataTransmission ( BaseParticle particle)

Prepares the MPI transmission of a single particle and its interactions.

When a single particle has to be added to the communication zone (i.e. when the user adds a particle during the simulation) then all processors should be informed if they receive the particle or not. The functionality of this function is practically the same as that of prepareBoundaryDataTransmission(ParticleHandler &particleHandler) The same is being done to the interactions of the newly found particles

Parameters
[in]particleA base particle that needs to be transmitted
1163  {
1164  //Assign the particle to the correct lists if the particle belongs to this domain
1165  if (containsParticle(particle))
1166  {
1167  findNewMPIParticle(particle);
1168  }
1169 
1170  //Note: When inserting a single particle, it has no interactions, so no interactions to be copied either
1171 
1172  //Compute number of particles to send
1173  //For all boundaries
1174  for (int localIndex : boundaryList_)
1175  {
1176  numberOfParticlesSend_[localIndex] = newBoundaryParticleList_[localIndex].size();
1177  numNewInteractionsSend_[localIndex] = newInteractionList_[localIndex].size();
1178  }
1179 
1180 
1181  //For all active boundaries
1182  for (int localIndex : boundaryList_)
1183  {
1184  //Send and receive the number of new boundary particles
1186  (numberOfParticlesSend_[localIndex]), localIndex);
1187 
1188  //Send and receive the new interactions
1190  (numNewInteractionsSend_[localIndex]), localIndex);
1191  }
1192  }

References boundaryList_, containsParticle(), findNewMPIParticle(), INTERACTION_COUNT, newBoundaryParticleList_, newInteractionList_, numberOfParticlesReceive_, numberOfParticlesSend_, numNewInteractionsReceive_, numNewInteractionsSend_, PARTICLE_COUNT, and sendAndReceiveCount().

◆ preparePositionAndVelocityUpdate()

void Domain::preparePositionAndVelocityUpdate ( )

Function that sends particle position and velocity data for ghost particles to other processors.

When the real particle moves on it's actual domain, it's ghost particles have to get an update this function sends the data to the processors that require the update

1440 {
1441  //For all active boundaries
1442  for (int localIndex : boundaryList_)
1443  {
1444  numberOfParticlesSend_[localIndex] = boundaryParticleList_[localIndex].size();
1445  numberOfParticlesReceive_[localIndex] = boundaryParticleListNeighbour_[localIndex].size();
1446 
1447  //Increase capacity for the receiving data files
1448  updatePositionDataReceive_[localIndex].resize(numberOfParticlesReceive_[localIndex]);
1449  updateVelocityDataReceive_[localIndex].resize(numberOfParticlesReceive_[localIndex]);
1450 
1451 
1452  //Collect data
1453  for (BaseParticle* particle : boundaryParticleList_[localIndex])
1454  {
1455  updatePositionDataSend_[localIndex].push_back(copyPositionFrom(particle));
1456  updateVelocityDataSend_[localIndex].push_back(copyVelocityFrom(particle));
1457  }
1458 
1459  //Send and receive the data
1461  updatePositionDataReceive_[localIndex].data(), numberOfParticlesReceive_[localIndex],
1462  updatePositionDataSend_[localIndex].data(), numberOfParticlesSend_[localIndex],
1463  localIndex);
1465  updateVelocityDataReceive_[localIndex].data(), numberOfParticlesReceive_[localIndex],
1466  updateVelocityDataSend_[localIndex].data(), numberOfParticlesSend_[localIndex],
1467  localIndex);
1468  }
1469 }
@ VELOCITY_DATA
Definition: MpiContainer.h:61
@ POSITION_DATA
Definition: MpiContainer.h:59
@ VELOCITY
Definition: MpiContainer.h:46
@ POSITION
Definition: MpiContainer.h:46
MPIParticlePosition copyPositionFrom(BaseParticle *particle)
Copies the position from a particle to an MPIParticlePosition class.
Definition: MpiDataClass.cc:153
MPIParticleVelocity copyVelocityFrom(BaseParticle *particle)
Copies the velocity from a particle to an MPIParticleVelocity class.
Definition: MpiDataClass.cc:169

References boundaryList_, boundaryParticleList_, boundaryParticleListNeighbour_, copyPositionFrom(), copyVelocityFrom(), data, numberOfParticlesReceive_, numberOfParticlesSend_, POSITION, POSITION_DATA, sendAndReceiveMPIData(), updatePositionDataReceive_, updatePositionDataSend_, updateVelocityDataReceive_, updateVelocityDataSend_, VELOCITY, and VELOCITY_DATA.

Referenced by updateStatus().

◆ prepareVelocityUpdate()

void Domain::prepareVelocityUpdate ( )

Function that sends particle velocity data for ghost particles.

This function is not in use

1509 {
1510  //For all active boundaries
1511  for (int localIndex : boundaryList_)
1512  {
1513  numberOfParticlesSend_[localIndex] = boundaryParticleList_[localIndex].size();
1514  numberOfParticlesReceive_[localIndex] = boundaryParticleListNeighbour_[localIndex].size();
1515 
1516  //Resize the vector to the correct size
1517  updateVelocityDataReceive_[localIndex].resize(numberOfParticlesReceive_[localIndex]);
1518 
1519  //Collect data
1520  for (BaseParticle* particle : boundaryParticleList_[localIndex])
1521  {
1522  updateVelocityDataSend_[localIndex].push_back(copyVelocityFrom(particle));
1523  }
1524 
1525  //Send the data
1527  updateVelocityDataReceive_[localIndex].data(), numberOfParticlesReceive_[localIndex],
1528  updateVelocityDataSend_[localIndex].data(), numberOfParticlesSend_[localIndex],
1529  localIndex);
1530  }
1531 }

References boundaryList_, boundaryParticleList_, boundaryParticleListNeighbour_, copyVelocityFrom(), data, numberOfParticlesReceive_, numberOfParticlesSend_, sendAndReceiveMPIData(), updateVelocityDataReceive_, updateVelocityDataSend_, VELOCITY, and VELOCITY_DATA.

Referenced by updateVelocity().

◆ processReceivedBoundaryParticleData()

void Domain::processReceivedBoundaryParticleData ( unsigned  index,
std::vector< BaseParticle * > &  newParticles 
)

Function that copies the mpi data format of a base particle to a real particle and adds it to the particleHandler.

When adding a particle with this function it's always a ghost particle and therefor gets the MPIParticle flag

Parameters
[in]indexThe boundary index of the boundary list currently being treated
[in,out]particleHandlerContainer containing the particles of the current domain, will contain the new MPI particles as well
921 {
922 
923  ParticleHandler& particleHandler = getHandler()->getDPMBase()->particleHandler;
924  //for all MPIParticles that have been received on the other side
925  for (int i = 0; i < numberOfParticlesReceive_[index]; i++)
926  {
927  //copy data from data
930 
931  //Flag that the particle is a ghost particle of a real particle in the neighbour domain
932  p0->setMPIParticle(true);
933  //Flag that the particle is list as a particle in the mpi domain
934  p0->setInMPIDomain(true);
935  //add particle to handler
936  particleHandler.addGhostObject(p0);
937  //Set previous position as current position
938  BaseParticle* pGhost = particleHandler.getLastObject();
939  pGhost->setPreviousPosition(particleHandler.getLastObject()->getPosition());
940  //Add to the newParticle list
941  newParticles.push_back(pGhost);
942  logger(VERBOSE, "Adding mpi particle % at: %", particleHandler.getLastObject()->getId(),
943  particleHandler.getLastObject()->getPosition());
944 
945  //add pointer to the particle to the list and set the status to idle
946  boundaryParticleListNeighbour_[index].push_back(particleHandler.getLastObject());
947  }
948 }
Vector3f p0
Definition: MatrixBase_all.cpp:2
void copyDataFromMPIParticleToParticle(MPIParticle *bP, BaseParticle *p, ParticleHandler *particleHandler)
Copies data from an MPIParticle class to a BaseParticle and sets the particleHandler and species.
Definition: MpiDataClass.cc:84
T * getLastObject()
Gets a pointer to the last Object in this BaseHandler.
Definition: BaseHandler.h:642
unsigned int getId() const
Returns the unique identifier of any particular object.
Definition: BaseObject.h:104
void setPreviousPosition(const Vec3D &pos)
Sets the particle's position in the previous time step.
Definition: BaseParticle.cc:600
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created.
Definition: DPMBase.h:1443
static BaseParticle * newParticle()
Definition: MpiDataClass.cc:136
Container to store pointers to all particles.
Definition: ParticleHandler.h:28
void addGhostObject(int fromProcessor, int toProcessor, BaseParticle *p)
Adds a ghost particle located at fromProcessor to toProcessor.
Definition: ParticleHandler.cc:275

References ParticleHandler::addGhostObject(), boundaryParticleDataReceive_, boundaryParticleListNeighbour_, copyDataFromMPIParticleToParticle(), BaseHandler< T >::getDPMBase(), getHandler(), BaseObject::getId(), BaseHandler< T >::getLastObject(), BaseInteractable::getPosition(), i, logger, MPISphericalParticle::newParticle(), numberOfParticlesReceive_, p0, DPMBase::particleHandler, BaseParticle::setPreviousPosition(), and VERBOSE.

Referenced by finaliseBoundaryDataTransmission().

◆ processReceivedInteractionData()

void Domain::processReceivedInteractionData ( unsigned  index,
std::vector< BaseParticle * > &  newParticles 
)

Processes the received interactions from newly added mpi particles

Processes the received interactions from newly added mpi particles.

The received interaction data is scanned for interaction id's P and I they are then matches to the actual particle or wall and the interaction is created. The history details of the interaction are filled in after creation.

Bug:
There is a subtle and very rare bug in here, where two particles with an interaction across a periodic boundary pass into the next domain at the same time step. In this case, the interactions should be copied over before the ghost-particles are constructed. However, since the interaction is with the ghost particle, this cannot be done. That is why there is a 'continue' if one of the particles of the interaction is not found. An illustration of this situation is given in PeriodicBoundaryEnteringMpiDomainMPI2Test.
Parameters
[in]localIndexThe boundary index of the boundary list currently being treated
[in,out]interactionHandlerHandler containing all interactions on the current domain
979 {
981  for (unsigned int l = 0; l < numNewInteractionsReceive_[localIndex]; l++)
982  {
983  unsigned int identificationP;
984  unsigned int identificationI;
985  bool isWallInteraction;
986  unsigned timeStamp;
987 
988  //Get the general information required to setup a new interaction
990  l, identificationP, identificationI,
991  isWallInteraction, timeStamp);
992 
993  logger(VERBOSE, "interaction details: %, %, idP %, idI %, wall %, time %", interactionDataReceive_[localIndex],
994  l, identificationP, identificationI,
995  isWallInteraction, timeStamp);
996 
997  //Find the particle in the newParticle list
998  BaseParticle* pGhost = nullptr;
999  int idOther;
1000  for (BaseParticle* particle : newParticles)
1001  {
1002  if (particle->getId() == identificationP)
1003  {
1004  pGhost = particle;
1005  idOther = identificationI;
1006  break;
1007  }
1008 
1009  if (particle->getId() == identificationI)
1010  {
1011  pGhost = particle;
1012  idOther = identificationP;
1013  break;
1014  }
1015  }
1016  if (pGhost == nullptr)
1017  {
1018  logger(WARN, "In Domain::processReceivedInteractionData: pGhost (id %) is nullptr, the interaction data is not copied. Two particles possibly moved into domain simultaneously.", identificationP);
1019  continue;
1020  }
1021 
1022  //If it is a wall interaction, do stuff
1023  if (isWallInteraction)
1024  {
1026  //Create interactions
1027  BaseInteraction* j = I->getInteractionWith(pGhost, timeStamp, &iH);
1028  if (j!= nullptr) j->setMPIInteraction(interactionDataReceive_[localIndex], l, false);
1029 
1030  }
1031  else
1032  {
1033  //Obtain potential interaction particles
1034  std::vector<BaseParticle*> interactingParticleList;
1035  getHandler()->getDPMBase()->hGridGetInteractingParticleList(pGhost, interactingParticleList);
1036 
1037  //Find the other interacting particle
1038  BaseParticle* otherParticle = nullptr;
1039  for (BaseParticle* p2 : interactingParticleList)
1040  {
1041  if (p2->getId() == idOther)
1042  {
1043  otherParticle = p2;
1044  break;
1045  }
1046  }
1047  if (otherParticle == nullptr) {
1048  //search for the other particle in the newParticles list
1049  for (BaseParticle *particle : newParticles) {
1050  if (particle->getId() == idOther) {
1051  otherParticle = particle;
1052  break;
1053  }
1054  }
1055  if (otherParticle == nullptr) {
1056  logger(WARN,
1057  "In Domain::processReceivedInteractionData: otherParticle (id %) is nullptr, the interaction data with pGhost (id %) is not copied. Two particles possibly moved into domain simultaneously. nt = %",
1058  identificationI, identificationP, getHandler()->getDPMBase()->getNumberOfTimeSteps());
1059  continue;
1060  }
1061  }
1062  //Add the interaction
1063  // flipped order of other and ghost, so it is in the same order as received
1064  BaseInteraction* j;
1065  if (otherParticle->getId() < pGhost->getId()) {
1066  j = pGhost->getInteractionWith(otherParticle, timeStamp, &iH);
1067  } else {
1068  j = otherParticle->getInteractionWith(pGhost, timeStamp, &iH);
1069  }
1070  if (j != nullptr) j->setMPIInteraction(interactionDataReceive_[localIndex], l, false);
1071  }
1072  }
1073 }
@ WARN
T * getObjectById(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:573
Defines the basic properties that a interactable object can have.
Definition: BaseInteractable.h:34
BaseInteraction * getInteractionWith(BaseParticle *P, unsigned timeStamp, InteractionHandler *interactionHandler) override
Checks if particle is in interaction with given particle P, and if so, returns vector of pointer to t...
Definition: BaseParticle.cc:667
virtual void hGridGetInteractingParticleList(BaseParticle *obj, std::vector< BaseParticle * > &list)
Creates a list of neighbour particles obtained from the hgrid.
Definition: DPMBase.h:989
WallHandler wallHandler
An object of the class WallHandler. Contains pointers to all the walls created.
Definition: DPMBase.h:1453
Container to store Interaction objects.
Definition: InteractionHandler.h:25
void getInteractionDetails(void *interactionData, unsigned int index, unsigned int &identificationP, unsigned int &identificationI, bool &isWallInteraction, unsigned &timeStamp)
reads the basic interaction details from an MPIInteractionDataArray
Definition: InteractionHandler.cc:225
#define I
Definition: main.h:127

References BaseHandler< T >::getDPMBase(), getHandler(), BaseObject::getId(), InteractionHandler::getInteractionDetails(), BaseParticle::getInteractionWith(), BaseHandler< T >::getObjectById(), DPMBase::hGridGetInteractingParticleList(), I, interactionDataReceive_, DPMBase::interactionHandler, j, logger, numNewInteractionsReceive_, VERBOSE, DPMBase::wallHandler, and WARN.

Referenced by finaliseBoundaryDataTransmission().

◆ processSentBoundaryParticles()

void Domain::processSentBoundaryParticles ( unsigned  index)

Bookkeep the newly send particles.

Each domain keeps a list of particles that have copies on other domains. The order of these lists is exactly the same order of the neighbour particle lists of the neighbour domain.

Parameters
[in]indexThe boundary index of the boundary list currently being treated
957 {
958  for (BaseParticle* particle : newBoundaryParticleList_[index])
959  {
960  boundaryParticleList_[index].push_back(particle);
961  particle->setInMPIDomain(true);
962  }
963 }

References boundaryParticleList_, and newBoundaryParticleList_.

Referenced by finaliseBoundaryDataTransmission().

◆ read()

void Domain::read ( std::istream &  is)
overridevirtual

This function does nothing.

Reads the object from a given istream.

Reads the object's id_ from the given istream

Parameters
[in,out]isistream the id_ is read from
Todo:
MX: why would this function be called?

Implements BaseObject.

166 {
167  logger(WARN, "[Domain::read] should not be called");
168  //BaseObject::read(is);
169 }

References logger, and WARN.

◆ sendAndReceiveCount()

void Domain::sendAndReceiveCount ( MercuryMPITag  tag,
unsigned countReceive,
unsigned countSend,
unsigned  localIndexNeighbour 
)

A symmetric communication between two domains exchanging a send/receive count.

Before real data (i.e. particle data) can be transmitted to other processors, these receiving processors need to know how many data objects they are receiving. This function facilitates a symmetric send mechanism between two domains to communicate how much objects they get from each-other

Parameters
[in]tagA MercuryMPITag that indicates what type of count is being send
[out]countReceiveunsigned integer containing the receiving count
[in]countSendunsigned integer containing the sending count
[in]localIndexNeighbourthe local index of the domain with which the communication is being done
1100  {
1101  int globalIndexNeighbour = localIndexToGlobalIndexTable_[localIndexNeighbour];
1102  int processor = localIndexToProcessorList_[localIndexNeighbour];
1103 
1104  //Create communication tags
1105  int tagReceive = globalIndexNeighbour * MAX_PROC + globalIndex_ * 10 + tag;
1106  int tagSend = globalIndex_ * MAX_PROC + globalIndexNeighbour * 10 + tag;
1107 
1108  logger.assert_debug(tagSend > 0, "Send tag is wrong. Tag: %", tagSend);
1109  logger.assert_debug(tagReceive > 0, "Receive tag is wrong. Tag: %", tagReceive);
1110  logger.assert_debug(processor >= 0, "Processor is wrong. processor: %", processor);
1111 
1112  //Communicate the requests
1113  MPIContainer::Instance().receive(countReceive, processor, tagReceive);
1114  MPIContainer::Instance().send(countSend, processor, tagSend);
1115  }
#define MAX_PROC
Definition: GeneralDefine.h:30
std::enable_if< std::is_scalar< T >::value, void >::type receive(T &t, int from, int tag)
asynchronously receive a scalar from some other processor.
Definition: MpiContainer.h:200
std::enable_if< std::is_scalar< T >::value, void >::type send(T &t, int to, int tag)
Asynchronously send a scalar to some other processor.
Definition: MpiContainer.h:150

References globalIndex_, MPIContainer::Instance(), localIndexToGlobalIndexTable_, localIndexToProcessorList_, logger, MAX_PROC, MPIContainer::receive(), and MPIContainer::send().

Referenced by prepareBoundaryDataTransmission().

◆ sendAndReceiveMPIData()

template<typename T >
void Domain::sendAndReceiveMPIData ( MercuryMPITag  tag,
MercuryMPIType  type,
T receiveData,
unsigned  receiveCount,
T sendData,
unsigned  sendCount,
unsigned  localIndexNeighbour 
)
inline

Function that sends transmissionData/positionData/velocityData to other processors.

This function is heavily templated on the type of data that can be send. All the types that are located in the MercuryMPIType enum class can be used to transmit data. Examples are MPIParticle and MPIParticlePosition data types

Parameters
[in]tagA MercuryMPITag that indicates what type of data is being send
[in]typeA MercuryMPIType that tells the MPI what MPI_Data structure to use
[out]receiveDataThe data that will be received by the current domain
[in]receiveCountThe number of items that are being received by the current domain
[in]sendDataThe data that will be send by the current domain
[in]sendCountThe number of items that are being send by the current domain
[in]localIndexNeighbourthe local index to the neighbouring domain
350  {
351  int globalIndexNeighbour = localIndexToGlobalIndexTable_[localIndexNeighbour];
352  int processor = localIndexToProcessorList_[localIndexNeighbour];
353  int tagReceive = globalIndexNeighbour * MAX_PROC + globalIndex_ * 10 + tag;
354  int tagSend = globalIndex_ * MAX_PROC + globalIndexNeighbour * 10 + tag;
355 
356  //Communicate the requests
357  if (receiveCount != 0)
358  {
359  MPIContainer::Instance().receive(receiveData, type, receiveCount, processor, tagReceive);
360  }
361  if (sendCount != 0)
362  {
363  MPIContainer::Instance().send(sendData, type, sendCount, processor, tagSend);
364  }
365  }
type
Definition: compute_granudrum_aor.py:141

References globalIndex_, MPIContainer::Instance(), localIndexToGlobalIndexTable_, localIndexToProcessorList_, MAX_PROC, MPIContainer::receive(), MPIContainer::send(), and compute_granudrum_aor::type.

Referenced by performBoundaryDataTransmission(), preparePositionAndVelocityUpdate(), and prepareVelocityUpdate().

◆ setBounds()

void Domain::setBounds ( std::vector< double domainMin,
std::vector< double domainMax,
bool  computeMiddle 
)

Sets the domain bounds.

This function sets the bound for the domain, it also computes the middle of the square domain, useful for mixed periodic/mpi particles.

Parameters
[in]domainMinMinimum values of the domain in x-,y-,z-direction
[in]domainMaxMaximum values of the domain in x-,y-,z-direction
248 {
249  domainMin_ = domainMin;
250  domainMax_ = domainMax;
251 
252  //Compute the middle of the closed domain
253  if (computeMiddle)
254  {
255  double minClosed;
256  double maxClosed;
257  for (int i = 0; i < 3; i++)
258  {
259  minClosed = domainMin_[i];
260  maxClosed = domainMax_[i];
261  if (domainMin_[i] == -constants::inf)
262  {
263  minClosed = getHandler()->getDPMBase()->getMin().getComponent(i);
264  }
265 
266  if (domainMax_[i] == constants::inf)
267  {
268  maxClosed = getHandler()->getDPMBase()->getMax().getComponent(i);
269  }
270 
271  middle_.setComponent(i, minClosed + (maxClosed - minClosed) / 2.0);
272  }
273  }
274 }
Vec3D getMax() const
Returns the maximum coordinates of the problem domain.
Definition: DPMBase.h:659
Vec3D getMin() const
Returns the minimum coordinates of the problem domain.
Definition: DPMBase.h:653
void setComponent(int index, double val)
Sets the requested component of this Vec3D to the requested value.
Definition: Vector.cc:197

References domainMax_, domainMin_, Vec3D::getComponent(), BaseHandler< T >::getDPMBase(), getHandler(), DPMBase::getMax(), DPMBase::getMin(), i, constants::inf, middle_, and Vec3D::setComponent().

◆ setGlobalMeshIndex()

void Domain::setGlobalMeshIndex ( std::vector< unsigned globalMeshIndex)

Sets the global mesh index of the domain.

sets the global mesh index

global mesh index has the shape of (i,j,k)

Parameters
[in]globalMeshIndexthe mesh index vector i,j,k
345 {
346  globalMeshIndex_ = globalMeshIndex;
347 }

References globalMeshIndex_.

◆ setHandler()

void Domain::setHandler ( DomainHandler domainHandler)

Sets the domainHandler.

Sets the pointer to the DomainHandler the domain belongs to

Parameters
[in]domainHandlerpointer to the DomainHandler
317 {
318  domainHandler_ = domainHandler;
319 }

References domainHandler_.

◆ setRange()

void Domain::setRange ( Direction  direction,
Mdouble  min,
Mdouble  max 
)

Sets the domain range in a given direction.

Sets the domain's range in a given direction.

Parameters
[in]directionDirection 0,1,2 corresponds to direction x,y,z respectively
[in]minMinimum domain bound
[in]maxMaximum domain bound
199 {
200  if (min > max)
201  {
202  logger(ERROR, "[MercuryMPI ERROR]: min is larger than max. (%,%)", min, max);
203  }
204 
205  double maxClosed;
206  double minClosed;
207  if (min == -constants::inf)
208  {
209  minClosed = getHandler()->getDPMBase()->getMin().getComponent(direction);
210  }
211 
212  if (max == constants::inf)
213  {
214  maxClosed = getHandler()->getDPMBase()->getMax().getComponent(direction);
215  }
216 
217 
218  switch (direction)
219  {
220  case Direction::XAXIS :
221  domainMin_[0] = min;
222  domainMax_[0] = max;
223  middle_.X = minClosed + (maxClosed - minClosed) / 2.0;
224  break;
225  case Direction::YAXIS :
226  domainMin_[1] = min;
227  domainMax_[1] = max;
228  middle_.Y = minClosed + (maxClosed - minClosed) / 2.0;
229  break;
230  case Direction::ZAXIS :
231  domainMin_[2] = min;
232  domainMax_[2] = max;
233  middle_.Z = minClosed + (maxClosed - minClosed) / 2.0;
234  break;
235  default :
236  logger(ERROR, "Direction is not a valid direction. (%)", direction);
237  break;
238  }
239 }
Mdouble Y
Definition: Kernel/Math/Vector.h:45
Mdouble Z
Definition: Kernel/Math/Vector.h:45
Mdouble X
the vector components
Definition: Kernel/Math/Vector.h:45
#define min(a, b)
Definition: datatypes.h:22
#define max(a, b)
Definition: datatypes.h:23

References calibrate::default, domainMax_, domainMin_, ERROR, Vec3D::getComponent(), BaseHandler< T >::getDPMBase(), getHandler(), DPMBase::getMax(), DPMBase::getMin(), constants::inf, logger, max, middle_, min, Vec3D::X, XAXIS, Vec3D::Y, YAXIS, Vec3D::Z, and ZAXIS.

◆ setRank()

void Domain::setRank ( int  rank)

Sets the rank associated with the assigned processorID.

Sets the domain's rank, corresponding to a processorID.

Parameters
[in]rankInteger corresponding to a processorID
281 {
282  rank_ = rank;
283 }

References rank_.

◆ updateParticlePosition()

void Domain::updateParticlePosition ( int  localIndex)

Updates the position of particles which are flagged as MPIParticles.

Manually updates the position of the particles, the displacement and the orientation It additionally updates the position of the particle in the hGrid

Parameters
[in]localIndexan index to the boundary being updated
1392  {
1393  //process the updated information
1394  unsigned int index = 0;
1395  for (BaseParticle* particle : boundaryParticleListNeighbour_[localIndex])
1396  {
1397  logger.assert_debug(particle->getId() == updatePositionDataReceive_[localIndex][index].id,
1398  "MPI particle lists are not in sync");
1399 
1400  //set position
1401  particle->setPreviousPosition(particle->getPosition());
1402  particle->setPosition(updatePositionDataReceive_[localIndex][index].position);
1403  particle->setOrientation(updatePositionDataReceive_[localIndex][index].orientation);
1404  if (std::is_base_of<MPILiquidFilmParticle,MPIParticle>()) /* will never occur */
1405  static_cast<LiquidFilmParticle*>(particle)->setLiquidVolume(updatePositionDataReceive_[localIndex][index].liquidVolume);
1406 
1407  //Update hGrid
1408  Vec3D displacement = particle->getPreviousPosition() - particle->getPosition();
1409  getHandler()->getDPMBase()->hGridUpdateMove(particle, displacement.getLengthSquared());
1410 
1411  index++;
1412  }
1413 }
virtual void hGridUpdateMove(BaseParticle *, Mdouble)
Definition: DPMBase.cc:1922
Definition: LiquidFilmParticle.h:15
static Mdouble getLengthSquared(const Vec3D &a)
Calculates the squared length of a Vec3D: .
Definition: Kernel/Math/Vector.h:324

References boundaryParticleListNeighbour_, BaseHandler< T >::getDPMBase(), getHandler(), Vec3D::getLengthSquared(), DPMBase::hGridUpdateMove(), logger, and updatePositionDataReceive_.

Referenced by finalisePositionAndVelocityUpdate().

◆ updateParticles()

void Domain::updateParticles ( std::set< BaseParticle * > &  ghostParticlesToBeDeleted)

This step updates all communication lists and particles in the communication zone.

After all the mpi particles have received a position and velocity update, a check is required to see if the particle needs to be treated differently. Comments inside the code show all possible options. Note that when a particle needs to be deleted, it will not be deleted straight away, but added to a list to be deleted later. Additionally the location in the communication lists will not be emptied by assigning a nullptr to it. When all particles are considered this nullptrs are removed from the list, to ensure that the mirror list on another processor keeps the same order in particles. A) The particle moves from the Neighbour domain to the current domain B) The particle moves out of the communication zone, into the neighbouring domain C) The particle moves out of the communication zone, into the current domain D) The particle changes complexity: A special case where the particle required a re-evaluation in which boundary list it belongs

Parameters
[in]particleHandlerHandler that takes care of all particles in this domain
1288  {
1289  int complexityNew;
1290  std::vector<int> boundaryIndex;
1291 
1292  //For all active boundaries
1293  for (int localIndex : boundaryList_)
1294  {
1295  //Step 1A: Remove the particles from the boundaryParticleList_ which require re-assignment
1296  //or have just moved away from the region
1297  for (int p = 0; p < boundaryParticleList_[localIndex].size(); p++)
1298  {
1299  BaseParticle* particle = boundaryParticleList_[localIndex][p];
1300  //Check if the particle is still in the domain, but not in the communication zone
1301  if (containsParticle(particle))
1302  {
1303  //check if the complexity has changed
1304  boundaryIndex = findNearbyBoundaries(particle);
1305  complexityNew = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
1306  if (particle->getCommunicationComplexity() != complexityNew)
1307  {
1308  logger(VERBOSE, "time: % | global index: % in list % | particle % | CURRENT DOMAIN - CHANGES "
1309  "COMPLEXITY", domainHandler_->getDPMBase()->getTime(), globalIndex_,
1310  localIndexToGlobalIndexTable_[localIndex], particle->getId());
1311  //Flag the particle that it no longer participates in the communication layer
1312  //so it can be reintroduced in the transmission step
1313  particle->setMPIParticle(false);
1314  particle->setInMPIDomain(false);
1315  particle->setCommunicationComplexity(0);
1316  boundaryParticleList_[localIndex][p] = nullptr;
1317  }
1318  }
1319  else
1320  {
1321  logger(VERBOSE, "time: % | global index: % in list % | particle % | CURRENT DOMAIN - TO NEIGHBOURING "
1322  "DOMAIN", domainHandler_->getDPMBase()->getTime(), globalIndex_,
1323  localIndexToGlobalIndexTable_[localIndex], particle->getId());
1324 
1325  ghostParticlesToBeDeleted.insert(particle);
1326  boundaryParticleList_[localIndex][p] = nullptr;
1327  }
1328  }
1329 
1330  //Step 1B: Remove the particles from the boundaryParticleListNeighbour_ which require re-assignment
1331  //or have just moved away from the region
1332  for (int p = 0; p < boundaryParticleListNeighbour_[localIndex].size(); p++)
1333  {
1334  BaseParticle* particle = boundaryParticleListNeighbour_[localIndex][p];
1335  //Check if the particle moved out of the neighbour domain
1337  {
1338  //The particle has moved to this domain
1339  if (containsParticle(particle))
1340  {
1341  logger(VERBOSE,
1342  "time: % | global index: % in list % | particle % | NEIGHBOURING DOMAIN - TO CURRENT DOMAIN",
1344  localIndexToGlobalIndexTable_[localIndex], particle->getId());
1345 
1346  //Flag the particle as not yet communicated
1347  particle->setMPIParticle(false);
1348  particle->setInMPIDomain(false);
1349  particle->setCommunicationComplexity(0);
1350  boundaryParticleListNeighbour_[localIndex][p] = nullptr;
1351  }
1352  //The particle has moved to a different domain
1353  else
1354  {
1355  logger(VERBOSE,
1356  "time: % | global index: % in list % | particle % | NEIGHBOURING DOMAIN - TO OTHER DOMAIN",
1358  localIndexToGlobalIndexTable_[localIndex], particle->getId());
1359  //Cruelly destroy the particle without any mercy.
1360  ghostParticlesToBeDeleted.insert(particle);
1361  boundaryParticleListNeighbour_[localIndex][p] = nullptr;
1362  }
1363  }
1364  else
1365  {
1366  //check if the complexity has changed
1367  boundaryIndex = domainHandler_->getObject(
1368  localIndexToGlobalIndexTable_[localIndex])->findNearbyBoundaries(particle);
1369  complexityNew = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
1370  if (particle->getCommunicationComplexity() != complexityNew)
1371  {
1372  logger(VERBOSE,
1373  "time: % | global index: % in list % | particle % | NEIGHBOURING DOMAIN - CHANGES COMPLEXITY",
1375  localIndexToGlobalIndexTable_[localIndex], particle->getId());
1376  //Cruelly destroy the particle without any mercy.
1377  ghostParticlesToBeDeleted.insert(particle);
1378  boundaryParticleListNeighbour_[localIndex][p] = nullptr;
1379  }
1380  }
1381  }
1382  }
1383  }
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:621
void setInMPIDomain(bool flag)
Flags the status of the particle if wether it is in the communication zone or not.
Definition: BaseParticle.cc:264
void setMPIParticle(bool flag)
Flags the mpi particle status.
Definition: BaseParticle.cc:174
unsigned getCommunicationComplexity()
Obtains the communication complexity of the particle.
Definition: BaseParticle.cc:184
Mdouble getTime() const
Returns the current simulation time.
Definition: DPMBase.cc:799

References boundaryList_, boundaryParticleList_, boundaryParticleListNeighbour_, containsParticle(), domainHandler_, findNearbyBoundaries(), BaseParticle::getCommunicationComplexity(), BaseHandler< T >::getDPMBase(), BaseObject::getId(), BaseHandler< T >::getObject(), DPMBase::getTime(), globalIndex_, localIndexToGlobalIndexTable_, logger, p, BaseParticle::setCommunicationComplexity(), BaseParticle::setInMPIDomain(), BaseParticle::setMPIParticle(), and VERBOSE.

Referenced by finalisePositionAndVelocityUpdate().

◆ updateParticleVelocity()

void Domain::updateParticleVelocity ( int  localIndex)

Updates the velocity of particles which are flagged as MPIParticles.

Updates the translation but also the angular velocity

Parameters
[in]localIndexan index to the boundary being updated
1421 {
1422  //process the updated information
1423  unsigned int index = 0;
1424  for (BaseParticle* particle: boundaryParticleListNeighbour_[localIndex])
1425  {
1426  //set velocity
1427  particle->setVelocity(updateVelocityDataReceive_[localIndex][index].velocity);
1428  particle->setAngularVelocity(updateVelocityDataReceive_[localIndex][index].angularVelocity);
1429  index++;
1430  }
1431 }
double velocity(const double &t)
Angular velocity as function of time t.
Definition: jeffery_orbit.cc:107

References boundaryParticleListNeighbour_, updateVelocityDataReceive_, and Jeffery_Solution::velocity().

Referenced by finalisePositionAndVelocityUpdate(), and finaliseVelocityUpdate().

◆ updateStatus()

void Domain::updateStatus ( std::set< BaseParticle * > &  ghostParticlesToBeDeleted)

Updates particles that are not in the current domain and communicates newly added particles.

First the newly positions of the ghost particles are communicated, based on the new positions these particles will be updated accordingly. Secondly a new sweep through all particles is performed to see if we need to add any particles to the list which have moved into the communication zone. Particles that need to be removed from the simulation are stored in a vector and will be destroyed at a later point in the code.

Parameters
[in,out]ghostParticlesToBeDeletedA list of particles which will be deleted afterwards
1613 {
1614  //Collect new positions and velocities and send them to the other domains
1617 
1618  //Receive the new positions and velocities from other domains
1619  //and update the mpi flagged particles accordingly. removes and switched particles in the lists
1620  finalisePositionAndVelocityUpdate(ghostParticlesToBeDeleted);
1622 }
void finalisePositionAndVelocityUpdate(std::set< BaseParticle * > &ghostParticlesToBeDeleted)
processes position and velocity data for ghost particles
Definition: Domain.cc:1480
void preparePositionAndVelocityUpdate()
Function that sends particle position and velocity data for ghost particles to other processors.
Definition: Domain.cc:1439

References finalisePositionAndVelocityUpdate(), MPIContainer::Instance(), preparePositionAndVelocityUpdate(), and MPIContainer::sync().

Referenced by DomainHandler::updateStatus().

◆ updateVelocity()

void Domain::updateVelocity ( )

Updates MPI particle velocity at the half-time step.

: not in use

1628 {
1629  //collect new velocity data and send
1632 
1633  //process the received data
1636 }
void prepareVelocityUpdate()
Function that sends particle velocity data for ghost particles.
Definition: Domain.cc:1508
void finaliseVelocityUpdate()
Processes particle velocity data for ghost particles.
Definition: Domain.cc:1536

References finaliseVelocityUpdate(), MPIContainer::Instance(), prepareVelocityUpdate(), and MPIContainer::sync().

Referenced by DomainHandler::updateVelocity().

◆ write()

void Domain::write ( std::ostream &  os) const
overridevirtual

This function does nothing.

Adds the object's id_ to the given ostream

Parameters
[in]osostream the id_ is added to
Todo:
MX: why would this function be called?

Implements BaseObject.

177 {
178  logger(WARN, "[Domain::write] should not be called");
179  //BaseObject::write(os);
180 }

References logger, and WARN.

Member Data Documentation

◆ activeBoundaryList_

std::vector<bool> Domain::activeBoundaryList_
private

A list of flags corresponding to an inactive or active boundary.

Referenced by constructor(), disableBoundaries(), disableBoundary(), Domain(), and getActiveBoundaryList().

◆ boundaryList_

◆ boundaryParticleDataReceive_

std::vector<std::vector<MPIParticle> > Domain::boundaryParticleDataReceive_
private

Container that keeps a list of MPIParticles that are being received by this domain.

Referenced by constructor(), Domain(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), and processReceivedBoundaryParticleData().

◆ boundaryParticleDataSend_

std::vector<std::vector<MPIParticle> > Domain::boundaryParticleDataSend_
private

Container that keeps a list of MPIParticles that are being send to other domains.

Referenced by collectBoundaryParticleData(), constructor(), Domain(), finaliseBoundaryDataTransmission(), and performBoundaryDataTransmission().

◆ boundaryParticleList_

std::vector<std::vector<BaseParticle*> > Domain::boundaryParticleList_
private

A list of boundary particles in the communication zone that are ghost particles on other domains.

Referenced by cleanCommunicationLists(), constructor(), Domain(), flushParticles(), preparePositionAndVelocityUpdate(), prepareVelocityUpdate(), processSentBoundaryParticles(), and updateParticles().

◆ boundaryParticleListNeighbour_

std::vector<std::vector<BaseParticle*> > Domain::boundaryParticleListNeighbour_
private

◆ domainHandler_

DomainHandler* Domain::domainHandler_
private

◆ domainMax_

std::vector<double> Domain::domainMax_
private

Maximum domain bounds in the x,y and z direction.

Referenced by constructor(), containsParticle(), Domain(), findNearbyBoundaries(), getDomainMax(), setBounds(), and setRange().

◆ domainMin_

std::vector<double> Domain::domainMin_
private

Minimum domain bounds in the x,y and z direction.

Referenced by constructor(), containsParticle(), Domain(), findNearbyBoundaries(), getDomainMin(), setBounds(), and setRange().

◆ globalIndex_

int Domain::globalIndex_
private

Global index of the domain in the mesh.

Note
for a standard decomposition this compares straight to the rank of the processor

Referenced by createLookUpTable(), getGlobalIndex(), sendAndReceiveCount(), sendAndReceiveMPIData(), and updateParticles().

◆ globalMeshIndex_

std::vector<unsigned> Domain::globalMeshIndex_
private

Vector containing the global mesh indices i,j,k.

Referenced by createLookUpTable(), disableBoundaries(), Domain(), getGlobalMeshIndex(), and setGlobalMeshIndex().

◆ interactionDataReceive_

std::vector<void*> Domain::interactionDataReceive_
private

Container that keeps a void array of all the interaction data that is being received by this domain, interpretation is done by the interaction handler.

Referenced by constructor(), Domain(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), and processReceivedInteractionData().

◆ interactionDataSend_

std::vector<void*> Domain::interactionDataSend_
private

Container that keeps a void array of all the interaction data that are being send to other domains, interpretation is done by the interaction handler.

Referenced by collectInteractionData(), constructor(), Domain(), finaliseBoundaryDataTransmission(), and performBoundaryDataTransmission().

◆ localIndexToGlobalIndexTable_

std::vector<int> Domain::localIndexToGlobalIndexTable_
private

look-up table to get the global index given a local domain index

Todo:
TW, Marnix should this be unsigned int

Referenced by constructor(), createLookUpTable(), Domain(), sendAndReceiveCount(), sendAndReceiveMPIData(), and updateParticles().

◆ localIndexToProcessorList_

std::vector<int> Domain::localIndexToProcessorList_
private

look-up table to get the processor of the domain given a local domain index

Todo:
TW, Marnix should this be unsigned int

Referenced by constructor(), createLookUpTable(), Domain(), sendAndReceiveCount(), and sendAndReceiveMPIData().

◆ middle_

Vec3D Domain::middle_
private

Middle of the closed domain.

Referenced by Domain(), getMiddle(), setBounds(), and setRange().

◆ newBoundaryParticleList_

std::vector<std::vector<BaseParticle*> > Domain::newBoundaryParticleList_
private

◆ newInteractionList_

std::vector<std::vector<BaseInteraction*> > Domain::newInteractionList_
private

Array that queues interactions that need to be transmitted.

Referenced by collectInteractionData(), constructor(), Domain(), finaliseBoundaryDataTransmission(), findNewMPIInteractions(), and prepareBoundaryDataTransmission().

◆ numberOfParticlesReceive_

std::vector<unsigned> Domain::numberOfParticlesReceive_
private

◆ numberOfParticlesSend_

std::vector<unsigned> Domain::numberOfParticlesSend_
private

Counter that keeps track of the number of particles that are being send to other domains.

Referenced by constructor(), Domain(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), prepareBoundaryDataTransmission(), preparePositionAndVelocityUpdate(), and prepareVelocityUpdate().

◆ numNewInteractionsReceive_

std::vector<unsigned> Domain::numNewInteractionsReceive_
private

Counter that keeps track of the number of interactions that are being received by this domain.

Referenced by constructor(), Domain(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), prepareBoundaryDataTransmission(), and processReceivedInteractionData().

◆ numNewInteractionsSend_

std::vector<unsigned> Domain::numNewInteractionsSend_
private

Counter that keeps track of the number of interactions that are being send to other domains.

Referenced by constructor(), Domain(), finaliseBoundaryDataTransmission(), performBoundaryDataTransmission(), and prepareBoundaryDataTransmission().

◆ rank_

int Domain::rank_
private

Rank of the domain which identifies to which processor it belongs.

Referenced by constructor(), createLookUpTable(), Domain(), getRank(), and setRank().

◆ updatePositionDataReceive_

std::vector<std::vector<MPIParticlePosition> > Domain::updatePositionDataReceive_
private

Container that keeps a list of MPIParticlePositions that are being received by this domain.

Referenced by constructor(), Domain(), finalisePositionAndVelocityUpdate(), preparePositionAndVelocityUpdate(), and updateParticlePosition().

◆ updatePositionDataSend_

std::vector<std::vector<MPIParticlePosition> > Domain::updatePositionDataSend_
private

Container that keeps a list of MPIParticlePositions that are being send to other domains.

Referenced by constructor(), Domain(), finalisePositionAndVelocityUpdate(), and preparePositionAndVelocityUpdate().

◆ updateVelocityDataReceive_

std::vector<std::vector<MPIParticleVelocity> > Domain::updateVelocityDataReceive_
private

Container that keeps a list of MPIParticleVelocities that are being received by this domain.

Referenced by constructor(), Domain(), finalisePositionAndVelocityUpdate(), finaliseVelocityUpdate(), preparePositionAndVelocityUpdate(), prepareVelocityUpdate(), and updateParticleVelocity().

◆ updateVelocityDataSend_

std::vector<std::vector<MPIParticleVelocity> > Domain::updateVelocityDataSend_
private

Container that keeps a list of MPIParticleVelocities that are being send to other domains.

Referenced by constructor(), Domain(), finalisePositionAndVelocityUpdate(), finaliseVelocityUpdate(), preparePositionAndVelocityUpdate(), and prepareVelocityUpdate().


The documentation for this class was generated from the following files: