Skip to content

Commit 3b3f73e

Browse files
authored
Merge pull request #2520 from su2code/fix_periodic_parallel
Fix periodic parallel preprocessing
2 parents a0ab3da + 70e7863 commit 3b3f73e

File tree

4 files changed

+145
-24
lines changed

4 files changed

+145
-24
lines changed

Common/src/geometry/CGeometry.cpp

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -792,15 +792,20 @@ 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+
auto pairHash = [](const PointMarkerPair& p) -> std::size_t {
800+
// Use the golden ratio constant and bit mixing to generate pair hash
801+
std::size_t h1 = std::hash<unsigned long>{}(p.first);
802+
std::size_t h2 = std::hash<unsigned long>{}(p.second);
803+
804+
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
805+
};
806+
807+
using PointMarkerSet = std::unordered_set<PointMarkerPair, decltype(pairHash)>;
808+
std::vector<PointMarkerSet> Points_Send_All(size, PointMarkerSet(0, pairHash));
804809

805810
/*--- Loop through all of our periodic markers and track
806811
our sends with each rank. ---*/
@@ -821,19 +826,17 @@ void CGeometry::PreprocessPeriodicComms(CGeometry* geometry, CConfig* config) {
821826

822827
iRank = static_cast<int>(geometry->vertex[iMarker][iVertex]->GetDonorProcessor());
823828

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-
}
829+
/*--- Store the (point, marker) pair in the set for the destination rank. ---*/
830+
Points_Send_All[iRank].insert(std::make_pair(iPoint, static_cast<unsigned long>(iMarker)));
831831
}
832832
}
833833
}
834834
}
835835

836-
delete[] nPoint_Flag;
836+
for (iRank = 0; iRank < size; iRank++) {
837+
nPoint_Send_All[iRank + 1] = Points_Send_All[iRank].size();
838+
nPoint_Recv_All[iRank + 1] = 0;
839+
}
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,21 @@ 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. Use the result if insert(), which is
982+
a pair whose second element is success. ---*/
983+
const auto pointMarkerPair = std::make_pair(iPoint, static_cast<unsigned long>(iMarker));
984+
const auto insertResult = Points_Send_All[destRank].insert(pointMarkerPair);
985+
if (insertResult.second) {
986+
Local_Point_PeriodicSend[ii] = iPoint;
987+
Local_Marker_PeriodicSend[ii] = static_cast<unsigned long>(iMarker);
988+
jj = ii * nPackets;
989+
idSend[jj] = geometry->vertex[iMarker][iVertex]->GetDonorPoint();
990+
jj++;
991+
idSend[jj] = static_cast<unsigned long>(iPeriodic);
992+
ii++;
993+
}
980994
}
981995
}
982996
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2+
% %
3+
% SU2 configuration file %
4+
% Case description: Isentropic vortex (FVM) %
5+
% Author: Brian Munguía %
6+
% Date: 2025.25.06 %
7+
% File Version 8.2.0 "Harrier" %
8+
% %
9+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10+
11+
% ------------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION ------------%
12+
%
13+
KIND_VERIFICATION_SOLUTION= INVISCID_VORTEX
14+
SOLVER= EULER
15+
MATH_PROBLEM= DIRECT
16+
RESTART_SOL= NO
17+
18+
% ----------- COMPRESSIBLE AND INCOMPRESSIBLE FREE-STREAM DEFINITION ----------%
19+
%
20+
MACH_NUMBER= 0.5
21+
AOA= 45.0
22+
FREESTREAM_DENSITY= 1.0
23+
FREESTREAM_PRESSURE= 1.0
24+
FREESTREAM_TEMPERATURE= 1.0
25+
26+
% -------------- COMPRESSIBLE AND INCOMPRESSIBLE FLUID CONSTANTS --------------%
27+
%
28+
FLUID_MODEL= IDEAL_GAS
29+
GAMMA_VALUE= 1.4
30+
GAS_CONSTANT= 1.0
31+
32+
% ---------------------- REFERENCE VALUE DEFINITION ---------------------------%
33+
%
34+
REF_ORIGIN_MOMENT_X= 0.00
35+
REF_ORIGIN_MOMENT_Y= 0.00
36+
REF_ORIGIN_MOMENT_Z= 0.00
37+
REF_AREA= 1.0
38+
REF_DIMENSIONALIZATION= DIMENSIONAL
39+
40+
% ------------------------- UNSTEADY SIMULATION -------------------------------%
41+
%
42+
TIME_DOMAIN= YES
43+
TIME_MARCHING= TIME_STEPPING
44+
TIME_STEP= 2.0e-3
45+
MAX_TIME= 50.0
46+
47+
% -------------------- BOUNDARY CONDITION DEFINITION --------------------------%
48+
%
49+
MARKER_PERIODIC= ( PeriodicBottom, PeriodicTop, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, \
50+
PeriodicLeft, PeriodicRight, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0 )
51+
52+
% ------------- COMMON PARAMETERS TO DEFINE THE NUMERICAL METHOD --------------%
53+
%
54+
CFL_NUMBER= 0.2
55+
TIME_ITER= 50
56+
RK_ALPHA_COEFF= ( 0.666667, 0.666667, 1.0 )
57+
58+
% ------------------ FLOW NUMERICAL METHOD DEFINITION ----------------------%
59+
%
60+
CONV_NUM_METHOD_FLOW= ROE
61+
MUSCL_FLOW= YES
62+
SLOPE_LIMITER_FLOW= NONE
63+
TIME_DISCRE_FLOW= EULER_IMPLICIT
64+
65+
% --------------------------- CONVERGENCE PARAMETERS --------------------------%
66+
%
67+
CONV_RESIDUAL_MINVAL= -15
68+
CONV_STARTITER= 10
69+
CONV_CAUCHY_ELEMS= 100
70+
CONV_CAUCHY_EPS= 1E-6
71+
72+
% ------------------------- INPUT/OUTPUT INFORMATION --------------------------%
73+
%
74+
MESH_FILENAME= TriAdapt.su2
75+
MESH_FORMAT= SU2
76+
MESH_OUT_FILENAME= mesh_out.su2
77+
SOLUTION_FILENAME= solution_flow.dat
78+
SOLUTION_ADJ_FILENAME= solution_adj.dat
79+
TABULAR_FORMAT= CSV
80+
CONV_FILENAME= history
81+
RESTART_FILENAME= restart_flow.dat
82+
RESTART_ADJ_FILENAME= restart_adj.dat
83+
VOLUME_FILENAME= flow
84+
VOLUME_ADJ_FILENAME= adjoint
85+
GRAD_OBJFUNC_FILENAME= of_grad.dat
86+
SURFACE_FILENAME= surface_flow
87+
SURFACE_ADJ_FILENAME= surface_adjoint
88+
OUTPUT_WRT_FREQ= 50
89+
SCREEN_OUTPUT= (TIME_ITER, RMS_DENSITY, RMS_ENERGY, LIFT, DRAG)

