OpenLB 1.7
Loading...
Searching...
No Matches
Classes | Functions
olb::particles::communication Namespace Reference

Classes

struct  ParticleCommunicator
 

Functions

template<typename T , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
std::unordered_set< int > evalDestRanks (contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, const std::size_t globalParticleID)
 evaluates ranks that need the new particle data
 
template<typename T , typename PARTICLETYPE >
void communicateEquationsOfMotionResultsIntra (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const std::size_t &pID, const Vector< T, PARTICLETYPE::d > &position, const Vector< T, PARTICLETYPE::d > &velocity, const Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > &angle, const Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > &angVelocity)
 
template<typename T , typename PARTICLETYPE , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
std::size_t evalEquationsOfMotionResults (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &dataMap)
 
template<typename T , typename PARTICLETYPE >
void receiveEquationsOfMotionResults (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, MPI_Comm equationsOfMotionComm, singleton::MpiNonBlockingHelper &mpiNbHelper)
 
template<typename T , typename PARTICLETYPE , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
void communicateEquationsOfMotionResults (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, MPI_Comm equationsOfMotionComm)
 
template<typename T , typename PARTICLETYPE >
void updateSurfacePtr (ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t iP)
 
template<typename T , typename PARTICLETYPE >
std::size_t appendSerializedParticle (ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t rawBuffer[])
 
template<typename T , typename PARTICLETYPE >
std::size_t insertSerializedParticle (ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t idxParticle, std::uint8_t rawBuffer[])
 
template<typename T , typename PARTICLETYPE >
std::size_t attachSerializedParticle (ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t *rawBuffer)
 
template<typename T , typename PARTICLETYPE >
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)
 
template<typename T , typename PARTICLETYPE >
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)
 
template<typename T , typename PARTICLETYPE >
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 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 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)
 
template<typename T , typename PARTICLETYPE >
void checkInvalidationOnReceival (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::vector< std::size_t > > &receivedLocalIDs, const Vector< bool, PARTICLETYPE::d > &periodicity)
 
template<typename T , typename PARTICLETYPE >
void assignParticleToIC (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::vector< std::size_t > > &receivedLocalIDs, int rankOrig, std::uint8_t *rawBuffer)
 
template<typename F >
void receiveAndExecuteForData (const std::unordered_set< int > &availableRanks, std::size_t serialSize, MPI_Comm Comm, singleton::MpiNonBlockingHelper &mpiNbHelper, F f)
 
template<typename T , typename PARTICLETYPE >
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)
 
template<typename T , typename PARTICLETYPE >
void updateParticleCuboidDistribution (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T physDeltaX, MPI_Comm particleDistributionComm, const Vector< bool, PARTICLETYPE::d > &periodicity)
 
template<typename DATA >
void collectDataAndAppendVector (std::vector< DATA > &dataVector, std::unordered_set< int > &availableRanks, singleton::MpiNonBlockingHelper &mpiNbHelper, MPI_Comm commGroup=MPI_COMM_WORLD)
 
template<typename T , typename PARTICLETYPE , unsigned forceDataSize>
void communicateSurfaceForce (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::map< std::size_t, Vector< T, forceDataSize > > &globalIdDataMap, MPI_Comm surfaceForceComm)
 
template<typename T , typename PARTICLETYPE , unsigned forceDataSize>
void assignSurfaceForce (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::map< std::size_t, Vector< T, forceDataSize > > &globalIdDataMap)
 
template<typename T , unsigned D, bool verbose = false>
std::vector< int > getNeighborCuboids (CuboidGeometry< T, D > &cuboidGeometry, unsigned offset, int globiC)
 Get neighbour cuboids.
 
template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > getNeighbourRanksFromCuboidNeighbourhood (SuperStructure< T, D > &superStructure, int rank, std::map< int, std::vector< int > > neighbourhood)
 Get neighbour ranks.
 
template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > getNeighbourRanksFromCuboidNeighbourhood (SuperStructure< T, D > &superStructure, int rank, const std::vector< std::unordered_set< int > > &neighbourhood)
 Get neighbour ranks.
 
template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > getNeighbourRanksFromCuboidNeighbourhood (SuperStructure< T, D > &superStructure, const std::vector< std::unordered_set< int > > &neighbourhood)
 Get neighbour ranks.
 
template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > getNeighbourRanks (SuperStructure< T, D > &superStructure, unsigned offset, int rank)
 Get neighbour ranks.
 
template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > getNeighbourRanks (SuperStructure< T, D > &superStructure, unsigned offset)
 Get neighbour ranks.
 
template<typename T , typename PARTICLETYPE >
std::size_t serializeIcDest (int globiCdest, std::uint8_t *bufferiCandParticle)
 
template<typename T , typename PARTICLETYPE >
void serializeIcDestAndParticle (int globiCdest, Particle< T, PARTICLETYPE > &particle, std::uint8_t *bufferiCandParticle)
 
template<typename T , typename PARTICLETYPE >
std::size_t deserializeIcDest (int &globiCdest, std::uint8_t *bufferRaw)
 
template<typename T , typename PARTICLETYPE >
void deserializeIcDestAndParticle (int &globiCdest, Particle< T, PARTICLETYPE > &particle, std::uint8_t *bufferiCandParticle)
 
template<typename T , typename PARTICLETYPE >
void checkCuboidSizes (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem)
 
template<typename T >
movePositionToStart (const T position, const T max, const T min)
 
template<typename T >
movePositionToEnd (const T position, const T max, const T min)
 
template<typename T >
applyPeriodicityToPosition (const bool isPeriodic, T position, const T max, const T min)
 
template<typename T , unsigned D>
Vector< T, D > getCuboidMin (const CuboidGeometry< T, D > &cuboidGeometry)
 Returns minimal coordinate of domain for periodic particle boundaries.
 
template<typename T , unsigned D>
Vector< T, D > getCuboidMax (const CuboidGeometry< T, D > &cuboidGeometry, const PhysR< T, D > &min)
 Returns maximal coordinate of domain for periodic particle boundaries.
 
template<typename T , unsigned D>
Vector< T, D > applyPeriodicityToPosition (const CuboidGeometry< T, D > &cuboidGeometry, const Vector< bool, D > &periodicity, PhysR< T, D > position)
 Updates a position if out of bounds and periodic setup is used.
 
template<typename T , unsigned D>
bool getCuboid (const CuboidGeometry< T, D > &cuboidGeometry, const Vector< bool, D > &periodicity, const PhysR< T, D > &position, int &iC)
 Function returns true if cuboid was found and gives iC.
 
template<typename T , typename PARTICLETYPE , typename F >
void forSystemsInSuperParticleSystem (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
 
template<typename T , typename PARTICLETYPE , typename PCONDITION = conditions::valid_particles, typename F >
void forParticlesInSuperParticleSystem (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
 
template<typename T , typename PARTICLETYPE , typename F >
void doForParticle (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, ParallelParticleLocator &locator, F f)
 
template<typename T , typename PARTICLETYPE , typename PCONDITION = conditions::valid_particle_centres, bool sync = true>
bool searchParticleGlobally (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::size_t globalIDrequested, std::size_t &localParticleID, int &globiC)
 Search particle in SuperParticleSystem by globalParticleID and return globiC if found.
 
template<typename T , unsigned D, typename F = std::function<void(int)>, bool domainWarning = false, bool checkDiscretePoints = false>
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 globiC.
 
template<typename T , typename PARTICLETYPE , typename F = std::function<void(int)>>
std::unordered_set< int > getSurfaceTouchingICs (SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, Vector< T, PARTICLETYPE::d > position, T circumRadius, const Vector< bool, PARTICLETYPE::d > &periodicity, int globiC, F f=[](int){})
 
template<typename T , unsigned D, typename F = std::function<void(int)>, bool domainWarning = false>
std::vector< int > getVectorOfSurfaceTouchingICs (CuboidGeometry< T, D > &cuboidGeometry, Vector< T, D > position, T circumRadius, const Vector< bool, D > &periodicity, int globiC, F f=[](int){})
 

Function Documentation

◆ appendSerializedParticle()

template<typename T , typename PARTICLETYPE >
std::size_t olb::particles::communication::appendSerializedParticle ( ParticleSystem< T, PARTICLETYPE > & particleSystem,
std::uint8_t rawBuffer[] )

Definition at line 63 of file relocation.h.

66{
67 //Extend particle container
68 auto& particleContainer = particleSystem.get();
69 particleContainer.push_back();
70 //Retrieve new particle
71 std::size_t idxParticleNew = particleSystem.size()-1;
72 auto particleNew = particleSystem.get(idxParticleNew);
73 //Deserialise particle
74 int globiCdest;
75 deserializeIcDestAndParticle(globiCdest,particleNew,rawBuffer);
76 //Update surface pointer
77 if constexpr( access::providesSurface<PARTICLETYPE>() ){
78 updateSurfacePtr( particleSystem, idxParticleNew );
79 }
80 return particleNew.getId();
81}
auto & get()
Expose container.
constexpr std::size_t size()
Size of ParticleSystem.
void updateSurfacePtr(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::size_t iP)
Definition relocation.h:42
void deserializeIcDestAndParticle(int &globiCdest, Particle< T, PARTICLETYPE > &particle, std::uint8_t *bufferiCandParticle)
Definition utilities.h:195

References deserializeIcDestAndParticle(), olb::particles::ParticleSystem< T, PARTICLETYPE >::get(), olb::particles::ParticleSystem< T, PARTICLETYPE >::size(), and updateSurfacePtr().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyPeriodicityToPosition() [1/2]

template<typename T >
T olb::particles::communication::applyPeriodicityToPosition ( const bool isPeriodic,
T position,
const T max,
const T min )

Definition at line 266 of file utilities.h.

267{
268 if(isPeriodic) {
269 if(position < min) {
270 position = movePositionToEnd(position, max, min);
271 }
272 else if(position > max) {
273 position = movePositionToStart(position, max, min);
274 }
275 }
276 return position;
277}
T movePositionToEnd(const T position, const T max, const T min)
Definition utilities.h:260

References olb::particles::isPeriodic(), movePositionToEnd(), and movePositionToStart().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyPeriodicityToPosition() [2/2]

template<typename T , unsigned D>
Vector< T, D > olb::particles::communication::applyPeriodicityToPosition ( const CuboidGeometry< T, D > & cuboidGeometry,
const Vector< bool, D > & periodicity,
PhysR< T, D > position )

Updates a position if out of bounds and periodic setup is used.

Definition at line 302 of file utilities.h.

306{
307 const PhysR<T,D> min = getCuboidMin<T,D>(cuboidGeometry);
308 const PhysR<T,D> max = getCuboidMax<T,D>(cuboidGeometry, min);
309
310 for(unsigned iD=0; iD<D; ++iD) {
311 position[iD] = applyPeriodicityToPosition(periodicity[iD],
312 position[iD], max[iD], min[iD]);
313 }
314
315 return position;
316}
Plain old scalar vector.
Definition vector.h:47
T applyPeriodicityToPosition(const bool isPeriodic, T position, const T max, const T min)
Definition utilities.h:266

References applyPeriodicityToPosition().

+ Here is the call graph for this function:

◆ assignParticleToIC()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::assignParticleToIC ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
std::vector< std::vector< std::size_t > > & receivedLocalIDs,
int rankOrig,
std::uint8_t * rawBuffer )

Definition at line 517 of file relocation.h.

522{
523 using namespace descriptors;
524
525 //Deserialize globiCdest
526 int globiCdest;
527 deserializeIcDest<T,PARTICLETYPE>( globiCdest,rawBuffer );
528
529 //Loop over ParticleSystems in SuperParticleSystem
530 forSystemsInSuperParticleSystem( sParticleSystem,
531 [&](ParticleSystem<T,PARTICLETYPE>& particleSystem, int iC,
532 int globiC){
533
534 if (globiC == globiCdest){
535
536 //Attach serialized particle to new particleSystem
537 [[maybe_unused]] std::size_t particleID =
539 particleSystem, rawBuffer);
540
541 //Add local particle iD to list (resolved only)
542 if constexpr( access::providesSurface<PARTICLETYPE>() ){
543 receivedLocalIDs[iC].push_back(particleID);
544 }
545
546#ifdef VERBOSE_COMMUNICATION
547 int rank = singleton::mpi().getRank();
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>();
557#endif
558
559 } //if (globiC == globiCdest)
560 }); //forSystemsInSuperParticleSystem
561}
void forSystemsInSuperParticleSystem(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
std::size_t attachSerializedParticle(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t *rawBuffer)
Definition relocation.h:128

References attachSerializedParticle(), forSystemsInSuperParticleSystem(), olb::particles::ParticleSystem< T, PARTICLETYPE >::get(), olb::singleton::MpiManager::getRank(), and olb::singleton::mpi().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ assignSurfaceForce()

template<typename T , typename PARTICLETYPE , unsigned forceDataSize>
void olb::particles::communication::assignSurfaceForce ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
std::map< std::size_t, Vector< T, forceDataSize > > & globalIdDataMap )

