51 #ifdef DEBUG_CONSTRUCTOR
52 std::cout<<
"Domain::Domain() finished"<<std::endl;
62 Domain::Domain(std::vector<unsigned> globalMeshIndex) : globalMeshIndex_(std::move(globalMeshIndex))
65 #ifdef DEBUG_CONSTRUCTOR
66 std::cout<<
"Domain::Domain() finished"<<std::endl;
87 unsigned long numberOfNeighbours = 27;
92 boundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours, std::vector<BaseParticle*>(0));
94 std::vector<BaseParticle*>(0));
96 std::vector<BaseParticle*>(0));
98 std::vector<BaseInteraction*>(0));
113 #ifdef DEBUG_CONSTRUCTOR
114 std::cout<<
"Domain::Domain(const Domain &b) finished"<<std::endl;
123 #ifdef DEBUG_DESTRUCTOR
124 std::cout <<
"Domain::~Domain() finished"<<std::endl;
141 int numberOfNeighbours = 27;
146 boundaryParticleList_ = std::vector<std::vector<BaseParticle*> >(numberOfNeighbours, std::vector<BaseParticle*>(0));
148 std::vector<BaseParticle*>(0));
150 std::vector<BaseParticle*>(0));
152 std::vector<BaseInteraction*>(0));
188 logger(
WARN,
"[Domain::read] should not be called");
199 logger(
WARN,
"[Domain::write] should not be called");
223 logger(
ERROR,
"[MercuryMPI ERROR]: min is larger than max. (%,%)", min, max);
244 middle_.
X = minClosed + (maxClosed - minClosed) / 2.0;
249 middle_.
Y = minClosed + (maxClosed - minClosed) / 2.0;
254 middle_.
Z = minClosed + (maxClosed - minClosed) / 2.0;
257 logger(
ERROR,
"Direction is not a valid direction. (%)", direction);
268 void Domain::setBounds(std::vector<double> domainMin, std::vector<double> domainMax,
bool computeMiddle)
278 for (
int i = 0;
i < 3;
i++)
402 for (
unsigned i = 0;
i < 3;
i++)
457 std::vector<unsigned> globalMeshMultiplier = {1,
468 for (
int i = -1;
i < 2;
i++)
470 for (
int j = -1; j < 2; j++)
472 for (
int k = -1; k < 2; k++)
475 localIndex =
i + 3 * j + 9 * k + 13;
500 return i + 3 * j + 9 * k + 13;
517 return {localIndex%3, (localIndex/3)%3, (localIndex/9)%3};
533 if (particle->getId() == identification)
556 std::vector<int> boundaryIndex(3);
560 for (
int d = 0; d < 3; d++)
566 boundaryIndex[d] = -1;
572 boundaryIndex[d] = 1;
575 return boundaryIndex;
582 for (
int i = 0;
i < 3; ++
i)
584 if (localIndex[
i]!=0 && boundaryIndex[
i]!=localIndex[
i]) {
600 std::vector<int> localMeshIndex(3);
607 for (
unsigned d = 0; d < 3; d++)
610 if (numberOfDomains[d] == 1)
613 for (
int i = -1;
i < 2;
i++)
616 for (
int j = -1; j < 2; j++)
619 for (
int k = -1; k < 2; k++)
625 if (localMeshIndex[d] != 0)
638 std::vector<int> boundaryIndex(3);
639 for (
int d = 0; d < 3; d++)
645 boundaryIndex[d] = -1;
651 boundaryIndex[d] = 1;
656 for (
int d = 0; d < 3; d++)
659 if (boundaryIndex[d] != 0)
662 for (
int i = -1;
i < 2;
i++)
664 for (
int j = -1; j < 2; j++)
666 for (
int k = -1; k < 2; k++)
668 localMeshIndex = {
i, j, k};
671 localMeshIndex[d] = boundaryIndex[d];
706 unsigned int complexity = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
707 unsigned int list_complexity = 0;
708 for (
int d = 0; d < 3; d++)
710 list_complexity += std::abs(boundaryIndex[d]);
716 switch (list_complexity)
732 for (
int d = 0; d < 3; d++)
734 std::vector<int> localMeshIndex = {0, 0, 0};
735 localMeshIndex[d] = boundaryIndex[d];
737 if (localMeshIndex[d] != 0)
752 for (
int d = 0; d < 3; d++)
754 std::vector<int> localMeshIndex = {0, 0, 0};
756 localMeshIndex[d] = boundaryIndex[d];
761 for (
int d = 0; d < 3; d++)
763 std::vector<int> localMeshIndex = boundaryIndex;
765 localMeshIndex[d] = 0;
775 logger(
INFO,
"boundaryIndex : %,%,% | list_complexity: %", boundaryIndex[0], boundaryIndex[1], boundaryIndex[2],
777 logger(
ERROR,
"Particle is in contact with the wrong number of boundaries");
833 std::vector<BaseInteraction*> interactions = newBoundaryParticle->getInteractions();
841 if (newBoundaryParticle == particleP)
851 if (distance <= particleP->getMaxInteractionRadius())
869 Mdouble sumOfInteractionRadii =
871 if (distanceSquared < (sumOfInteractionRadii * sumOfInteractionRadii))
889 Mdouble sumOfInteractionRadii =
891 if (distanceSquared < (sumOfInteractionRadii * sumOfInteractionRadii))
927 unsigned int indexInteraction = 0;
962 newParticles.push_back(pGhost);
982 particle->setInMPIDomain(
true);
1004 unsigned int identificationP;
1005 unsigned int identificationI;
1006 bool isWallInteraction;
1011 l, identificationP, identificationI,
1012 isWallInteraction, timeStamp);
1015 l, identificationP, identificationI,
1016 isWallInteraction, timeStamp);
1023 if (particle->getId() == identificationP)
1026 idOther = identificationI;
1030 if (particle->getId() == identificationI)
1033 idOther = identificationP;
1037 if (pGhost ==
nullptr)
1039 logger(
WARN,
"In Domain::processReceivedInteractionData: pGhost (id %) is nullptr, the interaction data is not copied. Two particles possibly moved into domain simultaneously.", identificationP);
1044 if (isWallInteraction)
1055 std::vector<BaseParticle*> interactingParticleList;
1062 if (p2->getId() == idOther)
1068 if (otherParticle ==
nullptr) {
1071 if (particle->getId() == idOther) {
1072 otherParticle = particle;
1076 if (otherParticle ==
nullptr) {
1078 "In Domain::processReceivedInteractionData: otherParticle (id %) is nullptr, the interaction data with pGhost (id %) is not copied. Two particles possibly moved into domain simultaneously. nt = %",
1079 identificationI, identificationP,
getHandler()->getDPMBase()->getNumberOfTimeSteps());
1086 if (otherParticle->
getId() < pGhost->
getId()) {
1097 std::stringstream s;
1098 std::stringstream m;
1099 for (
auto p :
getHandler()->getDPMBase()->particleHandler) {
1100 if (p->isMPIParticle())
1101 m << std::setw(4) << p->getId();
1103 s << std::setw(4) << p->getId();
1105 logger(
INFO,
"Particles %, MPI %",s.str(),m.str());
1120 unsigned localIndexNeighbour)
1129 logger.assert_debug(tagSend > 0,
"Send tag is wrong. Tag: %", tagSend);
1130 logger.assert_debug(tagReceive > 0,
"Receive tag is wrong. Tag: %", tagReceive);
1131 logger.assert_debug(processor >= 0,
"Processor is wrong. processor: %", processor);
1163 for (
int localIndex : boundaryList_)
1203 for (
int localIndex : boundaryList_)
1268 std::vector<BaseParticle*> newParticles;
1311 std::vector<int> boundaryIndex;
1326 complexityNew = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
1329 logger(
VERBOSE,
"time: % | global index: % in list % | particle % | CURRENT DOMAIN - CHANGES "
1342 logger(
VERBOSE,
"time: % | global index: % in list % | particle % | CURRENT DOMAIN - TO NEIGHBOURING "
1346 ghostParticlesToBeDeleted.insert(particle);
1363 "time: % | global index: % in list % | particle % | NEIGHBOURING DOMAIN - TO CURRENT DOMAIN",
1377 "time: % | global index: % in list % | particle % | NEIGBOURING DOMAIN - TO OTHER DOMAIN",
1381 ghostParticlesToBeDeleted.insert(particle);
1390 complexityNew = boundaryIndex[0] + 3 * boundaryIndex[1] + 9 * boundaryIndex[2] + 13;
1394 "time: % | global index: % in list % | particle % | NEIGHBOURING DOMAIN - CHANGES COMPLEXITY",
1398 ghostParticlesToBeDeleted.insert(particle);
1415 unsigned int index = 0;
1419 "MPI particle lists are not in sync");
1422 particle->setPreviousPosition(particle->getPosition());
1425 if (std::is_base_of<MPILiquidFilmParticle,MPIParticle>())
1429 Vec3D displacement = particle->getPreviousPosition() - particle->getPosition();
1444 unsigned int index = 0;
1516 for (
int localIndex : boundaryList_)
1566 for (
int localIndex : boundaryList_)
1666 unsigned int count = 0;
1669 count += index.size();
1681 unsigned int count = 0;
1684 for (
auto& p : index)
1686 if (!p->isPeriodicGhostParticle())
1711 for (
auto& p : list)
1719 if (particle1 == particle2)
1759 for (
int i = 0;
i < list.size();
i++)
1761 if (list[
i] ==
nullptr)
1763 list[
i] = list.back();
void prepareBoundaryDataTransmission()
Prepares the MPI transmission of particle and interaction data from particles in particleHandler.
unsigned int getId() const
Returns the unique identifier of any particular object.
std::vector< void * > interactionDataSend_
Container that keeps a void array of all the interaction data that are being send to other domains...
std::vector< unsigned > numberOfParticlesReceive_
Counter that keeps track of the number of particles that are being received by this domain...
bool isInInnerDomain(BaseParticle *particle)
Check if the particle is in the current domain but not in the communication zone. ...
void disableBoundary(unsigned localIndex)
Disables a boundary of the domain with a neighbouring domain.
std::vector< bool > activeBoundaryList_
A list of flags corresponding to an inactive or active boundary.
void updateParticleVelocity(int localIndex)
Updates the velocity of particles which are flagged as MPIParticles.
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
static MPIContainer & Instance()
fetch the instance to be used for communication
std::vector< int > getLocalIndexInverse(int localMeshIndex)
Mdouble X
the vector components
void updateParticles(std::set< BaseParticle * > &ghostParticlesToBeDeleted)
This step updates all communication lists and particles in the communication zone.
void setBounds(std::vector< double > domainLeft, std::vector< double > domainRight, bool computeMiddle)
Sets the domain bounds.
void addParticle(BaseParticle *particle)
Initialises a single particle which is added during the simulation.
int getGlobalIndex()
Gets the global index of the domain.
bool inBoundary(BaseParticle *particle, int localIndex)
virtual void hGridGetInteractingParticleList(BaseParticle *obj, std::vector< BaseParticle * > &list)
Creates a list of neighbour particles obtained from the hgrid.
void setInMPIDomain(bool flag)
Flags the status of the particle if wether it is in the communication zone or not.
void collectInteractionData(int localIndex)
Collects the data of an interaction that has to be communicated to other processors.
int getRank()
Gets the rank associated with the assigned processorID.
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
Definition of different loggers with certain modules. A user can define its own custom logger here...
void constructor()
contructor of a domain
bool isInNewBoundaryParticleList(BaseParticle *object, int localIndex) const
void * createMPIInteractionDataArray(unsigned int numberOfInteractions) const
creates an empty MPIInteractionDataArray
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...
T * getObjectById(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
std::vector< unsigned > numNewInteractionsSend_
Counter that keeps track of the number of interactions that are being send to other domains...
std::vector< int > findNearbyBoundaries(BaseParticle *particle, Mdouble offset=0)
This function finds if a given particle is close to a given boundary.
Vec3D middle_
Middle of the closed domain.
std::vector< double > domainMin_
Minimum domain bounds in the x,y and z direction.
std::vector< unsigned > getGlobalMeshIndex()
Gets the global mesh index of the domain.
It is an abstract base class due to the purely virtual functions declared below. Even if the function...
std::vector< int > localIndexToGlobalIndexTable_
look-up table to get the global index given a local domain index
const std::complex< Mdouble > i
void flushParticles(std::set< BaseParticle * > &toBeDeletedList)
Particles that are going to be deleted from the simulation are flushed out of the communication bound...
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.
virtual BaseInteraction * getInteractionWith(BaseParticle *P, unsigned timeStamp, InteractionHandler *interactionHandler)=0
Returns the interaction between this object and a given BaseParticle.
void addNewParticles()
Initialises the MPIParticles by communicating newly found particles.
void addGhostObject(int fromPrcessor, int toProcessor, BaseParticle *p)
Adds a ghost particle located at fromProcessor to toProcessor.
void setCommunicationComplexity(unsigned complexity)
Set the communication complexity of the particle.
BaseParticle * findParticleInList(unsigned int identification, std::vector< BaseParticle * > particleList)
Searches for a particle with a specific id in a list of particles.
Mdouble getSumOfInteractionRadii(const BaseParticle *particle) const
returns the sum of the radii plus the interactionDistance
std::vector< int > localIndexToProcessorList_
look-up table to get the processor of the domain given a local domain index
bool containsParticle(BaseParticle *particle, Mdouble offset=0.0)
Check to see if a given particle is within the current domain.
Domain()
Default Domain constructor.
void findNewMPIInteractions()
Finds interactions that have to be send over to another domain.
void performBoundaryDataTransmission()
Collects data to be transmitted and then performs the transmission of the data.
std::vector< std::vector< BaseInteraction * > > newInteractionList_
Array that queues interactions that need to be transmitted.
Mdouble getInteractionDistance()
Gets the interaction distance of the domain handler.
void deleteMPIInteractionDataArray(void *dataArray)
deletes an MPIInteractionDataArray
bool isInGreaterDomain(BaseParticle *particle)
Check to see if a given particle is in the current domain or in neighbouring communication zones...
void finaliseVelocityUpdate()
Processes particle velocity data for ghost particles.
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataReceive_
Container that keeps a list of MPIParticleVelocities that are being received by this domain...
void updateStatus(std::set< BaseParticle * > &ghostParticlesToBeDeleted)
Updates particles that are not in the current domain and communicates newly added particles...
Mdouble getLengthSquared() const
Calculates the squared length of this Vec3D: .
Stores information about interactions between two interactable objects; often particles but could be ...
std::vector< unsigned > globalMeshIndex_
Vector containing the global mesh indices i,j,k.
std::vector< int > boundaryList_
A list of indices of all the active boundaries.
unsigned int getNumberOfTrueMPIParticles()
Obtains the number of particles in the particleHandler that are MPIParticles, but NOT periodic partic...
void setComponent(int index, double val)
Sets the requested component of this Vec3D to the requested value.
void copyDataFromMPIParticleToParticle(MPIParticle *bP, BaseParticle *p, ParticleHandler *particleHandler)
Copies data from an MPIParticle class to a BaseParticle and sets the particleHandler and species...
std::vector< void * > interactionDataReceive_
Container that keeps a void array of all the interaction data that is being received by this domain...
void setRange(Direction direction, Mdouble min, Mdouble max)
Sets the domain range in a given direction.
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
void updateParticlePosition(int localIndex)
Updates the position of particles which are flagged as MPIParticles.
void write(std::ostream &os) const override
This function does nothing.
std::vector< std::vector< MPIParticlePosition > > updatePositionDataSend_
Container that keeps a list of MPIParticlePositions that are being send to other domains.
void processReceivedInteractionData(unsigned index, std::vector< BaseParticle * > &newParticles)
Processes the received interactions from newly added mpi particles.
static BaseParticle * newParticle()
MPIParticle copyDataFromParticleToMPIParticle(BaseParticle *p)
Copies data from a SuperQuadricParticle to an MPIParticle class and returns this. ...
void cleanCommunicationLists()
Removes nullptrs from boundaryParticleList_ and boundaryParticleListNeighbour_.
void preparePositionAndVelocityUpdate()
Function that sends particle position and velocity data for ghost particles to other processors...
bool isInMPIDomain()
Indicates if the particle is in the communication zone of the mpi domain.
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...
void finalisePositionAndVelocityUpdate(std::set< BaseParticle * > &ghostParticlesToBeDeleted)
processes position and velocity data for ghost particles
void findNewMPIParticles(const ParticleHandler &particleHandler)
Function that finds new particles in the particle handler that should be added to the communication l...
void setPreviousPosition(const Vec3D &pos)
Sets the particle's position in the previous time step.
MercuryMPITag
An enum that facilitates the creation of unique communication tags in the parallel code...
std::vector< double > getDomainMin()
Gets the minimum domain bounds.
Mdouble getComponent(int index) const
Returns the requested component of this Vec3D.
std::vector< std::vector< BaseParticle * > > boundaryParticleListNeighbour_
a list of ghost particles on the current domain, which are real on the neighbour domain ...
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created...
void cleanCommunicationList(std::vector< BaseParticle * > &list)
Removes nullptr's from a given particle list.
Container to store Interaction objects.
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
std::vector< std::vector< MPIParticleVelocity > > updateVelocityDataSend_
Container that keeps a list of MPIParticleVelocities that are being send to other domains...
DomainHandler * getHandler() const
Gets the domainHandler.
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.
void sendAndReceiveCount(MercuryMPITag tag, unsigned &countReceive, unsigned &countSend, unsigned localIndexNeighbour)
A symmetric communication between two domains exchanging a send/recieve count.
std::vector< unsigned > numberOfParticlesSend_
Counter that keeps track of the number of particles that are being send to other domains.
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...
DomainHandler * domainHandler_
Pointer to the domain's DomainHandler container.
void collectBoundaryParticleData(int localIndex)
collects the data of a particle that has to be communicated to other processors
void read(std::istream &is) override
This function does nothing.
std::vector< double > getDomainMax()
Gets the maximum domain bounds.
void finaliseBoundaryDataTransmission()
This function processes the transmitted data.
void setRank(int rank)
Sets the rank associated with the assigned processorID.
void findNewMPIParticle(BaseParticle *particle)
Function that check if a given particle should be added to the communication lists.
InteractionHandler interactionHandler
An object of the class InteractionHandler.
bool isPeriodicGhostParticle() const
Indicates if this particle is a ghost in the periodic boundary.
Container to store all BaseParticle.
MPIParticlePosition copyPositionFrom(BaseParticle *particle)
Copies the position from a particle to an MPIParticlePosition class.
~Domain() override
Destructor, destroys the domain.
WallHandler wallHandler
An object of the class WallHandler. Contains pointers to all the walls created.
std::vector< std::vector< BaseParticle * > > newBoundaryParticleList_
Array that queues particles that need to be transmitted.
The simulation can be subdivided into Domain's used in parallel code.
void sync()
Process all pending asynchronous communication requests before continuing.
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.
Vec3D getMiddle() const
Gives the middle of the domain.
void createLookUpTable()
Create a look up table between local index system to global index system.
bool isInCommunicationZone(BaseParticle *particle)
Check if the particle is in the communication zone of the current domain.
unsigned getCommunicationComplexity()
Obtains the communication complexity of the particle.
void setMPIParticle(bool flag)
Flags the mpi particle status.
void disableBoundaries()
disables all domain boundaries that have no neighbour
Container to store all Domain.
static Mdouble getLengthSquared(const Vec3D &a)
Calculates the squared length of a Vec3D: .
void updateVelocity()
Updates MPI particle velocity at the half-time step.
std::string getName() const override
Returns the name of the object.
Direction
An enum that indicates the direction in Cartesian coordinates.
std::vector< std::vector< MPIParticlePosition > > updatePositionDataReceive_
Container that keeps a list of MPIParticlePositions that are being received by this domain...
int globalIndex_
Global index of the domain in the mesh.
std::vector< unsigned > getNumberOfDomains()
Gets the number of domains in the domain handler.
int rank_
Rank of the domain which identifies to which processor it belongs.
std::vector< double > domainMax_
Maximum domain bounds in the x,y and z direction.
Defines the basic properties that a interactable object can have.
std::vector< std::vector< MPIParticle > > boundaryParticleDataReceive_
Container that keeps a list of MPIParticles that are being received by this domain.
virtual void setMPIInteraction(void *interactionDataArray, unsigned int index, bool resetPointers)
virtual void hGridUpdateMove(BaseParticle *, Mdouble)
void prepareVelocityUpdate()
Function that sends particle velocity data for ghost particles.
virtual Domain * copy() const
Function that creates a copy of this current domain, using the copy constructor.
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 communcation bou...
T * getLastObject()
Gets a pointer to the last Object in this BaseHandler.
std::vector< std::vector< BaseParticle * > > boundaryParticleList_
A list of boundary particles in the communication zone that are ghost particles on other domains...
void processSentBoundaryParticles(unsigned index)
Bookkeep the newly send particles.
int getLocalIndex(int i, int j, int k)
return the local index of a domain given local mesh indices i,j and k
MPIParticleVelocity copyVelocityFrom(BaseParticle *particle)
Copies the velocity from a particle to an MPIParticleVelocity class.
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
std::vector< unsigned > numNewInteractionsReceive_
Counter that keeps track of the number of interactions that are being received by this domain...
Mdouble getTime() const
Returns the current simulation time.
void setHandler(DomainHandler *handler)
Sets the domainHandler.
void addParticlesToLists(BaseParticle *particle, std::vector< std::vector< BaseParticle * > > &list)
Function that adds the particles to the approriate boundary list.
std::vector< bool > getActiveBoundaryList()
Returns a list of boundaries that are active in mpi communication.
unsigned int getNumberOfMPIParticles()
Obtains the number of particles in the particleHandler that are MPIParticles.
void setGlobalMeshIndex(std::vector< unsigned > globalMeshIndex)
Sets the global mesh index of theh domain.
std::vector< std::vector< MPIParticle > > boundaryParticleDataSend_
Container that keeps a list of MPIParticles that are being send to other domains. ...