28#ifndef PARTICLE_CONTACT_COMMUNICATION_FUNCTIONS_H
29#define PARTICLE_CONTACT_COMMUNICATION_FUNCTIONS_H
37template <
typename T,
typename PARTICLECONTACTTYPE,
typename WALLCONTACTTYPE>
41#ifdef PARALLEL_MODE_MPI
45 int sumParticleContact = 0;
46 int sumWallContact = 0;
49 int localCountParticleContacts = 0;
50 int localCountWallContacts = 0;
65 sumParticleContact += countParticleContactsPerRank[rank];
67 sumWallContact += countWallContactsPerRank[rank];
72 localCountParticleContacts =
77 localCountWallContacts = contactContainer.
wallContacts.size();
90 if (sumParticleContact > 0 || sumWallContact > 0) {
92 sumParticleContact, sumWallContact);
93 int particleContactObjSize =
sizeof(PARTICLECONTACTTYPE);
94 int wallContactObjSize =
sizeof(WALLCONTACTTYPE);
99 WALLCONTACTTYPE* currWall = container.
wallContacts.data();
101 std::uint8_t* bytesParticle = (std::uint8_t*)currParticle;
102 std::uint8_t* bytesWall = (std::uint8_t*)currWall;
105 countParticleContactsPerRank[rank] *
106 particleContactObjSize,
109 bytesWall, countWallContactsPerRank[rank] * wallContactObjSize,
117 particleContactObjSize);
118 std::memcpy(bytesWall,
123 currParticle += countParticleContactsPerRank[rank];
124 currWall += countWallContactsPerRank[rank];
128 PARTICLECONTACTTYPE* currParticle =
130 WALLCONTACTTYPE* currWall = contactContainer.
wallContacts.data();
131 std::uint8_t* bytesParticle = (std::uint8_t*)currParticle;
132 std::uint8_t* bytesWall = (std::uint8_t*)currWall;
134 bytesParticle, localCountParticleContacts * particleContactObjSize,
137 localCountWallContacts * wallContactObjSize,
147 std::uint8_t* containerParticlesBytes =
150 sumParticleContact * particleContactObjSize,
152 std::uint8_t* containerWallBytes =
155 sumWallContact * wallContactObjSize,
167 contactContainer = container;
174template <
typename T,
typename PARTICLETYPE,
typename PARTICLECONTACTTYPE,
175 typename WALLCONTACTTYPE,
typename F>
182 using namespace descriptors;
190 particles::communication::getCuboidMin<T, PARTICLETYPE::d>(
193 particles::communication::getCuboidMax<T, PARTICLETYPE::d>(
200 const std::size_t currentGlobalParticleID =
201 particle.template getField<PARALLELIZATION, ID>();
203 for (WALLCONTACTTYPE& wallContact : contactContainer.
wallContacts) {
204 if (!wallContact.isEmpty() && !wallContact.isNew() &&
205 wallContact.getParticleID() == currentGlobalParticleID &&
209 wallContact.resetMinMax();
211 particle, cellMin, cellMax, getSetupPeriodicity, physDeltaX);
212 wallContact.setParticlePosition(unifiedPos);
215 particle, wallContact.getParticlePosition(), min, cellMin,
216 cellMax, getSetupPeriodicity, physDeltaX);
219 particle, wallContact.getParticlePosition(), max, cellMin,
220 cellMax, getSetupPeriodicity, physDeltaX);
221 wallContact.updateMinMax(newMin);
222 wallContact.updateMinMax(newMax);
225 for (PARTICLECONTACTTYPE& particleContact :
227 if (!particleContact.isEmpty() && !particleContact.isNew() &&
228 particleContact.getIDs()[0] == currentGlobalParticleID &&
229 particleContact.getResponsibleRank() ==
233 particleContact.resetMinMax();
234 std::array<PhysR<T, PARTICLETYPE::d>, 2> unifiedPos;
235 auto particleB = sParticleSystem.
get(particleContact.getIDs()[1]);
237 getSetupPeriodicity, unifiedPos,
239 particleContact.setParticlePositions(unifiedPos);
242 particle, particleContact.getParticlePositions()[0], min,
243 cellMin, cellMax, getSetupPeriodicity, physDeltaX);
246 particle, particleContact.getParticlePositions()[0], max,
247 cellMin, cellMax, getSetupPeriodicity, physDeltaX);
248 particleContact.updateMinMax(newMin);
249 particleContact.updateMinMax(newMax);
256template <
typename T,
typename PARTICLETYPE,
bool CONVEX>
263 using namespace descriptors;
270 std::set<int> intersectingRanks {};
271 std::array<int, 2> responsibleRank = {-1, -1};
272 std::array<std::set<int>, 2> touchedRanks {};
273 std::unordered_set<int> destRanks {};
276 const auto errorTreatment = [&contact, &destRanks]() {
288 const std::size_t globalParticleID =
289 particle.template getField<PARALLELIZATION, ID>();
291 for (
unsigned short index = 0; index < 2; ++index) {
292 if (globalParticleID == contact.
getIDs()[index]) {
293 const int globiCcenter =
294 particle.template getField<PARALLELIZATION, IC>();
295 responsibleRank[index] = loadBalancer.rank(globiCcenter);
296 touchedRanks[index].insert(responsibleRank[index]);
302 sParticleSystem, position, circumRadius, periodicity,
303 globiCcenter, [&](
const int iC) {
304 touchedRanks[index].insert(loadBalancer.rank(iC));
312 if (touchedRanks[0].empty() || touchedRanks[1].empty() ||
313 responsibleRank[0] < 0 || responsibleRank[1] < 0) {
317 else if (responsibleRank[0] == responsibleRank[1]) {
318 destRanks.insert(responsibleRank[0]);
323 std::set_intersection(
324 touchedRanks[0].begin(), touchedRanks[0].end(), touchedRanks[1].begin(),
325 touchedRanks[1].end(),
326 std::inserter(intersectingRanks, intersectingRanks.begin()));
337 if (!intersectingRanks.empty()) {
338 destRanks.insert(responsibleRank[0]);
339 destRanks.insert(responsibleRank[1]);
342 if (responsibleRank[0] > responsibleRank[1]) {
343 std::swap(responsibleRank[0], responsibleRank[1]);
347 if (intersectingRanks.find(responsibleRank[0]) !=
348 intersectingRanks.end()) {
351 else if (intersectingRanks.find(responsibleRank[1]) !=
352 intersectingRanks.end()) {
357 const int responsibleRankContact = *intersectingRanks.begin();
359 destRanks.insert(responsibleRankContact);
367#ifdef VERBOSE_CONTACT_COMMUNICATION
368 std::cout <<
"Contact of ids " << contact.
getIDs()[0] <<
" & "
369 << contact.
getIDs()[1] <<
" goes to " << destRanks <<
" and "
371 <<
" is responsible for the calculation (Rank "
373 <<
" the intersection was " << intersectingRanks
374 <<
" from touched ranks " << touchedRanks[0] <<
" and "
375 << touchedRanks[1] << std::endl;
382template <
typename T,
typename PARTICLETYPE,
bool CONVEX>
388 using namespace descriptors;
392 bool isSuccessful =
false;
393 std::unordered_set<int> destRanks {};
401 const std::size_t globalParticleID =
402 particle.template getField<PARALLELIZATION, ID>();
404 std::size_t globiCcenter =
405 particle.template getField<PARALLELIZATION, IC>();
406 destRank = loadBalancer.rank(globiCcenter);
414 destRanks.insert(destRank);
417#ifdef VERBOSE_CONTACT_COMMUNICATION
419 <<
" & solid boundary " << contact.
getWallID() <<
" goes to "
420 << destRanks << std::endl;
428template <
typename T,
typename PARTICLETYPE,
bool CONVEX>
435 using namespace descriptors;
438 auto& cuboidGeometry = superStructure.getCuboidGeometry();
440 std::unordered_set<int> destRanks;
441 std::array<std::set<int>, 2> touchedRanks;
449 const std::size_t globalParticleID =
450 particle.template getField<PARALLELIZATION, ID>();
452 for (
unsigned short index = 0; index < 2; ++index) {
453 if (globalParticleID == contact.
getIDs()[index]) {
459 cuboidGeometry, periodicity, position, globiCcenter);
461 touchedRanks[index].insert(loadBalancer.rank(globiCcenter));
465 sParticleSystem, position, circumRadius, periodicity,
466 globiCcenter, [&](
const int iC) {
467 touchedRanks[index].insert(loadBalancer.rank(iC));
474 std::set_intersection(touchedRanks[0].begin(), touchedRanks[0].end(),
475 touchedRanks[1].begin(), touchedRanks[1].end(),
476 std::inserter(destRanks, destRanks.begin()));
478#ifdef VERBOSE_CONTACT_COMMUNICATION
479 std::cout <<
"Contact of ids " << contact.
getIDs()[0] <<
" & "
480 << contact.
getIDs()[1] <<
" goes to " << destRanks <<
" and "
482 <<
" is responsible for the calculation (Rank "
484 <<
"Touched ranks of 1. particle: " << touchedRanks[0]
485 <<
" and touched ranks of 2. particle: " << touchedRanks[1]
493template <
typename T,
typename PARTICLETYPE,
bool CONVEX>
499 using namespace descriptors;
502 auto& cuboidGeometry = superStructure.getCuboidGeometry();
504 std::unordered_set<int> destRanks;
512 const std::size_t globalParticleID =
513 particle.template getField<PARALLELIZATION, ID>();
520 cuboidGeometry, periodicity, position, globiCcenter);
522 destRanks.insert(loadBalancer.rank(globiCcenter));
526 sParticleSystem, position, circumRadius, periodicity,
527 globiCcenter, [&](
const int iC) {
528 destRanks.insert(loadBalancer.rank(iC));
534#ifdef VERBOSE_CONTACT_COMMUNICATION
536 <<
" & solid boundary " << contact.
getWallID() <<
" goes to "
538 <<
" is responsible for the calculation" << std::endl;
544template <
typename T,
typename PARTICLETYPE,
typename CONTACTTYPE,
bool CONVEX,
545 bool SANITYCHECK =
false>
550 std::vector<CONTACTTYPE>& contacts, [[maybe_unused]]
int rankOrig)
552 using namespace descriptors;
554 bool addNewContact =
true;
557 if constexpr (SANITYCHECK) {
559 bool isParticleDataAvailable[2] = {
false,
false};
565 for (
unsigned short i = 0; i < 2; ++i) {
566 if (particle.template getField<PARALLELIZATION, ID>() ==
568 isParticleDataAvailable[i] = true;
572 if (!isParticleDataAvailable[0] || !isParticleDataAvailable[1]) {
573 addNewContact =
false;
575 <<
" received a contact of particles with the global ids "
576 << newcontact.
getIDs()[0] <<
" and " << newcontact.
getIDs()[1]
577 <<
" from rank " << rankOrig
578 <<
" for which no particle data are available." << std::endl;
584 const std::array<std::size_t, 2> particleIDs = newcontact.
getIDs();
586 const std::function<bool(
const CONTACTTYPE&)> condition =
587 [&particleIDs](
const CONTACTTYPE& contact) {
593 if (contactIt != std::end(contacts)) {
594 contactIt->combineWith(newcontact);
597 contacts.push_back(newcontact);
600#ifdef VERBOSE_CONTACT_COMMUNICATION
602 <<
" received contact of ids " << newcontact.
getIDs()[0] <<
" & "
603 << newcontact.
getIDs()[1] <<
". Rank "
605 <<
" is responsible for the calculation." << std::endl;
610template <
typename T,
typename PARTICLETYPE,
typename CONTACTTYPE,
bool CONVEX,
611 bool SANITYCHECK =
false>
615 std::vector<CONTACTTYPE>& contacts,
616 [[maybe_unused]]
int rankOrig)
618 using namespace descriptors;
620 bool addNewContact =
true;
622 if constexpr (SANITYCHECK) {
624 bool isParticleDataAvailable =
false;
630 if (particle.template getField<PARALLELIZATION, ID>() ==
631 newcontact.getParticleID()) {
632 isParticleDataAvailable = true;
635 if (!isParticleDataAvailable) {
636 addNewContact =
false;
638 <<
" received a contact of particle with the global id "
639 << newcontact.getParticleID() <<
" from rank " << rankOrig
640 <<
" for which no particle data is available." << std::endl;
646 const std::size_t particleID = newcontact.getParticleID();
647 const std::size_t solidBoundaryMaterial = newcontact.getWallID();
649 const std::function<bool(
const CONTACTTYPE&)> condition =
650 [&particleID, &solidBoundaryMaterial](
const CONTACTTYPE& contact) {
651 return particleID == contact.getParticleID() &&
652 solidBoundaryMaterial == contact.getWallID();
657 if (contactIt != std::end(contacts)) {
658 contactIt->combineWith(newcontact);
661 contacts.push_back(newcontact);
666template <
typename T,
typename PARTICLETYPE,
typename CONTACTTYPE>
668 std::vector<CONTACTTYPE>& contacts,
670#ifdef PARALLEL_MODE_MPI
671 MPI_Comm contactDetectionComm,
675#ifdef PARALLEL_MODE_MPI
680 constexpr std::size_t serialSize = CONTACTTYPE::getSerialSize();
682 std::multimap<int, std::unique_ptr<std::uint8_t[]>> dataMap;
684 for (CONTACTTYPE& contact : contacts) {
688 if (!contact.isEmpty()) {
690 contact, sParticleSystem, deltaX, periodicity)};
696 && (contact.isNew() ||
698 for (
const int destRank : destRanks) {
700 std::unique_ptr<std::uint8_t[]> buffer(
701 new std::uint8_t[serialSize] {});
702 contact.serialize(buffer.get());
703 dataMap.insert(std::make_pair(destRank, std::move(buffer)));
718 std::map<int, std::vector<std::uint8_t>> rankDataMapSorted;
723 serialSize, contactDetectionComm, mpiNbHelper);
727 listNeighbourRanks, serialSize, contactDetectionComm, mpiNbHelper,
728 [&](
int rankOrig, std::uint8_t* buffer) {
729 CONTACTTYPE newcontact;
730 newcontact.deserialize(buffer);
732#ifdef VERBOSE_CONTACT_COMMUNICATION
733 std::cout <<
"From Rank " << rankOrig <<
": ";
741template <
typename T,
typename PARTICLETYPE,
typename PARTICLECONTACTTYPE,
742 typename WALLCONTACTTYPE>
746#ifdef PARALLEL_MODE_MPI
747 MPI_Comm particleContactDetectionComm, MPI_Comm wallContactDetectionComm,
751#ifdef PARALLEL_MODE_MPI
755 deltaX, wallContactDetectionComm, periodicity);
758 sParticleSystem, deltaX,
759 particleContactDetectionComm, periodicity);
763template <
typename T,
typename PARTICLETYPE,
typename CONTACTTYPE>
765 std::vector<CONTACTTYPE>& contacts,
767#ifdef PARALLEL_MODE_MPI
768 MPI_Comm postContactTreatmentComm,
772#ifdef PARALLEL_MODE_MPI
773 OstreamManager clout(std::cout,
"postContactTreatmentCommunication");
777 constexpr std::size_t serialSize = CONTACTTYPE::getSerialSize();
779 std::multimap<int, std::unique_ptr<std::uint8_t[]>> dataMap;
781 for (CONTACTTYPE& contact : contacts) {
783 if (!contact.isEmpty()) {
784 std::unordered_set<int> destRanks {
786 contact, sParticleSystem, deltaX, periodicity)};
788 for (
const int destRank : destRanks) {
790 std::unique_ptr<std::uint8_t[]> buffer(
791 new std::uint8_t[serialSize] {});
792 contact.serialize(buffer.get());
793 dataMap.insert(std::make_pair(destRank, std::move(buffer)));
800 contact.resetMinMax();
807 std::map<int, std::vector<std::uint8_t>> rankDataMapSorted;
812 serialSize, postContactTreatmentComm,
820 listNeighbourRanks, serialSize, postContactTreatmentComm, mpiNbHelper,
821 [&](
int rankOrig, std::uint8_t* buffer) {
822 CONTACTTYPE newcontact;
823 newcontact.deserialize(buffer);
829template <
typename T,
typename PARTICLETYPE,
typename PARTICLECONTACTTYPE,
830 typename WALLCONTACTTYPE>
835#ifdef PARALLEL_MODE_MPI
836 MPI_Comm particlePostContactTreatmentComm,
837 MPI_Comm wallPostContactTreatmentComm,
841#ifdef PARALLEL_MODE_MPI
842 OstreamManager clout(std::cout,
"postContactTreatmentCommunication");
846 wallPostContactTreatmentComm, periodicity);
850 particlePostContactTreatmentComm, periodicity);
855#ifdef PARALLEL_MODE_MPI
856template <
typename T,
unsigned D>
862 std::array<std::size_t, 1> commGlobalParticleID {1};
873 const std::vector<unsigned> indicesID {0};
874 std::vector<unsigned> indicesForce;
875 if constexpr (D == 3) {
876 indicesForce = std::vector<unsigned> {0, 1, 2};
879 indicesForce = std::vector<unsigned> {0, 1};
881 std::vector<unsigned> indicesTorque;
882 if constexpr (D == 3) {
883 indicesTorque = indicesForce;
886 indicesTorque = std::vector<unsigned> {0};
890 return communicatableID.
size(indicesID) +
891 communicatableForce.
size(indicesForce) +
892 communicatableTorque.
size(indicesTorque);
896template <
typename T,
unsigned D>
898 const std::size_t& globalParticleID,
Vector<T, D>& force,
901 std::multimap<
int, std::unique_ptr<std::uint8_t[]>>& dataMap)
903#ifdef PARALLEL_MODE_MPI
905 std::array<std::size_t, 1> commGlobalParticleID {globalParticleID};
912 const std::vector<unsigned> indicesID {0};
913 std::vector<unsigned> indicesForce;
914 if constexpr (D == 3) {
915 indicesForce = std::vector<unsigned> {0, 1, 2};
918 indicesForce = std::vector<unsigned> {0, 1};
920 std::vector<unsigned> indicesTorque;
921 if constexpr (D == 3) {
922 indicesTorque = indicesForce;
925 indicesTorque = std::vector<unsigned> {0};
929 const std::size_t serialSize = communicatableID.
size(indicesID) +
930 communicatableForce.
size(indicesForce) +
931 communicatableTorque.
size(indicesTorque);
933 std::unique_ptr<std::uint8_t[]> buffer(
new std::uint8_t[serialSize] {});
934 std::uint8_t* bufferRaw = buffer.get();
935 std::size_t serialIdx = communicatableID.
serialize(indicesID, bufferRaw);
937 communicatableForce.
serialize(indicesForce, &bufferRaw[serialIdx]);
939 communicatableTorque.
serialize(indicesTorque, &bufferRaw[serialIdx]);
941 dataMap.insert(std::make_pair(destRank, std::move(buffer)));
942#ifdef VERBOSE_CONTACT_COMMUNICATION
944 <<
" sends contact treatment results of particle "
945 << globalParticleID <<
" to " << destRank << std::endl;
950#ifdef PARALLEL_MODE_MPI
951template <
typename T,
typename PARTICLETYPE>
956 using namespace descriptors;
959 constexpr unsigned D = PARTICLETYPE::d;
965#ifdef VERBOSE_CONTACT_COMMUNICATION
967 for (
auto& neighbourRank : listNeighbourRanks) {
968 std::cout << neighbourRank <<
" ";
970 std::cout << std::endl;
974 const std::vector<unsigned> indicesID {0};
975 std::vector<unsigned> indicesForce;
976 if constexpr (D == 3) {
977 indicesForce = std::vector<unsigned> {0, 1, 2};
980 indicesForce = std::vector<unsigned> {0, 1};
982 std::vector<unsigned> indicesTorque;
983 if constexpr (D == 3) {
984 indicesTorque = indicesForce;
987 indicesTorque = std::vector<unsigned> {0};
990 std::array<std::size_t, 1> commGlobalParticleID;
1003 const std::size_t serialSize = communicatableID.
size(indicesID) +
1004 communicatableForce.
size(indicesForce) +
1005 communicatableTorque.
size(indicesTorque);
1010 listNeighbourRanks, serialSize, contactTreatmentComm, mpiNbHelper,
1011 [&](
int rankOrig, std::uint8_t* buffer) {
1012 std::size_t serialIdx = communicatableID.
deserialize(indicesID, buffer);
1014 communicatableForce.
deserialize(indicesForce, &buffer[serialIdx]);
1016 communicatableTorque.
deserialize(indicesTorque, &buffer[serialIdx]);
1018#ifdef VERBOSE_CONTACT_COMMUNICATION
1020 <<
" received contact treatment results for particle "
1021 << commGlobalParticleID[0] <<
" (force = " << contactForce
1022 <<
"; torque = " << contactTorque <<
") from rank "
1023 << rankOrig << std::endl;
1031 const std::size_t currentGlobalParticleID =
1032 particle.template getField<PARALLELIZATION, ID>();
1033 if (commGlobalParticleID[0] == currentGlobalParticleID) {
1036 particle.template getField<FORCING, FORCE>();
1037 particle.template setField<FORCING, FORCE>(force +
1041 particle.template getField<FORCING, TORQUE>());
1042 particle.template setField<FORCING, TORQUE>(
1044 torque + contactTorque));
1051template <
typename T,
typename PARTICLETYPE>
1054 std::multimap<
int, std::unique_ptr<std::uint8_t[]>>& dataMap
1055#ifdef PARALLEL_MODE_MPI
1057 MPI_Comm contactTreatmentComm
1061#ifdef PARALLEL_MODE_MPI
1062 if constexpr (access::providesParallelization<PARTICLETYPE>()) {
1064 std::size_t serialSize =
1065 getContactTreatmentResultsSerialSize<T, PARTICLETYPE::d>();
1070 std::map<int, std::vector<std::uint8_t>> rankDataMapSorted;
1076 contactTreatmentComm, mpiNbHelper);
std::size_t deserialize(ConstSpan< CellID > indices, const std::uint8_t *buffer) override
Deserialize data at locations indices to buffer
std::size_t serialize(ConstSpan< CellID > indices, std::uint8_t *buffer) const override
Serialize data at locations indices to buffer
std::size_t size(ConstSpan< CellID > indices) const override
Get serialized size for data at locations indices
class for marking output with some text
Representation of a statistic for a parallel 2D geometry.
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
SuperStructure< T, PARTICLETYPE::d > & getSuperStructure()
Particle< T, PARTICLETYPE > get(std::size_t globalParticleID)
const std::unordered_set< int > & getNeighbourRanks()
void send(T *buf, int count, int dest, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Sends data at *buf, blocking.
void bCast(T *sendBuf, int sendCount, int root=0, MPI_Comm comm=MPI_COMM_WORLD)
Broadcast data from one processor to multiple processors.
int getSize() const
Returns the number of processes.
bool isMainProcessor() const
Tells whether current processor is main processor.
int getRank() const
Returns the process ID.
int bossId() const
Returns process ID of main processor.
void receive(T *buf, int count, int source, int tag=0, MPI_Comm comm=MPI_COMM_WORLD)
Receives data at *buf, blocking.
Helper class for non blocking MPI communication.
Vector< T, PARTICLETYPE::d > getPosition(Particle< T, PARTICLETYPE > particle)
void receiveAndExecuteForData(const std::unordered_set< int > &availableRanks, std::size_t serialSize, MPI_Comm Comm, singleton::MpiNonBlockingHelper &mpiNbHelper, F f)
std::unordered_set< int > getSurfaceTouchingICs(CuboidGeometry< T, D > &cuboidGeometry, Vector< T, D > position, T circumRadius, const Vector< bool, D > &periodicity, int globiC, F f=[](int){})
Get a set of surface touching iCs (that are not globiC) Allows to run an optional function per unique...
void 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)
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.
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 forParticlesInSuperParticleSystem(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, F f)
void unifyPositions(Particle< T, PARTICLETYPE > &particle1, Particle< T, PARTICLETYPE > &particle2, const PhysR< T, PARTICLETYPE::d > &cellMin, const PhysR< T, PARTICLETYPE::d > &cellMax, F getSetupPeriodicity, std::array< PhysR< T, PARTICLETYPE::d >, 2 > &positions, T deltaX)
void accountForPeriodicParticleBoundary(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, contact::ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, const SuperGeometry< T, PARTICLETYPE::d > &sGeometry, F getSetupPeriodicity)
update positions in contact to account for periodic boundaries
void receiveContactTreatmentResults(SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, MPI_Comm contactTreatmentComm, singleton::MpiNonBlockingHelper &mpiNbHelper)
void cleanContacts(std::vector< CONTACTTYPE > &contacts)
void resetResponsibleRank(CONTACTTYPE &contact)
bool particleContactConsistsOfIDs(PARTICLECONTACTTYPE &particleContact, const std::array< size_t, 2 > &ids)
bool isResponsibleRankSet(CONTACTTYPE &contact)
void receiveContact(ParticleContactArbitraryFromOverlapVolume< T, PARTICLETYPE::d, CONVEX > &newcontact, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, std::vector< CONTACTTYPE > &contacts, int rankOrig)
void communicateContactTreatmentResults(SuperParticleSystem< T, PARTICLETYPE > &particleSystem, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &dataMap, MPI_Comm contactTreatmentComm)
PhysR< T, PARTICLETYPE::d > evalContactPosition(Particle< T, PARTICLETYPE > &particle, const PhysR< T, PARTICLETYPE::d > &particlePos, const PhysR< T, PARTICLETYPE::d > &contactPos, const PhysR< T, PARTICLETYPE::d > &cellMin, const PhysR< T, PARTICLETYPE::d > &cellMax, F getSetupPeriodicity, T deltaX)
void communicateParallelContacts(std::vector< CONTACTTYPE > &contacts, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T deltaX, MPI_Comm contactDetectionComm, const Vector< bool, PARTICLETYPE::d > &periodicity)
T evalCircumRadius(T const contactDetectionDistance, T const circumRadius, T const epsilon)
void communicateContactsParallel(ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T deltaX, MPI_Comm particleContactDetectionComm, MPI_Comm wallContactDetectionComm, const Vector< bool, PARTICLETYPE::d > &periodicity)
void communicatePostContactTreatmentContacts(std::vector< CONTACTTYPE > &contacts, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T deltaX, MPI_Comm postContactTreatmentComm, const Vector< bool, PARTICLETYPE::d > &periodicity)
int getContactTreatmentResultsSerialSize()
void extendContactTreatmentResultsDataMap(const std::size_t &globalParticleID, Vector< T, D > &force, Vector< T, utilities::dimensions::convert< D >::rotation > &torque, const int destRank, std::multimap< int, std::unique_ptr< std::uint8_t[]> > &dataMap)
auto getContactIterator(std::vector< CONTACTTYPE > &contacts, const std::function< bool(const CONTACTTYPE &)> condition)
PhysR< T, PARTICLETYPE::d > unifyPosition(Particle< T, PARTICLETYPE > &particle, const PhysR< T, PARTICLETYPE::d > &cellMin, const PhysR< T, PARTICLETYPE::d > &cellMax, F getSetupPeriodicity, T deltaX)
std::unordered_set< int > evalDestRanksForDetectionCommunication(ParticleContactArbitraryFromOverlapVolume< T, PARTICLETYPE::d, CONVEX > &contact, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T deltaX, const Vector< bool, PARTICLETYPE::d > &periodicity)
evaluate responsible ranks for particle-particle contact
std::unordered_set< int > evalDestRanksForPostContactTreatmentCommunication(ParticleContactArbitraryFromOverlapVolume< T, PARTICLETYPE::d, CONVEX > &contact, SuperParticleSystem< T, PARTICLETYPE > &sParticleSystem, const T deltaX, const Vector< bool, PARTICLETYPE::d > &periodicity)
evaluate ranks that touch both particles of a particle-particle contact
void communicateContacts(ContactContainer< T, PARTICLECONTACTTYPE, WALLCONTACTTYPE > &contactContainer)
Top level namespace for all of OpenLB.
std::vector< PARTICLECONTACTTYPE > particleContacts
resizeable vector containing all particle-particle contacts
void cleanContacts()
Clean contacts - remove "empty" contacts.
std::vector< WALLCONTACTTYPE > wallContacts
resizeable vector containg all particle-wall contacts
void combineContacts()
Combine contacts with same ids.
An object holding data for a contact which is described analog to Nassauer and Kuna (2013)
constexpr const std::array< std::size_t, 2 > & getIDs() const
Read access to particle IDs.
constexpr const int & getResponsibleRank() const
Read access to the responsible rank.
constexpr void resetMinMax()
Reset min and max to default values.
constexpr void setResponsibleRank(const int &rank)
Set processor that is responsible for contact treatment.
constexpr void setResponsibleRank(const int &rank)
Set processor that is responsible for contact treatment.
constexpr const std::size_t & getParticleID() const
Read access to particle ID.
constexpr unsigned getWallID() const
Read access to wall matreial.
constexpr const int & getResponsibleRank() const
Read access to the responsible rank.
Converts dimensions by deriving from given cartesian dimension D.