Definition at line 185 of file surfaceForce.h.

188{
189 using namespace descriptors;
190 //Retrieve dimension
191 constexpr unsigned D = PARTICLETYPE::d;
192 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
193 //Loop over particle systems
194 communication::forSystemsInSuperParticleSystem( sParticleSystem,
195 [&](ParticleSystem<T,PARTICLETYPE>& particleSystem, int iC,
196 int globiC){
197 //Loop over globalIdDataPairs
198 for ( auto globalIdDataPair : globalIdDataMap ){
199 //Loop over particles
200 // -! Lambda-expression unavailable due to break command
201 for (std::size_t iP=0; iP<particleSystem.size(); ++iP){
202 auto particle = particleSystem.get(iP);
203 //Only consider valid particle centres
204 if (conditions::valid_particle_centres::value(particle, globiC)){
205 //Retrieve globalIDs
206 std::size_t globalID = globalIdDataPair.first;
207 std::size_t globalIDiP = particle.template getField<PARALLELIZATION,ID>();
208 //Check whether globalID matches
209 if (globalIDiP==globalID){
210 //Retrieve force data
211 auto forceData = globalIdDataPair.second;
212 auto force = particle.template getField<FORCING,FORCE>();
213 auto torque = particle.template getField<FORCING,TORQUE>();
214 //Add force to particle
215 for (unsigned iDim=0; iDim<D; ++iDim) {
216 force[iDim] += forceData[iDim];
217 }
218 //Add torque to particle
220 torque += forceData[D];
221 }
222 else {
223 for (unsigned iDim=0; iDim<Drot; ++iDim) {
224 torque[iDim] += forceData[iDim+D];
225 }
226 }
227
228#ifdef VERBOSE_COMMUNICATION
229 int rank = singleton::mpi().getRank();
230 std::cout << "Assigned (on rank=" << rank
231 << "): force=" << force
232 << std::endl
233 << " "
234 << ", torque=" << torque
235 << ", globalID=" << globalID
236 << std::endl;
237#endif
238 //Update particle
239 particle.template setField<FORCING,FORCE>( force );
240 particle.template setField<FORCING,TORQUE>( torque );
241 //Break, since particle already found
242 break;
243 }
244 }
245 }
246 }
247 });
248}
Converts dimensions by deriving from given cartesian dimension D.

References forSystemsInSuperParticleSystem(), olb::particles::ParticleSystem< T, PARTICLETYPE >::get(), olb::singleton::MpiManager::getRank(), olb::singleton::mpi(), olb::particles::ParticleSystem< T, PARTICLETYPE >::size(), and olb::particles::conditions::valid_particle_centres::value().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ attachSerializedParticle()

template<typename T , typename PARTICLETYPE >
std::size_t olb::particles::communication::attachSerializedParticle ( ParticleSystem< T, PARTICLETYPE > & particleSystem,
std::uint8_t * rawBuffer )

Definition at line 128 of file relocation.h.

131{
132 using namespace descriptors;
133
134 std::size_t particleID;
135 //Check whether resolved (or subgrid)
136 //- subgrid has to be appended always, as valid particle data will not
137 // be present on new core due to previous direct invalidation
138 //- TODO: Check consistency, as for now, invalidated slots are considered
139 // for resolved, but not for sub grid particles
140 if constexpr( access::providesSurface<PARTICLETYPE>() ){
141 //Attach serialized particle (either at end or at existing index)
142 if (particleSystem.size()==0){
143 particleID = appendSerializedParticle( particleSystem, rawBuffer );
144 } else {
145 //Create temporary particle system to retrieve global id
146 ParticleSystem<T,PARTICLETYPE> particleSystemTmp(1);
147 auto particleTmp = particleSystemTmp.get(0);
148 int globiCdummy;
149 deserializeIcDestAndParticle(globiCdummy,particleTmp,rawBuffer);
150 std::size_t globalID = particleTmp.template getField<PARALLELIZATION,ID>();
151 //Check whether particle already existing
152 // -! Lambda-expression unavailable due to break command
153 bool found=false;
154 //Loop over particles
155 //- including invalid slots, as they are revalidated
156 // anyways when inserting particle data)
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){
161 particleID = insertSerializedParticle( particleSystem, iP, rawBuffer );
162 found=true;
163 break;
164 }
165 }
166 if (!found){
167 particleID = appendSerializedParticle( particleSystem, rawBuffer );
168 }
169 }
170 } else { //if constexpr ( access::providesSurface<PARTICLETYPE>() )
171 //Attach serialized particle
172 particleID = appendSerializedParticle( particleSystem, rawBuffer );
173 }
174 return particleID;
175}
std::size_t appendSerializedParticle(ParticleSystem< T, PARTICLETYPE > &particleSystem, std::uint8_t rawBuffer[])
Definition relocation.h:63

References appendSerializedParticle(), deserializeIcDestAndParticle(), olb::particles::ParticleSystem< T, PARTICLETYPE >::get(), insertSerializedParticle(), and olb::particles::ParticleSystem< T, PARTICLETYPE >::size().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkCuboidSizes()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::checkCuboidSizes ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem)

Definition at line 213 of file utilities.h.

214{
215 constexpr unsigned D = PARTICLETYPE::d;
216 auto& cuboidGeometry = sParticleSystem.getSuperStructure().getCuboidGeometry();
217
218 const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR();
219
220 T maxCircumRadius{0};
221 communication::forParticlesInSuperParticleSystem(
222 sParticleSystem,
223 [&](Particle<T, PARTICLETYPE>& particle,
224 ParticleSystem<T, PARTICLETYPE>& particleSystem, int globiC) {
225 maxCircumRadius = util::max(maxCircumRadius,
226 particles::contact::evalCircumRadius(particle, physDeltaX));
227 });
228#ifdef PARALLEL_MODE_MPI
229 singleton::mpi().reduceAndBcast(maxCircumRadius, MPI_MAX,
230 singleton::mpi().bossId());
231#endif
232
233 int minCuboidExtent{std::numeric_limits<int>::max()};
234 for (int iC=0; iC<cuboidGeometry.getNc(); ++iC){
235 for(unsigned iD=0; iD<D; ++iD){
236 minCuboidExtent = util::min(minCuboidExtent,
237 cuboidGeometry.get(iC).getExtent()[iD]);
238 }
239 }
240#ifdef PARALLEL_MODE_MPI
241 singleton::mpi().reduceAndBcast(minCuboidExtent, MPI_MIN,
242 singleton::mpi().bossId());
243#endif
244
245 // It's enough that one rank checks for an error
246 if (singleton::mpi().getRank() == 0) {
247 OLB_ASSERT(minCuboidExtent*physDeltaX > maxCircumRadius,
248 "At least one cuboid too small so that the currently implemented "
249 "particle parallelization strategy does not work.");
250 }
251}
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
SuperStructure< T, PARTICLETYPE::d > & getSuperStructure()
#define OLB_ASSERT(COND, MESSAGE)
Definition olbDebug.h:45

References olb::particles::contact::evalCircumRadius(), forParticlesInSuperParticleSystem(), olb::SuperStructure< T, D >::getCuboidGeometry(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::util::max(), olb::util::min(), olb::singleton::mpi(), OLB_ASSERT, and olb::singleton::MpiManager::reduceAndBcast().

+ Here is the call graph for this function:

◆ checkInvalidationOnReceival()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::checkInvalidationOnReceival ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
std::vector< std::vector< std::size_t > > & receivedLocalIDs,
const Vector< bool, PARTICLETYPE::d > & periodicity )

Definition at line 442 of file relocation.h.

