@@ -792,15 +792,18 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) {
792792 nPoint_Send_All[0 ] = 0 ;
793793 int * nPoint_Recv_All = new int [size + 1 ];
794794 nPoint_Recv_All[0 ] = 0 ;
795- int * nPoint_Flag = new int [size];
796795
797- for (iRank = 0 ; iRank < size; iRank++) {
798- nPoint_Send_All[iRank] = 0 ;
799- nPoint_Recv_All[iRank] = 0 ;
800- nPoint_Flag[iRank] = -1 ;
801- }
802- nPoint_Send_All[size] = 0 ;
803- nPoint_Recv_All[size] = 0 ;
796+ /* --- Store a set of unique (point, marker) pairs per destination rank. ---*/
797+ using PointMarkerPair = std::pair<unsigned long , unsigned long >;
798+
799+ struct PairHash {
800+ std::size_t operator ()(const PointMarkerPair& p) const {
801+ return std::hash<unsigned long >{}(p.first ) ^ (std::hash<unsigned long >{}(p.second ) << 1 );
802+ }
803+ };
804+
805+ using PointMarkerSet = std::unordered_set<PointMarkerPair, PairHash>;
806+ std::vector<PointMarkerSet> Points_Send_All (size);
804807
805808 /* --- Loop through all of our periodic markers and track
806809 our sends with each rank. ---*/
@@ -821,19 +824,19 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) {
821824
822825 iRank = static_cast <int >(geometry->vertex [iMarker][iVertex]->GetDonorProcessor ());
823826
824- /* --- If we have not visited this point last, increment our
825- number of points that must be sent to a particular proc. ---*/
826-
827- if ((nPoint_Flag[iRank] != static_cast <int >(iPoint))) {
828- nPoint_Flag[iRank] = static_cast <int >(iPoint);
829- nPoint_Send_All[iRank + 1 ] += 1 ;
830- }
827+ /* --- Store the (point, marker) pair in the set for the destination rank. ---*/
828+ Points_Send_All[iRank].insert (std::make_pair (iPoint, static_cast <unsigned long >(iMarker)));
831829 }
832830 }
833831 }
834832 }
835833
836- delete[] nPoint_Flag;
834+ for (iRank = 0 ; iRank < size; iRank++) {
835+ nPoint_Send_All[iRank + 1 ] = Points_Send_All[iRank].size ();
836+ nPoint_Recv_All[iRank + 1 ] = 0 ;
837+ }
838+ // nPoint_Send_All[size] = 0;
839+ nPoint_Recv_All[size] = 0 ;
837840
838841 /* --- Communicate the number of points to be sent/recv'd amongst
839842 all processors. After this communication, each proc knows how
@@ -943,11 +946,15 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) {
943946 auto * idSend = new unsigned long [nPoint_PeriodicSend[nPeriodicSend] * nPackets];
944947 for (iSend = 0 ; iSend < nPoint_PeriodicSend[nPeriodicSend] * nPackets; iSend++) idSend[iSend] = 0 ;
945948
949+ /* --- Re-use set of unique points per destination rank. ---*/
950+ for (iRank = 0 ; iRank < size; iRank++) Points_Send_All[iRank].clear ();
951+
946952 /* --- Build the lists of local index and periodic marker index values. ---*/
947953
948954 ii = 0 ;
949955 jj = 0 ;
950956 for (iSend = 0 ; iSend < nPeriodicSend; iSend++) {
957+ int destRank = Neighbors_PeriodicSend[iSend];
951958 for (iMarker = 0 ; iMarker < config->GetnMarker_All (); iMarker++) {
952959 if (config->GetMarker_All_KindBC (iMarker) == PERIODIC_BOUNDARY) {
953960 iPeriodic = config->GetMarker_All_PerBound (iMarker);
@@ -969,14 +976,22 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) {
969976 index on the matching periodic point and the periodic marker
970977 index to be communicated to the recv rank. ---*/
971978
972- if (iRank == Neighbors_PeriodicSend[iSend]) {
973- Local_Point_PeriodicSend[ii] = iPoint;
974- Local_Marker_PeriodicSend[ii] = static_cast <unsigned long >(iMarker);
975- jj = ii * nPackets;
976- idSend[jj] = geometry->vertex [iMarker][iVertex]->GetDonorPoint ();
977- jj++;
978- idSend[jj] = static_cast <unsigned long >(iPeriodic);
979- ii++;
979+ if (iRank == destRank) {
980+ /* --- Check if we have already added this (point, marker) pair
981+ for this destination rank. ---*/
982+ auto pointMarkerPair = std::make_pair (iPoint, static_cast <unsigned long >(iMarker));
983+ if (Points_Send_All[destRank].find (pointMarkerPair) == Points_Send_All[destRank].end ()) {
984+ Local_Point_PeriodicSend[ii] = iPoint;
985+ Local_Marker_PeriodicSend[ii] = static_cast <unsigned long >(iMarker);
986+ jj = ii * nPackets;
987+ idSend[jj] = geometry->vertex [iMarker][iVertex]->GetDonorPoint ();
988+ jj++;
989+ idSend[jj] = static_cast <unsigned long >(iPeriodic);
990+ ii++;
991+
992+ /* --- Store the (point, marker) pair in the set for the destination rank. ---*/
993+ Points_Send_All[destRank].insert (pointMarkerPair);
994+ }
980995 }
981996 }
982997 }
0 commit comments