25#ifndef PARTICLE_RELOCATION_H
26#define PARTICLE_RELOCATION_H
38namespace communication {
41template<
typename T,
typename PARTICLETYPE>
45 using namespace descriptors;
46 static_assert(PARTICLETYPE::template providesNested<SURFACE,SURFACE_ID>(),
"Field SURFACE_ID has to be provided");
48 auto particle = particleSystem.
get(iP);
50 std::size_t idxSurface = particle.template getField<SURFACE,SURFACE_ID>();
53 auto& vectorOfIndicators = particleSystem.template getAssociatedData<
54 std::vector<std::unique_ptr<SIndicatorBaseType>>>();
55 auto sIndicatorPtr = vectorOfIndicators.at( idxSurface ).
get();
57 particle.template setField<SURFACE,SINDICATOR>( sIndicatorPtr );
62template<
typename T,
typename PARTICLETYPE>
65 std::uint8_t rawBuffer[])
68 auto& particleContainer = particleSystem.
get();
69 particleContainer.push_back();
71 std::size_t idxParticleNew = particleSystem.
size()-1;
72 auto particleNew = particleSystem.
get(idxParticleNew);
77 if constexpr( access::providesSurface<PARTICLETYPE>() ){
80 return particleNew.getId();
84template<
typename T,
typename PARTICLETYPE>
87 std::size_t idxParticle,
88 std::uint8_t rawBuffer[])
90 using namespace descriptors;
92 auto particle = particleSystem.
get(idxParticle);
94#ifdef VERBOSE_COMMUNICATION
95 auto globiCcentreLast = particle.template getField<PARALLELIZATION,IC>();
102#ifdef VERBOSE_COMMUNICATION
103 auto globiCcentre = particle.template getField<PARALLELIZATION,IC>();
105 if(globiCcentre!=globiCcentreLast){
107 std::cout << std::endl <<
"[Particle] "
109 << globiCcentreLast <<
"->" << globiCcentre <<
")"
110 <<
" at receiving at iC=" <<
"X"
111 <<
"(rank=" << rank <<
")" << std::endl;
117 if constexpr( access::providesSurface<PARTICLETYPE>() ){
120 return particle.getId();
127template<
typename T,
typename PARTICLETYPE>
130 std::uint8_t* rawBuffer )
132 using namespace descriptors;
134 std::size_t particleID;
140 if constexpr( access::providesSurface<PARTICLETYPE>() ){
142 if (particleSystem.
size()==0){
147 auto particleTmp = particleSystemTmp.
get(0);
150 std::size_t globalID = particleTmp.template getField<PARALLELIZATION,ID>();
157 for (std::size_t iP=0; iP<particleSystem.
size(); ++iP){
158 auto particle = particleSystem.
get(iP);
159 auto globalIDiP = particle.template getField<PARALLELIZATION,ID>();
160 if (globalIDiP==globalID){
181template<
typename T,
typename PARTICLETYPE>
185 int globiC,
int globiCdest,
186 std::multimap<
int,std::unique_ptr<std::uint8_t[]>>& rankDataMapRelocationInter,
187 std::vector<std::unique_ptr<std::uint8_t[]>>& dataListRelocationIntra,
188 std::size_t serialSize )
193 std::unique_ptr<std::uint8_t[]> buffer(
new std::uint8_t[serialSize]{ });
200 int rankDest = loadBalancer.rank(globiCdest);
201 if (rank != rankDest){
203 rankDataMapRelocationInter.insert(std::make_pair(rankDest, std::move(buffer)));
206 dataListRelocationIntra.push_back(std::move(buffer));
209#ifdef VERBOSE_COMMUNICATION
210 auto globalID = particle.template getField<
212 std::cout << std::endl <<
"[Particle] SENDING";
213 if (rank != rankDest){ std::cout <<
"(inter)"; }
else { std::cout <<
"(intra)"; }
214 std::cout <<
" Particle"
215 <<
"(globalID=" << globalID <<
") "
216 <<
"from iC" << globiC <<
"(rank=" << rank <<
") to iC"
217 << globiCdest <<
"(rank=" << rankDest <<
")" << std::endl;
218 particle.template print<true>();
224template<
typename T,
typename PARTICLETYPE>
229 std::multimap<
int,std::unique_ptr<std::uint8_t[]>>& rankDataMapRelocationInter,
230 std::vector<std::unique_ptr<std::uint8_t[]>>& dataListRelocationIntra,
239 const int globiCcentre = particle.template getField<descriptors::PARALLELIZATION,descriptors::IC>();
242 [&](
const int globiCdest){
244 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
251template<
typename T,
typename PARTICLETYPE>
255 std::multimap<
int,std::unique_ptr<std::uint8_t[]>>& rankDataMapRelocationInter,
256 std::vector<std::unique_ptr<std::uint8_t[]>>& dataListRelocationIntra,
259 using namespace descriptors;
260 using namespace particles::access;
261 constexpr unsigned D = PARTICLETYPE::d;
275 int globiCcentreLast= -1;
276 if constexpr( providesSurface<PARTICLETYPE>() ){
277 globiCcentreLast = particle.template getField<PARALLELIZATION,IC>();
282 periodicity, particle.template getField<GENERAL,POSITION>());
284 int globiCcentre = -1;
286 const bool particleCentreInDomain = cuboidGeometry.getC(position, globiCcentre);
299 particle.template setField<GENERAL, POSITION>(position);
312 if constexpr( providesSurface<PARTICLETYPE>() ){
313 particle.template setField<PARALLELIZATION,IC>(globiCcentre);
317 if (particleCentreInDomain){
322 if (globiCcentre == globiC){
324 if constexpr( providesSurface<PARTICLETYPE>() ){
326 rankDataMapRelocationInter, dataListRelocationIntra, serialSize, periodicity );
331 if constexpr( providesSurface<PARTICLETYPE>() ){
336 if(globiCcentre!=globiCcentreLast){
337#ifdef VERBOSE_COMMUNICATION
339 std::cout << std::endl <<
"[Particle] "
341 << globiCcentreLast <<
"->" << globiCcentre <<
")"
342 <<
" at sending from iC=" << globiC
343 <<
"(rank=" << rank <<
")" << std::endl;
348 particle, globiC, globiCcentre,
349 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
351 if constexpr( providesSurface<PARTICLETYPE>() ){
355 particle, globiCcentre, globiC,
356 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
360 rankDataMapRelocationInter, dataListRelocationIntra, serialSize, periodicity );
367 particle, globiC, globiCcentre,
368 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
370 particle.template setField<GENERAL,INVALID>(
true);
375 particle.template setField<GENERAL,INVALID>(
true);
378 auto globalID = particle.template getField<PARALLELIZATION,ID>();
379 std::cout <<
">>>> WARNING: Particle " << globalID
380 <<
" lost domain at iC="<< globiC
381 <<
" (rank=" << rank <<
") <<<<" << std::endl;
388 std::multimap<
int,std::unique_ptr<std::uint8_t[]>>& rankDataMap,
389 std::map<
int, std::vector<std::uint8_t>>& rankDataMapSorted,
390 std::size_t serialSize )
393 for (
auto& rankDataPair : rankDataMap) {
395 int rankDest = rankDataPair.first;
396 std::uint8_t* buffer = rankDataPair.second.get();
399 rankDataMapSorted[rankDest].insert(
400 rankDataMapSorted[rankDest].end(),
402 buffer + serialSize );
406#ifdef PARALLEL_MODE_MPI
409 std::map<
int, std::vector<std::uint8_t> >& rankDataMapSorted,
410 const std::unordered_set<int>& availableRanks,
411 const std::size_t serialSize,
417 int noRelevantRanks = availableRanks.size();
420 mpiNbHelper.
allocate(noRelevantRanks);
423 for (
int rankEval : availableRanks) {
426 rankDataMapSorted[rankEval].data(),
427 rankDataMapSorted[rankEval].size(),
441template<
typename T,
typename PARTICLETYPE>
444 std::vector<std::vector<std::size_t>>& receivedLocalIDs,
447 using namespace descriptors;
454 forParticlesInSuperParticleSystem<T,PARTICLETYPE,conditions::valid_particle_surfaces>(
460 int lociC = loadBalancer.loc(globiC);
463 std::size_t locId = particle.
getId();
465#ifdef VERBOSE_COMMUNICATION
466 std::cout <<
"ReceivedLocalIDs:";
467 for (
int i=0; i<receivedLocalIDs[lociC].size(); ++i){
468 auto idPrint = receivedLocalIDs[lociC][i];
469 std::cout << idPrint;
470 if (i<receivedLocalIDs.size()){ std::cout <<
","; }
472 std::cout << std::endl;
476 if( std::find(receivedLocalIDs[lociC].begin(),receivedLocalIDs[lociC].end(),
477 locId) == receivedLocalIDs[lociC].end()){
479 particle.template setField<GENERAL,INVALID>(
true);
481#ifdef VERBOSE_COMMUNICATION
483 std::size_t globalID = particle.template getField<PARALLELIZATION,ID>();
484 std::cout << std::endl <<
"[Particle] "
485 <<
"INVALIDATING Particle"
486 <<
"(globalID=" << globalID <<
") "
487 <<
"on iC" << globiC <<
"(rank=" << rank <<
")" << std::endl;
488 particle.template print<true>();
516template<
typename T,
typename PARTICLETYPE>
519 std::vector<std::vector<std::size_t>>& receivedLocalIDs,
521 std::uint8_t* rawBuffer )
523 using namespace descriptors;
527 deserializeIcDest<T,PARTICLETYPE>( globiCdest,rawBuffer );
534 if (globiC == globiCdest){
537 [[maybe_unused]] std::size_t particleID =
539 particleSystem, rawBuffer);
542 if constexpr( access::providesSurface<PARTICLETYPE>() ){
543 receivedLocalIDs[iC].push_back(particleID);
546#ifdef VERBOSE_COMMUNICATION
548 auto particle = particleSystem.
get(particleID);
549 std::size_t globalID = particle.template getField<PARALLELIZATION,ID>();
550 std::cout << std::endl <<
"[Particle] RECEIVING";
551 if (rankOrig != rank){ std::cout <<
"(inter)"; }
else { std::cout <<
"(intra)"; }
552 std::cout <<
" Particle"
553 <<
"(globalID=" << globalID <<
") "
554 <<
"from iC" <<
"X" <<
"(rank=" << rankOrig <<
") to iC"
555 << globiCdest <<
"(rank=" << rank <<
")" << std::endl;
556 particle.template print<true>();
566#ifdef PARALLEL_MODE_MPI
573 const std::unordered_set<int>& availableRanks,
574 std::size_t serialSize,
580 for (
int rankOrig : availableRanks) {
584 std::vector<std::uint8_t> recv_buffer(noBytesReceived);
585#ifdef VERBOSE_COMMUNICATION
587 std::cout <<
"Serial(rank=" << rank <<
"): "
588 <<
"noBytesToBeReceived=" << noBytesReceived <<
"; " << std::endl;
598 for (
unsigned iByte=0; iByte < noBytesReceived; iByte += serialSize) {
600 std::uint8_t* rawBuffer = &recv_buffer[iByte];
602 f( rankOrig, rawBuffer );
603#ifdef VERBOSE_COMMUNICATION
605 std::cout <<
"Serial(rank=" << rank <<
"): "
606 <<
"noBytesReceived=" << noBytesReceived <<
"; "
607 <<
"iByte=" << iByte << std::endl;
620template<
typename T,
typename PARTICLETYPE>
623 std::vector<std::unique_ptr<std::uint8_t[]>>& dataListRelocationIntra,
624 std::size_t serialSize,
625 MPI_Comm particleDistributionComm,
629 using namespace particles::access;
637 std::vector<std::vector<std::size_t>> receivedLocalIDs(
638 loadBalancer.size());
641 for (
auto& buffer : dataListRelocationIntra ){
643 std::uint8_t* rawBuffer = buffer.get();
652 particleDistributionComm, mpiNbHelper,
653 [&](
int rankOrig, std::uint8_t* rawBuffer){
659 if constexpr( providesSurface<PARTICLETYPE>() ){
666template<
typename T,
typename PARTICLETYPE>
670#ifdef PARALLEL_MODE_MPI
671 MPI_Comm particleDistributionComm,
691 std::size_t serialSizeField = communicatable.size(index);
692 serialSize += serialSizeField;
695 std::multimap<int,std::unique_ptr<std::uint8_t[]>> rankDataMapRelocationInter;
696 std::vector<std::unique_ptr<std::uint8_t[]>> dataListRelocationIntra;
697 checkRelocation( sParticleSystem, physDeltaX, rankDataMapRelocationInter,
698 dataListRelocationIntra, serialSize, periodicity );
700#ifdef PARALLEL_MODE_MPI
709 std::map<int, std::vector<std::uint8_t> > rankDataMapSorted;
712 fillSendBuffer( rankDataMapRelocationInter, rankDataMapSorted, serialSize );
716 serialSize, particleDistributionComm, mpiNbHelper );
720 serialSize, particleDistributionComm, mpiNbHelper, periodicity );
724 <<
"ERROR: Invalidation treatement for sequential runs not implemented yet!"
731#ifdef PARALLEL_MODE_MPI
733template<
typename DATA>
735 std::unordered_set<int>& availableRanks,
737 MPI_Comm commGroup = MPI_COMM_WORLD)
741 const int serialSize = communicatable.size();
744 serialSize, commGroup, mpiNbHelper,
745 [&](
int rankOrig, std::uint8_t* rawBuffer){
747 communicatable.deserialize( rawBuffer );
749 dataVector.push_back(data);
SoA storage for instances of a single FIELD.
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
auto & get()
Expose container.
constexpr std::size_t size()
Size of ParticleSystem.
std::size_t getId() const
Return memory ID of the currently represented particle.
SuperStructure< T, PARTICLETYPE::d > & getSuperStructure()
const std::unordered_set< int > & getExtendedNeighbourRanks()
std::size_t getSerialSize() const
void iSend(T *buf, int count, int dest, MPI_Request *request, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Sends data at *buf, non blocking.
int getRank() const
Returns the process ID.
std::size_t probeReceiveSize(int source, MPI_Datatype type, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Probe size of incoming message.
void waitAll(MpiNonBlockingHelper &mpiNbHelper)
Complete a series of non-blocking MPI operations.
void receive(T *buf, int count, int source, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Receives data at *buf, blocking.
Helper class for non blocking MPI communication.
void allocate(unsigned i)
Allocates memory.
MPI_Request * get_mpiRequest(int i=0) const
Get the specified request object.
Vector< T, PARTICLETYPE::d > getPosition(Particle< T, PARTICLETYPE > particle)
void receiveAndExecuteForData(const std::unordered_set< int > &availableRanks, std::size_t serialSize, MPI_Comm Comm, singleton::MpiNonBlockingHelper &mpiNbHelper, F f)
void forSystemsInSuperParticleSystem(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
std::size_t insertSerializedParticle(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t idxParticle, std::uint8_t rawBuffer[])
void assignParticleToIC(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::vector< std::size_t > > &receivedLocalIDs, int rankOrig, std::uint8_t *rawBuffer)
void collectDataAndAppendVector(std::vector< DATA > &dataVector, std::unordered_set< int > &availableRanks, singleton::MpiNonBlockingHelper &mpiNbHelper, MPI_Comm commGroup=MPI_COMM_WORLD)
std::unordered_set< int > getSurfaceTouchingICs(CuboidGeometry< T, D > &cuboidGeometry, Vector< T, D > position, T circumRadius, const Vector< bool, D > &periodicity, int globiC, F f=[](int){})
Get a set of surface touching iCs (that are not globiC) Allows to run an optional function per unique...
void updateParticleCuboidDistribution(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T physDeltaX, MPI_Comm particleDistributionComm, const Vector< bool, PARTICLETYPE::d > &periodicity)
std::size_t appendSerializedParticle(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t rawBuffer[])
void sendMappedData(std::map< int, std::vector< std::uint8_t > > &rankDataMapSorted, const std::unordered_set< int > &availableRanks, const std::size_t serialSize, MPI_Comm Comm, singleton::MpiNonBlockingHelper &mpiNbHelper)
void fillSendBuffer(std::multimap< int, std::unique_ptr< std::uint8_t[]> > &rankDataMap, std::map< int, std::vector< std::uint8_t > > &rankDataMapSorted, std::size_t serialSize)
void updateSurfacePtr(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t iP)
void checkInvalidationOnReceival(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::vector< std::size_t > > &receivedLocalIDs, const Vector< bool, PARTICLETYPE::d > &periodicity)
void receiveParticles(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::unique_ptr< std::uint8_t[]> > &dataListRelocationIntra, std::size_t serialSize, MPI_Comm particleDistributionComm, singleton::MpiNonBlockingHelper &mpiNbHelper, const Vector< bool, PARTICLETYPE::d > &periodicity)
void forParticlesInSuperParticleSystem(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
void prepareRelocation(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, Particle< T, PARTICLETYPE > &particle, int globiC, int globiCdest, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &rankDataMapRelocationInter, std::vector< std::unique_ptr< std::uint8_t[]> > &dataListRelocationIntra, std::size_t serialSize)
std::size_t attachSerializedParticle(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t *rawBuffer)
void checkRelocation(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T physDeltaX, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &rankDataMapRelocationInter, std::vector< std::unique_ptr< std::uint8_t[]> > &dataListRelocationIntra, std::size_t serialSize, const Vector< bool, PARTICLETYPE::d > &periodicity)
void deserializeIcDestAndParticle(int &globiCdest, Particle< T, PARTICLETYPE > &particle, std::uint8_t *bufferiCandParticle)
T applyPeriodicityToPosition(const bool isPeriodic, T position, const T max, const T min)
void serializeIcDestAndParticle(int globiCdest, Particle< T, PARTICLETYPE > &particle, std::uint8_t *bufferiCandParticle)
void checkSurfaceRelocation(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T physDeltaX, Particle< T, PARTICLETYPE > &particle, int globiC, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &rankDataMapRelocationInter, std::vector< std::unique_ptr< std::uint8_t[]> > &dataListRelocationIntra, std::size_t serialSize, const Vector< bool, PARTICLETYPE::d > &periodicity)
T evalCircumRadius(T const contactDetectionDistance, T const circumRadius, T const epsilon)
Top level namespace for all of OpenLB.
std::conditional_t< D==2, SmoothIndicatorF2D< T, T, PARTICLE >, SmoothIndicatorF3D< T, T, PARTICLE > > SmoothIndicatorF