446{
447 using namespace descriptors;
448
449 //Retrieve load balancer
450 auto& superStructure = sParticleSystem.getSuperStructure();
451 auto& loadBalancer = superStructure.getLoadBalancer();
452
453 //Loop over valid surfaces and check, whether any data was received
454 forParticlesInSuperParticleSystem<T,PARTICLETYPE,conditions::valid_particle_surfaces>(
455 sParticleSystem,
456 [&](Particle<T,PARTICLETYPE>& particle,
457 ParticleSystem<T,PARTICLETYPE>& particleSystem, int globiC){
458
459 //Retrieve local iC
460 int lociC = loadBalancer.loc(globiC);
461
462 //Retrieve local particle iD
463 std::size_t locId = particle.getId();
464
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 << ","; }
471 }
472 std::cout << std::endl;
473#endif
474
475 //Check wether particle belongs to those having received data (here, if not found)
476 if( std::find(receivedLocalIDs[lociC].begin(),receivedLocalIDs[lociC].end(),
477 locId) == receivedLocalIDs[lociC].end()){
478 //Invalidate particle
479 particle.template setField<GENERAL,INVALID>(true);
480
481#ifdef VERBOSE_COMMUNICATION
482 int rank = singleton::mpi().getRank();
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>();
489#endif
490
491 } // if( std::find() )
492 /* else { */
493 /* // Check if the current block still touches the surface, if not then invalidate the particle */
494 /* auto& cuboidGeometry = superStructure.getCuboidGeometry(); */
495 /* const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR(); */
496 /* const T circumRadius = contact::evalCircumRadius(particle, physDeltaX); */
497 /* const int globiCcenter = particle.template getField<PARALLELIZATION, IC>(); */
498 /* bool touchesSurface = false; */
499 /* communication::getSurfaceTouchingICs( */
500 /* sParticleSystem, access::getPosition(particle), circumRadius, periodicity, globiCcenter, */
501 /* [&](int surfaceTouchingGlobiC){ */
502 /* if(surfaceTouchingGlobiC == globiC) { */
503 /* touchesSurface = true; */
504 /* } */
505 /* }); */
506 /* if(!touchesSurface) { */
507 /* particle.template setField<GENERAL,INVALID>(true); */
508 /* } */
509 /* } */
510 }); //forParticlesInSuperParticleSystem<T,PARTICLETYPE,valid_particle_surfaces>
511}
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
std::size_t getId() const
Return memory ID of the currently represented particle.
Definition particle.hh:67

References olb::particles::Particle< T, PARTICLETYPE >::getId(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), and olb::singleton::mpi().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkRelocation()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::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 )

Definition at line 252 of file relocation.h.

258{
259 using namespace descriptors;
260 using namespace particles::access;
261 constexpr unsigned D = PARTICLETYPE::d;
262
263 //Retrieve load balancer and cuboid geometry
264 auto& superStructure = sParticleSystem.getSuperStructure();
265 auto& cuboidGeometry = superStructure.getCuboidGeometry();
266
267 //Loop over valid particles
268 forParticlesInSuperParticleSystem( sParticleSystem,
269 [&](Particle<T,PARTICLETYPE>& particle,
270 ParticleSystem<T,PARTICLETYPE>& particleSystem, int globiC){
271
272 //Retrieve centre iC in previous timestep.
273 //- used to detect iC change
274 //- unly updated for resolved particles
275 int globiCcentreLast= -1;
276 if constexpr( providesSurface<PARTICLETYPE>() ){
277 globiCcentreLast = particle.template getField<PARALLELIZATION,IC>();
278 }
279 // Retrieve and update particle position
280 // if a periodic setup is used and the particle is out of bounds
281 const PhysR<T,D> position = applyPeriodicityToPosition(cuboidGeometry,
282 periodicity, particle.template getField<GENERAL,POSITION>());
283 //Find particle system by position
284 int globiCcentre = -1;
285 // getC doesn't treat periodicity! We can only use it because we updated it before
286 const bool particleCentreInDomain = cuboidGeometry.getC(position, globiCcentre);
287 /*
288 // Retrieve particle position
289 PhysR<T,D> position = particle.template getField<GENERAL,POSITION>();
290 //Find particle system by position
291 int globiCcentre = -1;
292 const bool particleCentreInDomain = getCuboid(
293 cuboidGeometry, periodicity, position, globiCcentre);
294 */
295 // Replace the position with the updated position
296 // if no periodicity is used or the particle isn't out of bounds nothing happens
297 // (must be here, because it can be that the particle remains on the same block after crossing the boundary)
298 // TODO: Add constexpr check if the setup is periodic or not before continuously overwriting the position here
299 particle.template setField<GENERAL, POSITION>(position);
300 /*if(isPeriodic(periodicity)) {
301 const PhysR<T,D> min = getCuboidMin<T,D>(cuboidGeometry);
302 const PhysR<T,D> max = getCuboidMax<T,D>(cuboidGeometry, min);
303
304 for(unsigned iD=0; iD<D; ++iD) {
305 position[iD] = applyPeriodicityToPosition(
306 periodicity[iD], position[iD], max[iD], min[iD]);
307 }
308 particle.template setField<GENERAL, POSITION>(position);
309 }*/
310
311 //Update iC, if resolved
312 if constexpr( providesSurface<PARTICLETYPE>() ){
313 particle.template setField<PARALLELIZATION,IC>(globiCcentre);
314 }
315
316 //Check whether particle has lost the global domain
317 if (particleCentreInDomain){
318 //Check whether particle centre resides in current iC
319 //If yes:
320 //- subgrid: no data to be sent
321 //- resolved: check surface
322 if (globiCcentre == globiC){
323 //Check, whether surface parts have to be sent (resolved only)
324 if constexpr( providesSurface<PARTICLETYPE>() ){
325 checkSurfaceRelocation( sParticleSystem, physDeltaX, particle, globiC,
326 rankDataMapRelocationInter, dataListRelocationIntra, serialSize, periodicity );
327 }
328 //If particle centre does not reside in iC
329 } else { // if (globiCcentre == globiC)
330 //Differentiate between resolved and subgrid treatment
331 if constexpr( providesSurface<PARTICLETYPE>() ){
332
333 //Detect center switch
334 //- to send data one last time
335 //- necessary, since new responsible iC can only send at next timestep
336 if(globiCcentre!=globiCcentreLast){
337#ifdef VERBOSE_COMMUNICATION
338 int rank = singleton::mpi().getRank();
339 std::cout << std::endl << "[Particle] "
340 << "CENTRE SWITCH("
341 << globiCcentreLast << "->" << globiCcentre << ")"
342 << " at sending from iC=" << globiC
343 << "(rank=" << rank << ")" << std::endl;
344#endif
345 //Prepare inter relocation or intra relocation
346 //-here: to new responsible ic
347 prepareRelocation( sParticleSystem,
348 particle, globiC, globiCcentre,
349 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
350
351 if constexpr( providesSurface<PARTICLETYPE>() ){
352 //Sending to self, to avoid invalidation on receiving
353 //- necessary, as responsibility changed
354 prepareRelocation( sParticleSystem,
355 particle, globiCcentre, globiC,
356 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
357
358 //Check, whether surface parts have to be sent (resolved only)
359 checkSurfaceRelocation( sParticleSystem, physDeltaX, particle, globiC,
360 rankDataMapRelocationInter, dataListRelocationIntra, serialSize, periodicity );
361 }
362
363 } //if(globiCcentre!=globiCcentreLast)
364 } else { //if constexpr( providesSurface<PARTICLETYPE>() )
365 //Prepare inter relocation or intra relocation
366 prepareRelocation( sParticleSystem,
367 particle, globiC, globiCcentre,
368 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
369 //Immediate invalidation (subgrid only)
370 particle.template setField<GENERAL,INVALID>(true);
371 }
372 } // else (globiCcentre == globiC)
373 } else { //particleCentreInDomain
374 //Invalidate particle
375 particle.template setField<GENERAL,INVALID>(true);
376 //Output warning
377 int rank = singleton::mpi().getRank();
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;
382 }
383 }); // forParticlesInSuperParticleSystem
384}
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)
Definition relocation.h:182
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)
Definition relocation.h:225

References applyPeriodicityToPosition(), checkSurfaceRelocation(), forParticlesInSuperParticleSystem(), olb::SuperStructure< T, D >::getCuboidGeometry(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::singleton::mpi(), and prepareRelocation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ checkSurfaceRelocation()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::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 )

Definition at line 225 of file relocation.h.

232{
233 //Retrieve cuboid geometry
234 /* auto& superStructure = sParticleSystem.getSuperStructure(); */
235 /* auto& cuboidGeometry = superStructure.getCuboidGeometry(); */
236 //Retrieve position and circumRadius
237 auto position = access::getPosition( particle );
238 const T circumRadius = contact::evalCircumRadius(particle, physDeltaX);
239 const int globiCcentre = particle.template getField<descriptors::PARALLELIZATION,descriptors::IC>();
240 //Get unique iCs on surface and prepare relocation
241 getSurfaceTouchingICs(sParticleSystem, position, circumRadius, periodicity, globiCcentre,
242 [&](const int globiCdest){
243 prepareRelocation( sParticleSystem, particle, globiC, globiCdest,
244 rankDataMapRelocationInter, dataListRelocationIntra, serialSize);
245 });
246}
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...

References olb::particles::contact::evalCircumRadius(), olb::particles::access::getPosition(), getSurfaceTouchingICs(), and prepareRelocation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ collectDataAndAppendVector()

template<typename DATA >
void olb::particles::communication::collectDataAndAppendVector ( std::vector< DATA > & dataVector,
std::unordered_set< int > & availableRanks,
singleton::MpiNonBlockingHelper & mpiNbHelper,
MPI_Comm commGroup = MPI_COMM_WORLD )

Definition at line 734 of file relocation.h.

738{
739 DATA data;
740 auto communicatable = ConcreteCommunicatable(data);
741 const int serialSize = communicatable.size();
742 //Receive data
743 receiveAndExecuteForData( availableRanks,
744 serialSize, commGroup, mpiNbHelper,
745 [&](int rankOrig, std::uint8_t* rawBuffer){
746 //Deserialize buffer
747 communicatable.deserialize( rawBuffer );
748 //Append data to std::vector
749 dataVector.push_back(data);
750 });
751}
void receiveAndExecuteForData(const std::unordered_set< int > &availableRanks, std::size_t serialSize, MPI_Comm Comm, singleton::MpiNonBlockingHelper &mpiNbHelper, F f)
Definition relocation.h:572

References receiveAndExecuteForData().

+ Here is the call graph for this function:

◆ communicateEquationsOfMotionResults()

template<typename T , typename PARTICLETYPE , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
void olb::particles::communication::communicateEquationsOfMotionResults ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > & contactContainer,
MPI_Comm equationsOfMotionComm )

Definition at line 304 of file equationsOfMotionResults.h.