TestCases/parallel_regression.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,15 @@ def main():
14791479
### Method of Manufactured Solutions (MMS) ###
14801480
##############################################
14811481

1482+
# FVM, compressible, euler (periodic isentropic vortex)
1483+
mms_fvm_vortex = TestCase('mms_fvm_vortex')
1484+
mms_fvm_vortex.cfg_dir = "mms/fvm_euler"
1485+
mms_fvm_vortex.cfg_file = "inv_mms_vortex.cfg"
1486+
mms_fvm_vortex.test_iter = 10
1487+
mms_fvm_vortex.test_vals = [-5.704300, -4.848072, 0.000000, 0.000000]
1488+
mms_fvm_vortex.unsteady = True
1489+
test_list.append(mms_fvm_vortex)
1490+
14821491
# FVM, compressible, laminar N-S
14831492
mms_fvm_ns = TestCase('mms_fvm_ns')
14841493
mms_fvm_ns.cfg_dir = "mms/fvm_navierstokes"

TestCases/serial_regression.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,15 @@ def main():
11291129
### Method of Manufactured Solutions (MMS) ###
11301130
##############################################
11311131

1132+
# FVM, compressible, euler (periodic isentropic vortex)
1133+
mms_fvm_vortex = TestCase('mms_fvm_vortex')
1134+
mms_fvm_vortex.cfg_dir = "mms/fvm_euler"
1135+
mms_fvm_vortex.cfg_file = "inv_mms_vortex.cfg"
1136+
mms_fvm_vortex.test_iter = 10
1137+
mms_fvm_vortex.test_vals = [-5.704300, -4.848072, 0.000000, 0.000000]
1138+
mms_fvm_vortex.unsteady = True
1139+
test_list.append(mms_fvm_vortex)
1140+
11321141
# FVM, compressible, laminar N-S
11331142
mms_fvm_ns = TestCase('mms_fvm_ns')
11341143
mms_fvm_ns.cfg_dir = "mms/fvm_navierstokes"

0 commit comments

Comments
 (0)