313{
314 // TODO: Test if it is faster to only send & receive between processors that must exchange data (that way we don't need to synchronize all processors)
315
316#ifdef PARALLEL_MODE_MPI
317 // Create map for data
318 std::multimap<int, std::unique_ptr<std::uint8_t[]>> dataMap;
319
320 std::size_t serialSize =
321 evalEquationsOfMotionResults(sParticleSystem, contactContainer, dataMap);
322
323 //Create non blocking mpi helper
325
326 std::map<int, std::vector<std::uint8_t>> rankDataMapSorted;
327 communication::fillSendBuffer(dataMap, rankDataMapSorted, serialSize);
328
329 // Send mapped data
330 communication::sendMappedData(rankDataMapSorted,
331 sParticleSystem.getNeighbourRanks(), serialSize,
332 equationsOfMotionComm, mpiNbHelper);
333
334 receiveEquationsOfMotionResults(sParticleSystem, equationsOfMotionComm,
335 mpiNbHelper);
336#endif
337}
const std::unordered_set< int > & getNeighbourRanks()
Helper class for non blocking MPI communication.
Definition mpiManager.h:51
std::size_t evalEquationsOfMotionResults(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &dataMap)
void receiveEquationsOfMotionResults(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, MPI_Comm equationsOfMotionComm, singleton::MpiNonBlockingHelper &mpiNbHelper)

References evalEquationsOfMotionResults(), fillSendBuffer(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getNeighbourRanks(), receiveEquationsOfMotionResults(), and sendMappedData().

+ Here is the call graph for this function:

◆ communicateEquationsOfMotionResultsIntra()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::communicateEquationsOfMotionResultsIntra ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
const std::size_t & pID,
const Vector< T, PARTICLETYPE::d > & position,
const Vector< T, PARTICLETYPE::d > & velocity,
const Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > & angle,
const Vector< T, utilities::dimensions::convert< PARTICLETYPE::d >::rotation > & angVelocity )

Definition at line 71 of file equationsOfMotionResults.h.

79{
80 using namespace descriptors;
81
82 particles::communication::forParticlesInSuperParticleSystem(
83 sParticleSystem,
84 [&](Particle<T, PARTICLETYPE>& particle,
85 ParticleSystem<T, PARTICLETYPE>& particleSystem, int globiC) {
86 const std::size_t currGlobalParticleID =
87 particle.template getField<PARALLELIZATION, ID>();
88
89 if (currGlobalParticleID == pID) {
90 particle.template setField<GENERAL, POSITION>(position);
91 particle.template setField<MOBILITY, VELOCITY>(velocity);
92 particle.template setField<SURFACE, ANGLE>(
94 PARTICLETYPE::d>::serialize_rotation(angle));
95 particle.template setField<MOBILITY, ANG_VELOCITY>(
97 PARTICLETYPE::d>::serialize_rotation(angVelocity));
98 }
99 });
100}

References forParticlesInSuperParticleSystem().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ communicateSurfaceForce()

template<typename T , typename PARTICLETYPE , unsigned forceDataSize>
void olb::particles::communication::communicateSurfaceForce ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
std::map< std::size_t, Vector< T, forceDataSize > > & globalIdDataMap,
MPI_Comm surfaceForceComm )

Definition at line 43 of file surfaceForce.h.

50{
51 //TODO: add intra and inter core differentiation
52 using namespace descriptors;
53 //Retrieve dimensions
54 constexpr unsigned D = PARTICLETYPE::d;
55 constexpr unsigned Drot = utilities::dimensions::convert<D>::rotation;
56 //Retrieve loadBalancer
57 auto& superStructure = sParticleSystem.getSuperStructure();
58 auto& loadBalancer = superStructure.getLoadBalancer();
59
60 //Create FieldArrayD for globalID, force and torque
62 using FORCING_EVAL = typename PARTICLETYPE
63 ::template derivedField<descriptors::FORCING>;
64 using TORQUE_EVAL = typename FORCING_EVAL
65 ::template derivedField<descriptors::TORQUE>;
68
69 //Create communicatables
70 auto communicatableForce = ConcreteCommunicatable(fieldForce);
71 auto communicatableTorque = ConcreteCommunicatable(fieldTorque);
72 auto communicatableID = ConcreteCommunicatable(fieldID);
73 //Retrieve serial size
74 const std::vector<unsigned int> indices{0};
75 auto serialSize = communicatableForce.size(indices)
76 + communicatableTorque.size(indices)
77 + communicatableID.size(indices);
78 //Create rankDataMap
79 std::multimap<int,std::unique_ptr<std::uint8_t[]>> rankDataMap;
80
81 //Loop over valid particles in particle system
82 communication::forParticlesInSuperParticleSystem<T,PARTICLETYPE,
84 [&](Particle<T,PARTICLETYPE>& particle,
85 ParticleSystem<T,PARTICLETYPE>& particleSystem, int globiC){
86 //Retrieve globiC of particle center
87 int globiCcentre = particle.template getField<PARALLELIZATION,IC>();
88 int rankDest = loadBalancer.rank(globiCcentre);
89 //Retrieve force and torque and set FieldArray
90 auto force = particle.template getField<FORCING,FORCE>();
91 auto torque = particle.template getField<FORCING,TORQUE>();
92 auto globalID = particle.template getField<PARALLELIZATION,ID>();
93#ifdef VERBOSE_COMMUNICATION
94 std::cout << "EVALUATING: force=" << force << ", torque=" << torque << ", globalID=" << globalID << std::endl;
95#endif
96 fieldForce.setField(0, force);
97 fieldTorque.setField(0, torque);
98 fieldID.setField(0, globalID);
99 //Create buffer
100 std::unique_ptr<std::uint8_t[]> buffer(new std::uint8_t[serialSize]{ });
101 std::uint8_t* bufferRaw = buffer.get();
102 //Serialize force
103 std::size_t serialIdx = communicatableForce.serialize(indices, bufferRaw);
104 //Serialice torque with offset serialIdx
105 serialIdx += communicatableTorque.serialize(indices, &bufferRaw[serialIdx]);
106 //Serialice globalID with offset serialIdx
107 communicatableID.serialize(indices, &bufferRaw[serialIdx]);
108 //Add serialized data to rankDataMap
109 rankDataMap.insert(std::make_pair(rankDest, std::move(buffer)));
110 }); //forParticlesInSuperParticleSystem()
111
112 //Retrieve rank of direct neighbours
113 auto& listNeighbourRanks = sParticleSystem.getNeighbourRanks();
114
115 //Create non blocking mpi helper
116 singleton::MpiNonBlockingHelper mpiNbHelper;
117
118 //Create ranDataMapSorted (WARNING: has to be existent until all data is received! c.f. #290)
119 std::map<int, std::vector<std::uint8_t> > rankDataMapSorted;
120
121 //Fill send buffer
122 fillSendBuffer( rankDataMap, rankDataMapSorted, serialSize );
123
124 //Send mapped data
125 communication::sendMappedData( rankDataMapSorted,
126 listNeighbourRanks, serialSize, surfaceForceComm, mpiNbHelper );
127
128 //Receive data and iterate buffer
129 communication::receiveAndExecuteForData( listNeighbourRanks, serialSize,
130 surfaceForceComm, mpiNbHelper,
131 [&](int rankOrig, std::uint8_t* bufferRaw){
132 //Deserialize force
133 std::size_t serialIdx = communicatableForce.deserialize(indices, bufferRaw);
134 //Deserialize torque with offset serialIdx
135 serialIdx += communicatableTorque.deserialize(indices, &bufferRaw[serialIdx]);
136 //Deserialize globalID with offset serialIdx
137 communicatableID.deserialize(indices, &bufferRaw[serialIdx]);
138 //Retrieve vectors
139 auto force = fieldForce.getField(0);
140 auto torque = fieldTorque.getField(0);
141 auto globalID = fieldID.getField(0);
142
143#ifdef VERBOSE_COMMUNICATION
144 int rank = singleton::mpi().getRank();
145 std::cout << "Received (on rank=" << rank
146 << " from rank=" << rankOrig
147 << "): force=" << force
148 << std::endl
149 << " "
150 << ", torque=" << torque
151 << ", globalID=" << globalID
152 << std::endl;
153#endif
154
155 //Create forceData Vector
156 Vector<T,forceDataSize> forceData;
157 for (unsigned iDim=0; iDim<D; ++iDim) {
158 forceData[iDim] = force[iDim];
159 }
160
161 if constexpr (utilities::dimensions::convert<PARTICLETYPE::d>::rotation == 1 ) {
162 forceData[D] = torque;
163 }
164 else {
165 for (unsigned iDim=0; iDim<Drot; ++iDim) {
166 forceData[iDim+D] = torque[iDim];
167 }
168 }
169
170 //Add id-data-pair to map OR only add data
171 auto mapPair = globalIdDataMap.insert( std::pair<std::size_t,
172 Vector<T,forceDataSize>>(globalID, forceData) );
173 if (mapPair.second==false){ //Checks previous existance
174 globalIdDataMap[globalID] += forceData;
175 }
176 }); //receiveAndExecuteForData()
177}
SoA storage for instances of a single FIELD.

References fillSendBuffer(), forParticlesInSuperParticleSystem(), olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::getField(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getNeighbourRanks(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::singleton::mpi(), receiveAndExecuteForData(), sendMappedData(), and olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::setField().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deserializeIcDest()

template<typename T , typename PARTICLETYPE >
std::size_t olb::particles::communication::deserializeIcDest ( int & globiCdest,
std::uint8_t * bufferRaw )

Definition at line 179 of file utilities.h.

181{
182 //Define iC field as FieldArrayD with single entry
184 const std::vector<unsigned int> index{0};
185 auto communicatable = ConcreteCommunicatable(fieldiC);
186 //Deserialice iC
187 communicatable.deserialize(index, bufferRaw);
188 globiCdest = fieldiC.getField(0);
189 //Return communicatable size
190 return communicatable.size(index);
191}

References olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::getField().

+ Here is the call graph for this function:

◆ deserializeIcDestAndParticle()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::deserializeIcDestAndParticle ( int & globiCdest,
Particle< T, PARTICLETYPE > & particle,
std::uint8_t * bufferiCandParticle )

Definition at line 195 of file utilities.h.

198{
199 //Deserialize iC and retrieve particle buffer
200 std::size_t serialSizeField =
201 deserializeIcDest<T,PARTICLETYPE>(globiCdest,bufferiCandParticle);
202 std::uint8_t* bufferRawParticle = &bufferiCandParticle[serialSizeField];
203 //Deserialize particle
204 particle.deserialize(bufferRawParticle);
205}
std::size_t deserialize(const std::uint8_t *buffer)
Deserialize data.
Definition particle.h:146

References olb::particles::Particle< T, PARTICLETYPE >::deserialize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ doForParticle()

template<typename T , typename PARTICLETYPE , typename F >
void olb::particles::communication::doForParticle ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
ParallelParticleLocator & locator,
F f )

Definition at line 198 of file lambdaLoops.h.

201{
202 //Retrieve rank and only proceed for correct one
203 int rank = singleton::mpi().getRank();
204 auto& loadBalancer = sParticleSystem.getSuperStructure().getLoadBalancer();
205 if (rank==loadBalancer.rank(locator.globiC)){
206 //Retrieve ParticleSystem
207 auto bParticleSystems = sParticleSystem.getBlockParticleSystems();
208 auto& particleSystem = *bParticleSystems[loadBalancer.loc(locator.globiC)];
209 //Retrieve particle
210 auto particle = particleSystem.get(locator.localID);
211 //Call function f for particle
212 doForParticle( particle, f );
213 }
214}
std::vector< ParticleSystem< T, PARTICLETYPE > * > & getBlockParticleSystems()
void doForParticle(Particle< T, PARTICLETYPE > &particle, F f)
Definition lambdaLoops.h:37

References doForParticle(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getBlockParticleSystems(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::particles::ParallelParticleLocator::globiC, olb::particles::ParallelParticleLocator::localID, and olb::singleton::mpi().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ evalDestRanks()

template<typename T , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
std::unordered_set< int > olb::particles::communication::evalDestRanks ( contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > & contactContainer,
const std::size_t globalParticleID )

evaluates ranks that need the new particle data

contact.isEmpty() &&

contact.isEmpty() &&

Definition at line 44 of file equationsOfMotionResults.h.

47{
48 std::unordered_set<int> destRanks;
49
50 for (const PARTICLECONTACTTYPE& contact : contactContainer.particleContacts) {
51 if (
53 (globalParticleID == contact.getIDs()[0] ||
54 globalParticleID == contact.getIDs()[1])) {
55 destRanks.insert(contact.getResponsibleRank());
56 }
57 }
58 for (const WALLCONTACTTYPE& contact : contactContainer.wallContacts) {
59 if (
61 globalParticleID == contact.getParticleID()) {
62 destRanks.insert(contact.getResponsibleRank());
63 }
64 }
65
66 return destRanks;
67}
+ Here is the caller graph for this function:

◆ evalEquationsOfMotionResults()

template<typename T , typename PARTICLETYPE , typename PARTICLECONTACTTYPE , typename WALLCONTACTTYPE >
std::size_t olb::particles::communication::evalEquationsOfMotionResults ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > & contactContainer,
std::multimap< int, std::unique_ptr< std::uint8_t[]> > & dataMap )

Definition at line 106 of file equationsOfMotionResults.h.

111{
112 using namespace descriptors;
113
114 //Create FieldArrayD for globalID, force and torque
115 using GENERAL_EVAL =
116 typename PARTICLETYPE ::template derivedField<descriptors::GENERAL>;
117 using MOBILITY_EVAL =
118 typename PARTICLETYPE ::template derivedField<descriptors::MOBILITY>;
119 using SURFACE_EVAL =
120 typename PARTICLETYPE ::template derivedField<descriptors::SURFACE>;
121 using POSITION_EVAL =
122 typename GENERAL_EVAL ::template derivedField<descriptors::POSITION>;
123 using VELOCITY_EVAL =
124 typename MOBILITY_EVAL ::template derivedField<descriptors::VELOCITY>;
125 using ANGLE_EVAL =
126 typename SURFACE_EVAL ::template derivedField<descriptors::ANGLE>;
127 using ANGVELOCITY_EVAL =
128 typename MOBILITY_EVAL ::template derivedField<descriptors::ANG_VELOCITY>;
131 1);
133 1);
136 fieldAngVelocity(1);
137
138 //Create communicatables
139 auto communicatableID = ConcreteCommunicatable(fieldID);
140 auto communicatablePosition = ConcreteCommunicatable(fieldPosition);
141 auto communicatableVelocity = ConcreteCommunicatable(fieldVelocity);
142 auto communicatableAngle = ConcreteCommunicatable(fieldAngle);
143 auto communicatableAngVelocity = ConcreteCommunicatable(fieldAngVelocity);
144
145 //Retrieve serial size
146 const std::vector<unsigned int> indices {0};
147 const std::size_t serialSize =
148 communicatableID.size(indices) + communicatablePosition.size(indices) +
149 communicatableVelocity.size(indices) + communicatableAngle.size(indices) +
150 communicatableAngVelocity.size(indices);
151
152 // Fill map with data
153 communication::forParticlesInSuperParticleSystem(
154 sParticleSystem,
155 [&](Particle<T, PARTICLETYPE>& particle,
156 ParticleSystem<T, PARTICLETYPE>& particleSystem, int globiC) {
157 using PCONDITION = std::conditional_t<
158 access::providesSurface<PARTICLETYPE>(),
159 conditions::
160 valid_particle_centres, // only consider center for resolved
161 conditions::valid_particles>; // only consider valid
162
163 if (PCONDITION::value(particle, globiC)) {
164 // Get quantities to package
165 fieldID.setField(0,
166 particle.template getField<PARALLELIZATION, ID>());
167 fieldPosition.setField(0, access::getPosition(particle));
168 fieldVelocity.setField(0, access::getVelocity(particle));
169 fieldAngle.setField(0, access::getAngle(particle));
170 fieldAngVelocity.setField(0, access::getAngularVelocity(particle));
171
172 communicateEquationsOfMotionResultsIntra(
173 sParticleSystem,
174 particle.template getField<PARALLELIZATION, ID>(),
175 access::getPosition(particle), access::getVelocity(particle),
176 access::getAngle(particle), access::getAngularVelocity(particle));
177
178 // Evaluate which ranks need to know the data
179 std::unordered_set<int> destRanks {
180 evalDestRanks(contactContainer, fieldID.getField(0))};
181
182 for (const int destRank : destRanks) {
183 std::unique_ptr<std::uint8_t[]> buffer(
184 new std::uint8_t[serialSize] {});
185 std::uint8_t* bufferRaw = buffer.get();
186 std::size_t serialIdx =
187 communicatableID.serialize(indices, bufferRaw);
188 serialIdx += communicatablePosition.serialize(
189 indices, &bufferRaw[serialIdx]);
190 serialIdx += communicatableVelocity.serialize(
191 indices, &bufferRaw[serialIdx]);
192 serialIdx +=
193 communicatableAngle.serialize(indices, &bufferRaw[serialIdx]);
194 serialIdx += communicatableAngVelocity.serialize(
195 indices, &bufferRaw[serialIdx]);
196 dataMap.insert(std::make_pair(destRank, std::move(buffer)));
197 }
198
199#ifdef VERBOSE_CONTACT_COMMUNICATION
200 std::cout << "Rank " << singleton::mpi().getRank()
201 << " sends particle data of ID " << fieldID.getField(0)
202 << " to ";
203 for (const int destRank : destRanks) {
204 std::cout << destRank << " ";
205 }
206 std::cout << std::endl;
207#endif
208 }
209 });
210
211 return serialSize;
212}

References communicateEquationsOfMotionResultsIntra(), evalDestRanks(), forParticlesInSuperParticleSystem(), olb::particles::access::getAngle(), olb::particles::access::getAngularVelocity(), olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::getField(), olb::particles::access::getPosition(), olb::singleton::MpiManager::getRank(), olb::particles::access::getVelocity(), olb::singleton::mpi(), and olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::setField().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fillSendBuffer()

void olb::particles::communication::fillSendBuffer ( std::multimap< int, std::unique_ptr< std::uint8_t[]> > & rankDataMap,
std::map< int, std::vector< std::uint8_t > > & rankDataMapSorted,
std::size_t serialSize )

Definition at line 387 of file relocation.h.

391{
392 //Iterate over rank data pairs
393 for (auto& rankDataPair : rankDataMap) {
394 //Decompose pair
395 int rankDest = rankDataPair.first;
396 std::uint8_t* buffer = rankDataPair.second.get();
397 //Write data to sorted map
398 // - creates vector via 3-arg initializer list
399 rankDataMapSorted[rankDest].insert(
400 rankDataMapSorted[rankDest].end(),
401 buffer,
402 buffer + serialSize );
403 }
404}
+ Here is the caller graph for this function:

◆ forParticlesInSuperParticleSystem()

template<typename T , typename PARTICLETYPE , typename PCONDITION = conditions::valid_particles, typename F >
void olb::particles::communication::forParticlesInSuperParticleSystem ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
F f )

Definition at line 173 of file lambdaLoops.h.

176{
177 //Iterate over particle systems
178 forSystemsInSuperParticleSystem( sParticleSystem,
179 [&](ParticleSystem<T,PARTICLETYPE>& particleSystem, int iC, int globiC){
180 //Iterate over particles
181 forParticlesInParticleSystem<T,PARTICLETYPE,PCONDITION>( particleSystem,
182 [&](Particle<T,PARTICLETYPE>& particle){
183 if constexpr (std::is_invocable_v<F,
185 {
186 f( particle, particleSystem, globiC );
187 } else {
188 f( particle );
189 }
190 },globiC);
191 });
192}

References forSystemsInSuperParticleSystem().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ forSystemsInSuperParticleSystem()

template<typename T , typename PARTICLETYPE , typename F >
void olb::particles::communication::forSystemsInSuperParticleSystem ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
F f )

Definition at line 154 of file lambdaLoops.h.

157{
158 //Retrieve load balancer
159 auto& loadBalancer = sParticleSystem.getSuperStructure().getLoadBalancer();
160 //Loop over iCs
161 for (int iC=0; iC<loadBalancer.size(); ++iC){
162 int globiC = loadBalancer.glob(iC);
163 //Retrieve container
164 auto bParticleSystems = sParticleSystem.getBlockParticleSystems();
165 auto& particleSystem = *bParticleSystems[iC];
166 f( particleSystem, iC, globiC );
167 }
168}

References olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getBlockParticleSystems(), olb::SuperStructure< T, D >::getLoadBalancer(), and olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCuboid()

template<typename T , unsigned D>
bool olb::particles::communication::getCuboid ( const CuboidGeometry< T, D > & cuboidGeometry,
const Vector< bool, D > & periodicity,
const PhysR< T, D > & position,
int & iC )

Function returns true if cuboid was found and gives iC.

Definition at line 320 of file utilities.h.

323{
324 PhysR<T,D> newPosition(
325 applyPeriodicityToPosition(cuboidGeometry, periodicity, position));
326 return cuboidGeometry.getC(newPosition, iC);
327}

References applyPeriodicityToPosition().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCuboidMax()

template<typename T , unsigned D>
Vector< T, D > olb::particles::communication::getCuboidMax ( const CuboidGeometry< T, D > & cuboidGeometry,
const PhysR< T, D > & min )

Returns maximal coordinate of domain for periodic particle boundaries.

Definition at line 293 of file utilities.h.

295{
296 const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR();
297 return min + physDeltaX * cuboidGeometry.getMotherCuboid().getExtent();
298}

◆ getCuboidMin()

template<typename T , unsigned D>
Vector< T, D > olb::particles::communication::getCuboidMin ( const CuboidGeometry< T, D > & cuboidGeometry)

Returns minimal coordinate of domain for periodic particle boundaries.

Definition at line 284 of file utilities.h.

285{
286 const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR();
287 return (cuboidGeometry.getMotherCuboid().getOrigin() - 0.5 * physDeltaX);
288
289}

◆ getNeighborCuboids()

template<typename T , unsigned D, bool verbose = false>
std::vector< int > olb::particles::communication::getNeighborCuboids ( CuboidGeometry< T, D > & cuboidGeometry,
unsigned offset,
int globiC )

Get neighbour cuboids.

Definition at line 39 of file utilities.h.

41{
42 std::vector<int> neighbors;
43 cuboidGeometry.getNeighbourhood(globiC, neighbors, offset);
44
45 //Print, if desired
46 if constexpr(verbose){
47 std::cout << globiC << ": " << neighbors << std::endl;
48 }
49
50 return neighbors;
51}

◆ getNeighbourRanks() [1/2]

template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > olb::particles::communication::getNeighbourRanks ( SuperStructure< T, D > & superStructure,
unsigned offset )

Get neighbour ranks.

Definition at line 141 of file utilities.h.

143{
144 //Retrive parallization infos
145 const int rank = singleton::mpi().getRank();
146 return getNeighbourRanks<T,D,false>(superStructure, offset, rank);
147}

References olb::singleton::MpiManager::getRank(), and olb::singleton::mpi().

+ Here is the call graph for this function:

◆ getNeighbourRanks() [2/2]

template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > olb::particles::communication::getNeighbourRanks ( SuperStructure< T, D > & superStructure,
unsigned offset,
int rank )

Get neighbour ranks.

HOTFIX VERSION (according to #319)

Definition at line 113 of file utilities.h.

115{
116 std::unordered_set<int> rankNeighbours;
117
118#ifdef PARALLEL_MODE_MPI
119 auto& loadBalancer = superStructure.getLoadBalancer();
120 auto& cuboidGeometry = superStructure.getCuboidGeometry();
121
123 // 1. sample complete neighbourhood
124 std::map<int,std::vector<int>> neighbourhood;
125 evaluateCuboidGeometryNeighbourhood( cuboidGeometry, neighbourhood, offset);
126
127 //2. check consistency
128 constexpr bool correctFaultyNeighbourhood = true;
129 checkCuboidNeighbourhoodConsistency( neighbourhood, correctFaultyNeighbourhood );
130
131 //3. evaluate relevant ranks
132 rankNeighbours = getNeighbourRanksFromCuboidNeighbourhood<T,D,verbose>(
133 superStructure, rank, neighbourhood );
134#endif
135
136 return rankNeighbours;
137}
void evaluateCuboidGeometryNeighbourhood(CuboidGeometry2D< T > &cuboidGeometry, std::map< int, std::vector< int > > &neighbourhood, int offset=0)
Evaluate complete neighbourhood and store in std::map.
bool checkCuboidNeighbourhoodConsistency(std::map< int, std::vector< int > > &neighbourhood, bool correct=false, bool verbose=false)
Consistency check for neighbour retrieval.

References olb::checkCuboidNeighbourhoodConsistency(), olb::evaluateCuboidGeometryNeighbourhood(), olb::SuperStructure< T, D >::getCuboidGeometry(), and olb::SuperStructure< T, D >::getLoadBalancer().

+ Here is the call graph for this function:

◆ getNeighbourRanksFromCuboidNeighbourhood() [1/3]

template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > olb::particles::communication::getNeighbourRanksFromCuboidNeighbourhood ( SuperStructure< T, D > & superStructure,
const std::vector< std::unordered_set< int > > & neighbourhood )

Get neighbour ranks.

Definition at line 102 of file utilities.h.

104{
105 const int rank = singleton::mpi().getRank();
106 return getNeighbourRanksFromCuboidNeighbourhood<T,D,verbose>(
107 superStructure, rank, neighbourhood);
108}

References olb::singleton::MpiManager::getRank(), and olb::singleton::mpi().

+ Here is the call graph for this function:

◆ getNeighbourRanksFromCuboidNeighbourhood() [2/3]

template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > olb::particles::communication::getNeighbourRanksFromCuboidNeighbourhood ( SuperStructure< T, D > & superStructure,
int rank,
const std::vector< std::unordered_set< int > > & neighbourhood )

Get neighbour ranks.

Definition at line 84 of file utilities.h.

86{
87 std::map<int,std::vector<int>> neighbourhoodMap;
88
89 for(unsigned i=0; i<neighbourhood.size(); ++i) {
90 neighbourhoodMap[i] = std::vector<int>();
91 for(int iC : neighbourhood[i]) {
92 neighbourhoodMap[i].push_back(iC);
93 }
94 }
95
96 return getNeighbourRanksFromCuboidNeighbourhood<T,D,verbose>(
97 superStructure, rank, neighbourhoodMap );
98}

◆ getNeighbourRanksFromCuboidNeighbourhood() [3/3]

template<typename T , unsigned D, bool verbose = false>
std::unordered_set< int > olb::particles::communication::getNeighbourRanksFromCuboidNeighbourhood ( SuperStructure< T, D > & superStructure,
int rank,
std::map< int, std::vector< int > > neighbourhood )

Get neighbour ranks.

Definition at line 55 of file utilities.h.

57{
58 std::unordered_set<int> rankNeighbours;
59
60#ifdef PARALLEL_MODE_MPI
61 auto& loadBalancer = superStructure.getLoadBalancer();
62
63 for ( auto cuboidNeighbourPair : neighbourhood){
64 int globiC = cuboidNeighbourPair.first;
65 if (loadBalancer.rank(globiC) == rank) {
66 std::vector<int>& neighbours = cuboidNeighbourPair.second;
67 for (int globiCN : neighbours ){
68 rankNeighbours.insert( loadBalancer.rank(globiCN));
69 }
70 }
71 }
72
73 if constexpr(verbose){
74 std::cout << rank << ": " << rankNeighbours << std::endl;
75 }
76#endif
77
78 return rankNeighbours;
79}

References olb::SuperStructure< T, D >::getLoadBalancer().

+ Here is the call graph for this function:

◆ getSurfaceTouchingICs() [1/2]

template<typename T , unsigned D, typename F = std::function<void(int)>, bool domainWarning = false, bool checkDiscretePoints = false>
std::unordered_set< int > olb::particles::communication::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 globiC.

Definition at line 299 of file particleUtilities.h.

303 {} )
304{
305 // This option is prone to errors
306 if constexpr(checkDiscretePoints) {
307 //Set of destination iCs preventing sending to same iC multiple times
308 std::unordered_set<int> iCs;
309 //Retrieve points on hull
310 auto pointsOnHull = discrete_points_on_hull::calculate( position, circumRadius );
311 //Iterate over points on hull
312 for (const PhysR<T,D>& point : pointsOnHull){
313 //Retrieve residence iC
314 int globiConHull=0;
315 const bool cuboidFound = getCuboid(cuboidGeometry,
316 periodicity, point, globiConHull);
317 if constexpr(domainWarning){
318 if (!cuboidFound){
319 std::cerr << "Warning [during getSurfaceTouchingICs]: Cuboid not found for point "
320 << point << std::endl;
321 }
322 }
323 //Check whether point has left responsible ic
324 if (cuboidFound && globiConHull!=globiC){
325 //Add destination ic to list (to avoid resending)
326 if(iCs.insert(globiConHull).second) {
327 f(globiConHull);
328 }
329 } //if (globiConHull!=globiC)
330 } //for (auto point : pointsOnHull)
331 return iCs;
332 }
333 else {
334 const T physDeltaX = cuboidGeometry.getMotherCuboid().getDeltaR();
335 std::vector<int> tmp = communication::getNeighborCuboids<T,D,false>(
336 cuboidGeometry, util::ceil(circumRadius/physDeltaX), globiC);
337 std::unordered_set<int> iCs;
338 for(const int entry : tmp) {
339 if( globiC != entry ) {
340 iCs.insert(entry);
341 f(entry);
342 }
343 }
344 return iCs;
345 }
346 __builtin_unreachable();
347}

References getSurfaceTouchingICs().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getSurfaceTouchingICs() [2/2]

template<typename T , typename PARTICLETYPE , typename F = std::function<void(int)>>
std::unordered_set< int > olb::particles::communication::getSurfaceTouchingICs ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
Vector< T, PARTICLETYPE::d > position,
T circumRadius,
const Vector< bool, PARTICLETYPE::d > & periodicity,
int globiC,
F f = [](int){} )

Definition at line 350 of file particleUtilities.h.

354 {} )
355{
356 std::unordered_set<int> neighbors = sParticleSystem.getCuboidNeighborhood()[globiC];
357 for(const int neighbor: neighbors) {
358 f(neighbor);
359 }
360 return neighbors;
361}
const std::vector< std::unordered_set< int > > & getCuboidNeighborhood()

References getSurfaceTouchingICs().

+ Here is the call graph for this function:

◆ getVectorOfSurfaceTouchingICs()

template<typename T , unsigned D, typename F = std::function<void(int)>, bool domainWarning = false>
std::vector< int > olb::particles::communication::getVectorOfSurfaceTouchingICs ( CuboidGeometry< T, D > & cuboidGeometry,
Vector< T, D > position,
T circumRadius,
const Vector< bool, D > & periodicity,
int globiC,
F f = [](int){} )

Definition at line 367 of file particleUtilities.h.

371 {} )
372{
373 const std::unordered_set<int> touchedICs{getSurfaceTouchingICs<T,D,F,domainWarning>(
374 cuboidGeometry, position, circumRadius, periodicity, globiC, f)};
375 std::vector<int> listOfICs;
376 listOfICs.insert(listOfICs.end(), touchedICs.begin(), touchedICs.end());
377 return listOfICs;
378}

References getVectorOfSurfaceTouchingICs().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ insertSerializedParticle()

template<typename T , typename PARTICLETYPE >
std::size_t olb::particles::communication::insertSerializedParticle ( ParticleSystem< T, PARTICLETYPE > & particleSystem,
std::size_t idxParticle,
std::uint8_t rawBuffer[] )

Definition at line 85 of file relocation.h.

89{
90 using namespace descriptors;
91 //Retrieve particle
92 auto particle = particleSystem.get(idxParticle);
93
94#ifdef VERBOSE_COMMUNICATION
95 auto globiCcentreLast = particle.template getField<PARALLELIZATION,IC>();
96#endif
97
98 //Deserialise particle
99 int globiCdest;
100 deserializeIcDestAndParticle(globiCdest,particle,rawBuffer);
101
102#ifdef VERBOSE_COMMUNICATION
103 auto globiCcentre = particle.template getField<PARALLELIZATION,IC>();
104
105 if(globiCcentre!=globiCcentreLast){
106 int rank = singleton::mpi().getRank();
107 std::cout << std::endl << "[Particle] "
108 << "CENTRE SWITCH("
109 << globiCcentreLast << "->" << globiCcentre << ")"
110 << " at receiving at iC=" << "X"
111 << "(rank=" << rank << ")" << std::endl;
112 }
113#endif
114
115
116 //Update surface pointer
117 if constexpr( access::providesSurface<PARTICLETYPE>() ){
118 updateSurfacePtr( particleSystem, idxParticle );
119 }
120 return particle.getId();
121}

References deserializeIcDestAndParticle(), olb::particles::ParticleSystem< T, PARTICLETYPE >::get(), olb::singleton::MpiManager::getRank(), olb::singleton::mpi(), and updateSurfacePtr().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ movePositionToEnd()

template<typename T >
T olb::particles::communication::movePositionToEnd ( const T position,
const T max,
const T min )

Definition at line 260 of file utilities.h.

261{
262 return max - (min - position);
263}
+ Here is the caller graph for this function:

◆ movePositionToStart()

template<typename T >
T olb::particles::communication::movePositionToStart ( const T position,
const T max,
const T min )

Definition at line 254 of file utilities.h.

255{
256 return min + (position - max);
257}
+ Here is the caller graph for this function:

◆ prepareRelocation()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::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 )

Definition at line 182 of file relocation.h.

189{
190 //Retrieve loadBalancer
191 auto& loadBalancer = sParticleSystem.getSuperStructure().getLoadBalancer();
192 //Create buffer pointer
193 std::unique_ptr<std::uint8_t[]> buffer(new std::uint8_t[serialSize]{ });
194
195 //Serialize particle content into buffer
196 serializeIcDestAndParticle( globiCdest, particle, buffer.get() );
197
198 //Check, whether iCs are on same core
199 int rank = singleton::mpi().getRank();
200 int rankDest = loadBalancer.rank(globiCdest);
201 if (rank != rankDest){
202 //Add rank-buffer pair to rankDataMapRelocationInter
203 rankDataMapRelocationInter.insert(std::make_pair(rankDest, std::move(buffer)));
204 } else {
205 //If on same core location can be done without mpi
206 dataListRelocationIntra.push_back(std::move(buffer));
207 } //else (rank != rankDest)
208
209#ifdef VERBOSE_COMMUNICATION
210 auto globalID = particle.template getField<
211 descriptors::PARALLELIZATION,descriptors::ID>();
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>();
219#endif
220}

References olb::SuperStructure< T, D >::getLoadBalancer(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::singleton::mpi(), and serializeIcDestAndParticle().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ receiveAndExecuteForData()

template<typename F >
void olb::particles::communication::receiveAndExecuteForData ( const std::unordered_set< int > & availableRanks,
std::size_t serialSize,
MPI_Comm Comm,
singleton::MpiNonBlockingHelper & mpiNbHelper,
F f )

Definition at line 572 of file relocation.h.

578{
579 //Iterate available ranks
580 for (int rankOrig : availableRanks) {
581 //Probe whether incomming data on rank
582 std::size_t noBytesReceived = singleton::mpi().probeReceiveSize(rankOrig, MPI_BYTE, 1, Comm);
583 //Create receive buffer as vector
584 std::vector<std::uint8_t> recv_buffer(noBytesReceived);
585#ifdef VERBOSE_COMMUNICATION
586 int rank = singleton::mpi().getRank();
587 std::cout << "Serial(rank=" << rank << "): "
588 << "noBytesToBeReceived=" << noBytesReceived << "; " << std::endl;
589#endif
590 //Receive data via mpi
591 singleton::mpi().receive<std::uint8_t>(
592 recv_buffer.data(),
593 noBytesReceived,
594 rankOrig,
595 1,
596 Comm);
597 //Loop over bytes in chunks of serialSize
598 for (unsigned iByte=0; iByte < noBytesReceived; iByte += serialSize) {
599 //Define raw buffer
600 std::uint8_t* rawBuffer = &recv_buffer[iByte];
601 //Execute passed function
602 f( rankOrig, rawBuffer );
603#ifdef VERBOSE_COMMUNICATION
604 int rank = singleton::mpi().getRank();
605 std::cout << "Serial(rank=" << rank << "): "
606 << "noBytesReceived=" << noBytesReceived << "; "
607 << "iByte=" << iByte << std::endl;
608#endif
609 //assignParticleToIC( sParticleSystem, receivedLocalIDs, rankOrig, rawBuffer );
610 } // for (int iByte=0; iByte<noBytesReceived; iByte+=serialSize)
611 } // for (auto rankOrig : availableRanks)
612 singleton::mpi().waitAll(mpiNbHelper);
613 //Free mpi helper
614 mpiNbHelper.free();
615}

References olb::singleton::MpiNonBlockingHelper::free(), olb::singleton::MpiManager::getRank(), olb::singleton::mpi(), olb::singleton::MpiManager::probeReceiveSize(), olb::singleton::MpiManager::receive(), and olb::singleton::MpiManager::waitAll().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ receiveEquationsOfMotionResults()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::receiveEquationsOfMotionResults ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
MPI_Comm equationsOfMotionComm,
singleton::MpiNonBlockingHelper & mpiNbHelper )

Definition at line 217 of file equationsOfMotionResults.h.

221{
222 using namespace descriptors;
223
224 // Retrieve rank of direct neighbours
225 auto& listNeighbourRanks = sParticleSystem.getNeighbourRanks();
226
227 //Create FieldArrayD for globalID, force and torque
228 using GENERAL_EVAL =
229 typename PARTICLETYPE ::template derivedField<descriptors::GENERAL>;
230 using MOBILITY_EVAL =
231 typename PARTICLETYPE ::template derivedField<descriptors::MOBILITY>;
232 using SURFACE_EVAL =
233 typename PARTICLETYPE ::template derivedField<descriptors::SURFACE>;
234 using POSITION_EVAL =
235 typename GENERAL_EVAL ::template derivedField<descriptors::POSITION>;
236 using VELOCITY_EVAL =
237 typename MOBILITY_EVAL ::template derivedField<descriptors::VELOCITY>;
238 using ANGLE_EVAL =
239 typename SURFACE_EVAL ::template derivedField<descriptors::ANGLE>;
240 using ANGVELOCITY_EVAL =
241 typename MOBILITY_EVAL ::template derivedField<descriptors::ANG_VELOCITY>;
244 1);
246 1);
249 fieldAngVelocity(1);
250
251 //Create communicatables
252 auto communicatableID = ConcreteCommunicatable(fieldID);
253 auto communicatablePosition = ConcreteCommunicatable(fieldPosition);
254 auto communicatableVelocity = ConcreteCommunicatable(fieldVelocity);
255 auto communicatableAngle = ConcreteCommunicatable(fieldAngle);
256 auto communicatableAngVelocity = ConcreteCommunicatable(fieldAngVelocity);
257
258 // Retrieve serial size
259 const std::vector<unsigned int> indices {0};
260 const std::size_t serialSize =
261 communicatableID.size(indices) + communicatablePosition.size(indices) +
262 communicatableVelocity.size(indices) + communicatableAngle.size(indices) +
263 communicatableAngVelocity.size(indices);
264
265 // Receive data and iterate buffer
266 // TODO: Improve processing of data, do not iterate through the all particles every time (maybe also add main iC to the communicated data to reduce processed particles)
267 communication::receiveAndExecuteForData(
268 listNeighbourRanks, serialSize, equationsOfMotionComm, mpiNbHelper,
269 [&](int rankOrig, std::uint8_t* buffer) {
270 std::size_t serialIdx = communicatableID.deserialize(indices, buffer);
271 serialIdx +=
272 communicatablePosition.deserialize(indices, &buffer[serialIdx]);
273 serialIdx +=
274 communicatableVelocity.deserialize(indices, &buffer[serialIdx]);
275 serialIdx +=
276 communicatableAngle.deserialize(indices, &buffer[serialIdx]);
277 serialIdx +=
278 communicatableAngVelocity.deserialize(indices, &buffer[serialIdx]);
279
280 communication::forParticlesInSuperParticleSystem(
281 sParticleSystem,
282 [&](Particle<T, PARTICLETYPE>& particle,
283 ParticleSystem<T, PARTICLETYPE>& particleSystem, int globiC) {
284 const std::size_t currentGlobalParticleID =
285 particle.template getField<PARALLELIZATION, ID>();
286 if (fieldID.getField(0) == currentGlobalParticleID) {
287 // Override particle data
288 particle.template setField<GENERAL, POSITION>(
289 fieldPosition.getField(0));
290 particle.template setField<MOBILITY, VELOCITY>(
291 fieldVelocity.getField(0));
292 particle.template setField<SURFACE, ANGLE>(
293 fieldAngle.getField(0));
294 particle.template setField<MOBILITY, ANG_VELOCITY>(
295 fieldAngVelocity.getField(0));
296 }
297 });
298 });
299}

References forParticlesInSuperParticleSystem(), olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::getField(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getNeighbourRanks(), and receiveAndExecuteForData().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ receiveParticles()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::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 )

Definition at line 621 of file relocation.h.

628{
629 using namespace particles::access;
630
631 //Retrieve load balancer and cuboid geometry
632 auto& superStructure = sParticleSystem.getSuperStructure();
633 auto& loadBalancer = superStructure.getLoadBalancer();
634
635 //Create list of local particle iDs to check afterwards,
636 // whether data was received (resolved only)
637 std::vector<std::vector<std::size_t>> receivedLocalIDs(
638 loadBalancer.size());
639
640 //Intra core relocations (without MPI)
641 for ( auto& buffer : dataListRelocationIntra ){
642 //Define raw buffer
643 std::uint8_t* rawBuffer = buffer.get();
644 int rankOrig = singleton::mpi().getRank();
645 assignParticleToIC( sParticleSystem, receivedLocalIDs, rankOrig, rawBuffer );
646 }
647
648 //Retrieve neighbour ranks
649 auto& listNeighbourRanks = sParticleSystem.getExtendedNeighbourRanks();
650 //Iterate over inter core received particle data
651 receiveAndExecuteForData( listNeighbourRanks, serialSize,
652 particleDistributionComm, mpiNbHelper,
653 [&](int rankOrig, std::uint8_t* rawBuffer){
654 //Assign particle to destination iC
655 assignParticleToIC( sParticleSystem, receivedLocalIDs, rankOrig, rawBuffer );
656 });
657
658 //Check, whether invalidation nccessary
659 if constexpr( providesSurface<PARTICLETYPE>() ){
660 checkInvalidationOnReceival( sParticleSystem, receivedLocalIDs, periodicity );
661 }
662}
const std::unordered_set< int > & getExtendedNeighbourRanks()
void assignParticleToIC(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< std::vector< std::size_t > > &receivedLocalIDs, int rankOrig, std::uint8_t *rawBuffer)
Definition relocation.h:517

References assignParticleToIC(), checkInvalidationOnReceival(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getExtendedNeighbourRanks(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::singleton::MpiManager::getRank(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), olb::singleton::mpi(), and receiveAndExecuteForData().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ searchParticleGlobally()

template<typename T , typename PARTICLETYPE , typename PCONDITION = conditions::valid_particle_centres, bool sync = true>
bool olb::particles::communication::searchParticleGlobally ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
std::size_t globalIDrequested,
std::size_t & localParticleID,
int & globiC )

Search particle in SuperParticleSystem by globalParticleID and return globiC if found.

  • WARNING: Sync is enabled by default, to avoid errors. As it might usually not be necessary though, communication can be disables to increase performance.

Definition at line 240 of file particleUtilities.h.

242{
243 using namespace descriptors;
244 static_assert(PARTICLETYPE::template providesNested<PARALLELIZATION,ID>(), "Field PARALLELIZATION:ID has to be provided");
245 //Retrieve load balancer
246 auto& loadBalancer = sParticleSystem.getSuperStructure().getLoadBalancer();
247 //Initialize return quantities
248 localParticleID = 0;
249 globiC = 0;
250 bool found = false;
251 //Loop over particle systems
252 for (int iC=0; iC<loadBalancer.size(); ++iC){
253 if (!found){
254 int globiC = loadBalancer.glob(iC);
255 //Retrieve container
256 auto bParticleSystems = sParticleSystem.getBlockParticleSystems();
257 auto& particleSystem = *bParticleSystems[iC];
258 //Search particle on particleSystem
259 //NOTE: Can not be substituted with searchParticle( ParticleSystem ..) due to globiC
260 for (std::size_t iP=0; iP<particleSystem.size(); ++iP) {
261 if (!found){
262 auto particle = particleSystem.get(iP);
263 //Execute F when particle meets condition
264 doWhenMeetingCondition<T,PARTICLETYPE,PCONDITION>( particle,
265 [&](Particle<T,PARTICLETYPE> particle){
266 auto globalID = particle.template getField<PARALLELIZATION,ID>();
267 if (globalID==globalIDrequested){
268 localParticleID = particle.getId();
269 found=true;
270 }
271 }, globiC);
272 } else {
273 break;
274 }
275 } //for (std::size_t iP=0; iP<particleSystem.size(); ++iP)
276 } else {
277 break;
278 }
279 } //for (int iC=0; iC<loadBalancer.size(); ++iC)
280#ifdef PARALLEL_MODE_MPI
281 if constexpr(sync){
282 singleton::mpi().reduceAndBcast(found, MPI_LOR);
283 if (found){
284 singleton::mpi().reduceAndBcast(globiC, MPI_MAX);
285 singleton::mpi().reduceAndBcast(localParticleID, MPI_MAX);
286 }
287 }
288#endif
289 return found;
290}

References olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getBlockParticleSystems(), olb::particles::Particle< T, PARTICLETYPE >::getId(), olb::SuperStructure< T, D >::getLoadBalancer(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSuperStructure(), and searchParticleGlobally().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ sendMappedData()

void olb::particles::communication::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 )

Definition at line 408 of file relocation.h.

414{
415 //Create map with vector holding individual data (of type std::uint8_t)
416 //Iterate over available ranks and retrieve total number of ranks taking part in communication
417 int noRelevantRanks = availableRanks.size();
418 //Check whether any rank is taking part in communication
419 //Allocate mpi requests for relevant ranks
420 mpiNbHelper.allocate(noRelevantRanks);
421 //Iterate over ranks with index iRank
422 int iRank = 0;
423 for (int rankEval : availableRanks) {
424 //Send data via mpi
425 singleton::mpi().iSend<std::uint8_t>(
426 rankDataMapSorted[rankEval].data(), //buffer: pointer to rank section in rankDataMapSorted
427 rankDataMapSorted[rankEval].size(), //count: number of bytes (per rank)
428 rankEval, //dest: destination rank
429 &mpiNbHelper.get_mpiRequest()[iRank], //request: request for iRank (iterator for relevant ranks)
430 1, //tag
431 Comm); //MPI_Comm scope
432 iRank += 1;
433 }
434}
void allocate(unsigned i)
Allocates memory.
MPI_Request * get_mpiRequest(int i=0) const
Get the specified request object.

References olb::singleton::MpiNonBlockingHelper::allocate(), olb::singleton::MpiNonBlockingHelper::get_mpiRequest(), olb::singleton::MpiManager::iSend(), and olb::singleton::mpi().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ serializeIcDest()

template<typename T , typename PARTICLETYPE >
std::size_t olb::particles::communication::serializeIcDest ( int globiCdest,
std::uint8_t * bufferiCandParticle )

Definition at line 151 of file utilities.h.

153{
154 //Define iC field as FieldArrayD with single entry
156 fieldiC.setField(0, globiCdest);
157 const std::vector<unsigned int> index{0};
158 auto communicatable = ConcreteCommunicatable(fieldiC);
159 //Serialize iC
160 communicatable.serialize(index, bufferiCandParticle);
161 //Return communicatable size
162 return communicatable.size(index);
163}

References olb::FieldArrayD< T, DESCRIPTOR, PLATFORM, FIELD >::setField().

+ Here is the call graph for this function:

◆ serializeIcDestAndParticle()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::serializeIcDestAndParticle ( int globiCdest,
Particle< T, PARTICLETYPE > & particle,
std::uint8_t * bufferiCandParticle )

Definition at line 166 of file utilities.h.

169{
170 //Serialize iC and retrieve particle buffer
171 std::size_t serialSizeField =
172 serializeIcDest<T,PARTICLETYPE>( globiCdest, bufferiCandParticle );
173 std::uint8_t* bufferRawParticle = &bufferiCandParticle[serialSizeField];
174 //Serialize particle
175 particle.serialize(bufferRawParticle);
176}
std::size_t serialize(std::uint8_t *buffer) const
Serialize data.
Definition particle.h:141

References olb::particles::Particle< T, PARTICLETYPE >::serialize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ updateParticleCuboidDistribution()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::updateParticleCuboidDistribution ( SuperParticleSystem< T, PARTICLETYPE > & sParticleSystem,
const T physDeltaX,
MPI_Comm particleDistributionComm,
const Vector< bool, PARTICLETYPE::d > & periodicity )

Definition at line 667 of file relocation.h.

675{
676 //Retrieve serial size
677 std::size_t serialSize = sParticleSystem.getSerialSize();
678
679 //Increase serial size by Field holding the globiC of the destination
680 // - for that, using FieldArrayD with single entry
681 //TODO: Optimization possible here:
682 // - Necessary for resolved particles
683 // - Not necessary for subgrid: This could be exchanged by on-rank retrieval
684 // of the ic depending on particle position. This would lead to a reduction
685 // in buffer size, which will most likely speed up communication significantly.
686 // A separate treatment will however be very error prone.
688 const ConstSpan<unsigned> index(0, 1);
689 // Workaround for Clang argument deduction bug
690 auto communicatable = ConcreteCommunicatable(fieldiC);
691 std::size_t serialSizeField = communicatable.size(index);
692 serialSize += serialSizeField;
693
694 //Check rankDataMapRelocationInter necessity and create relocation map TODO: adapt description
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 );
699
700#ifdef PARALLEL_MODE_MPI
701
702 //Create non blocking mpi helper
704
705 //Retrieve rank of direct neighbours
706 auto& listNeighbourRanks = sParticleSystem.getExtendedNeighbourRanks();
707
708 //Create ranDataMapSorted (WARNING: has to be existent until all data is received! c.f. #290)
709 std::map<int, std::vector<std::uint8_t> > rankDataMapSorted;
710
711 //Fill send buffer
712 fillSendBuffer( rankDataMapRelocationInter, rankDataMapSorted, serialSize );
713
714 //Send particles in rankDataMapRelocationInter map via mpi().iSend and return global number of bytes
715 sendMappedData( rankDataMapSorted, listNeighbourRanks,
716 serialSize, particleDistributionComm, mpiNbHelper );
717
718 //Receive particles via mpi().receive
719 receiveParticles( sParticleSystem, dataListRelocationIntra,
720 serialSize, particleDistributionComm, mpiNbHelper, periodicity );
721
722#else
723 std::cerr
724 << "ERROR: Invalidation treatement for sequential runs not implemented yet!"
725 << std::endl;
726 throw;
727#endif
728
729}
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)
Definition relocation.h:408
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)
Definition relocation.h:387
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)
Definition relocation.h:621
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)
Definition relocation.h:252

References checkRelocation(), fillSendBuffer(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getExtendedNeighbourRanks(), olb::particles::SuperParticleSystem< T, PARTICLETYPE >::getSerialSize(), receiveParticles(), and sendMappedData().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ updateSurfacePtr()

template<typename T , typename PARTICLETYPE >
void olb::particles::communication::updateSurfacePtr ( ParticleSystem< T, PARTICLETYPE > & particleSystem,
std::size_t iP )

Definition at line 42 of file relocation.h.

44{
45 using namespace descriptors;
46 static_assert(PARTICLETYPE::template providesNested<SURFACE,SURFACE_ID>(), "Field SURFACE_ID has to be provided");
47 //Retrieve particle
48 auto particle = particleSystem.get(iP);
49 //Retrieve surface id
50 std::size_t idxSurface = particle.template getField<SURFACE,SURFACE_ID>();
51 //Retrieve surface ptr
52 using SIndicatorBaseType = SmoothIndicatorF<T,T,PARTICLETYPE::d,true>;
53 auto& vectorOfIndicators = particleSystem.template getAssociatedData<
54 std::vector<std::unique_ptr<SIndicatorBaseType>>>();
55 auto sIndicatorPtr = vectorOfIndicators.at( idxSurface ).get();
56 //Update particle
57 particle.template setField<SURFACE,SINDICATOR>( sIndicatorPtr );
58}
std::conditional_t< D==2, SmoothIndicatorF2D< T, T, PARTICLE >, SmoothIndicatorF3D< T, T, PARTICLE > > SmoothIndicatorF
Definition aliases.h:278

References olb::particles::ParticleSystem< T, PARTICLETYPE >::get().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: