@@ -1109,6 +1109,227 @@ def chemistry_cases():
11091109
11101110 chemistry_cases ()
11111111
1112+ def direction_symmetry_tests ():
1113+ """3D tests with shock propagating in x and y directions.
1114+
1115+ Default 3D tests have the shock along z. These test x and y
1116+ code paths to catch direction-specific bugs in reconstruction,
1117+ Riemann solvers, and gradient calculations.
1118+ """
1119+ for direction in ['x' , 'y' ]:
1120+ others = [d for d in ['x' , 'y' , 'z' ] if d != direction ]
1121+ mods = {
1122+ 'm' : 24 , 'n' : 24 , 'p' : 24 ,
1123+ 'x_domain%beg' : 0.E+00 , 'x_domain%end' : 1.E+00 ,
1124+ 'y_domain%beg' : 0.E+00 , 'y_domain%end' : 1.E+00 ,
1125+ 'z_domain%beg' : 0.E+00 , 'z_domain%end' : 1.E+00 ,
1126+ 'bc_x%beg' : - 3 , 'bc_x%end' : - 3 ,
1127+ 'bc_y%beg' : - 3 , 'bc_y%end' : - 3 ,
1128+ 'bc_z%beg' : - 3 , 'bc_z%end' : - 3 ,
1129+ }
1130+
1131+ centroids = [0.05 , 0.45 , 0.9 ]
1132+ lengths = [0.1 , 0.7 , 0.2 ]
1133+
1134+ for patchID in range (1 , 4 ):
1135+ mods [f'patch_icpp({ patchID } )%geometry' ] = 9
1136+ mods [f'patch_icpp({ patchID } )%vel(1)' ] = 0.0
1137+ mods [f'patch_icpp({ patchID } )%vel(2)' ] = 0.0
1138+ mods [f'patch_icpp({ patchID } )%vel(3)' ] = 0.0
1139+ mods [f'patch_icpp({ patchID } )%{ direction } _centroid' ] = centroids [patchID - 1 ]
1140+ mods [f'patch_icpp({ patchID } )%length_{ direction } ' ] = lengths [patchID - 1 ]
1141+ for od in others :
1142+ mods [f'patch_icpp({ patchID } )%{ od } _centroid' ] = 0.5
1143+ mods [f'patch_icpp({ patchID } )%length_{ od } ' ] = 1
1144+
1145+ stack .push (f'3D Direction Symmetry -> Shock in { direction .upper ()} ' , mods )
1146+ cases .append (define_case_d (stack , '' , {}))
1147+ stack .pop ()
1148+
1149+ direction_symmetry_tests ()
1150+
1151+ def mpi_consistency_tests ():
1152+ """ppn=2 tests for physics sensitive to MPI decomposition.
1153+
1154+ Exercises bubble dynamics, viscous flows, and hypoelasticity
1155+ with 2 MPI ranks to catch broadcast/reduction bugs.
1156+ """
1157+ base_3d = {
1158+ 'm' : 29 , 'n' : 29 , 'p' : 49 ,
1159+ 'x_domain%beg' : 0.E+00 , 'x_domain%end' : 1.E+00 ,
1160+ 'y_domain%beg' : 0.E+00 , 'y_domain%end' : 1.E+00 ,
1161+ 'z_domain%beg' : 0.E+00 , 'z_domain%end' : 1.E+00 ,
1162+ 'bc_x%beg' : - 3 , 'bc_x%end' : - 3 ,
1163+ 'bc_y%beg' : - 3 , 'bc_y%end' : - 3 ,
1164+ 'bc_z%beg' : - 3 , 'bc_z%end' : - 3 ,
1165+ }
1166+
1167+ for patchID in range (1 , 4 ):
1168+ base_3d [f'patch_icpp({ patchID } )%geometry' ] = 9
1169+ base_3d [f'patch_icpp({ patchID } )%vel(1)' ] = 0.0
1170+ base_3d [f'patch_icpp({ patchID } )%vel(2)' ] = 0.0
1171+ base_3d [f'patch_icpp({ patchID } )%vel(3)' ] = 0.0
1172+ base_3d [f'patch_icpp({ patchID } )%x_centroid' ] = 0.5
1173+ base_3d [f'patch_icpp({ patchID } )%length_x' ] = 1
1174+ base_3d [f'patch_icpp({ patchID } )%y_centroid' ] = 0.5
1175+ base_3d [f'patch_icpp({ patchID } )%length_y' ] = 1
1176+ base_3d .update ({
1177+ 'patch_icpp(1)%z_centroid' : 0.05 , 'patch_icpp(1)%length_z' : 0.1 ,
1178+ 'patch_icpp(2)%z_centroid' : 0.45 , 'patch_icpp(2)%length_z' : 0.7 ,
1179+ 'patch_icpp(3)%z_centroid' : 0.9 , 'patch_icpp(3)%length_z' : 0.2 ,
1180+ })
1181+
1182+ # Bubbles with 2 MPI ranks
1183+ stack .push ('MPI Consistency -> 3D -> Bubbles' , {** base_3d ,
1184+ 'dt' : 1e-06 ,
1185+ 'bubbles_euler' : 'T' , 'nb' : 1 , 'polytropic' : 'T' , 'bubble_model' : 2 ,
1186+ 'fluid_pp(1)%gamma' : 0.16 , 'fluid_pp(1)%pi_inf' : 3515.0 ,
1187+ 'bub_pp%R0ref' : 1.0 , 'bub_pp%p0ref' : 1.0 , 'bub_pp%rho0ref' : 1.0 , 'bub_pp%T0ref' : 1.0 ,
1188+ 'bub_pp%ss' : 0.07179866765358993 , 'bub_pp%pv' : 0.02308216136195411 ,
1189+ 'bub_pp%vd' : 0.2404125083932959 ,
1190+ 'bub_pp%mu_l' : 0.009954269975623244 , 'bub_pp%mu_v' : 8.758168074360729e-05 ,
1191+ 'bub_pp%mu_g' : 0.00017881922111898042 , 'bub_pp%gam_v' : 1.33 , 'bub_pp%gam_g' : 1.4 ,
1192+ 'bub_pp%M_v' : 18.02 , 'bub_pp%M_g' : 28.97 , 'bub_pp%k_v' : 0.5583395141263873 ,
1193+ 'bub_pp%k_g' : 0.7346421281308791 , 'bub_pp%R_v' : 1334.8378710170155 ,
1194+ 'bub_pp%R_g' : 830.2995663005393 ,
1195+ 'patch_icpp(1)%alpha_rho(1)' : 0.96 , 'patch_icpp(1)%alpha(1)' : 4e-02 ,
1196+ 'patch_icpp(2)%alpha_rho(1)' : 0.96 , 'patch_icpp(2)%alpha(1)' : 4e-02 ,
1197+ 'patch_icpp(3)%alpha_rho(1)' : 0.96 , 'patch_icpp(3)%alpha(1)' : 4e-02 ,
1198+ 'patch_icpp(1)%pres' : 1.0 , 'patch_icpp(2)%pres' : 1.0 , 'patch_icpp(3)%pres' : 1.0 ,
1199+ })
1200+ cases .append (define_case_d (stack , '' , {}, ppn = 2 ))
1201+ stack .pop ()
1202+
1203+ # Viscous with 2 MPI ranks
1204+ stack .push ('MPI Consistency -> 3D -> Viscous' , {** base_3d ,
1205+ 'dt' : 1e-11 ,
1206+ 'fluid_pp(1)%Re(1)' : 0.0001 , 'viscous' : 'T' ,
1207+ 'patch_icpp(1)%vel(1)' : 1.0 ,
1208+ 'patch_icpp(2)%vel(1)' : 1.0 ,
1209+ 'patch_icpp(3)%vel(1)' : 1.0 ,
1210+ })
1211+ cases .append (define_case_d (stack , '' , {}, ppn = 2 ))
1212+ stack .pop ()
1213+
1214+ # Hypoelasticity with 2 MPI ranks
1215+ stack .push ('MPI Consistency -> 3D -> Hypoelasticity' , {** base_3d ,
1216+ 'hypoelasticity' : 'T' , 'riemann_solver' : 1 , 'fd_order' : 4 ,
1217+ 'fluid_pp(1)%gamma' : 0.3 , 'fluid_pp(1)%pi_inf' : 7.8E+05 ,
1218+ 'fluid_pp(1)%G' : 1.E+05 ,
1219+ 'patch_icpp(1)%pres' : 1.E+06 , 'patch_icpp(1)%alpha_rho(1)' : 1000.E+00 ,
1220+ 'patch_icpp(2)%pres' : 1.E+05 , 'patch_icpp(2)%alpha_rho(1)' : 1000.E+00 ,
1221+ 'patch_icpp(3)%pres' : 5.E+05 , 'patch_icpp(3)%alpha_rho(1)' : 1000.E+00 ,
1222+ 'patch_icpp(1)%tau_e(1)' : 0.E+00 , 'patch_icpp(2)%tau_e(1)' : 0.E+00 ,
1223+ 'patch_icpp(3)%tau_e(1)' : 0.E+00 ,
1224+ 'patch_icpp(1)%tau_e(2)' : 0.E+00 , 'patch_icpp(1)%tau_e(3)' : 0.E+00 ,
1225+ 'patch_icpp(2)%tau_e(2)' : 0.E+00 , 'patch_icpp(2)%tau_e(3)' : 0.E+00 ,
1226+ 'patch_icpp(3)%tau_e(2)' : 0.E+00 , 'patch_icpp(3)%tau_e(3)' : 0.E+00 ,
1227+ 'patch_icpp(1)%tau_e(4)' : 0.E+00 , 'patch_icpp(1)%tau_e(5)' : 0.E+00 ,
1228+ 'patch_icpp(1)%tau_e(6)' : 0.E+00 ,
1229+ 'patch_icpp(2)%tau_e(4)' : 0.E+00 , 'patch_icpp(2)%tau_e(5)' : 0.E+00 ,
1230+ 'patch_icpp(2)%tau_e(6)' : 0.E+00 ,
1231+ 'patch_icpp(3)%tau_e(4)' : 0.E+00 , 'patch_icpp(3)%tau_e(5)' : 0.E+00 ,
1232+ 'patch_icpp(3)%tau_e(6)' : 0.E+00 ,
1233+ })
1234+ cases .append (define_case_d (stack , '' , {}, ppn = 2 ))
1235+ stack .pop ()
1236+
1237+ mpi_consistency_tests ()
1238+
1239+ def restart_roundtrip_tests ():
1240+ """Tests that verify save-restart roundtrip fidelity.
1241+
1242+ Each test runs a straight simulation, then a restart from the
1243+ midpoint. The restarted output is compared against the straight
1244+ run output to verify restart I/O doesn't introduce drift.
1245+ """
1246+ # 1D restart
1247+ stack .push ('Restart Roundtrip -> 1D' , {
1248+ 'm' : 299 , 'n' : 0 , 'p' : 0 ,
1249+ 'x_domain%beg' : 0.E+00 , 'x_domain%end' : 1.E+00 ,
1250+ 'bc_x%beg' : - 3 , 'bc_x%end' : - 3 ,
1251+ 'patch_icpp(1)%geometry' : 1 , 'patch_icpp(2)%geometry' : 1 ,
1252+ 'patch_icpp(3)%geometry' : 1 ,
1253+ 'patch_icpp(1)%x_centroid' : 0.05 , 'patch_icpp(1)%length_x' : 0.1 ,
1254+ 'patch_icpp(2)%x_centroid' : 0.45 , 'patch_icpp(2)%length_x' : 0.7 ,
1255+ 'patch_icpp(3)%x_centroid' : 0.9 , 'patch_icpp(3)%length_x' : 0.2 ,
1256+ 'patch_icpp(1)%vel(1)' : 0.0 , 'patch_icpp(2)%vel(1)' : 0.0 ,
1257+ 'patch_icpp(3)%vel(1)' : 0.0 ,
1258+ })
1259+ cases .append (define_case_d (stack , '' , {}, restart_check = True ))
1260+ stack .pop ()
1261+
1262+ # 3D restart
1263+ base_3d = {
1264+ 'm' : 24 , 'n' : 24 , 'p' : 24 ,
1265+ 'x_domain%beg' : 0.E+00 , 'x_domain%end' : 1.E+00 ,
1266+ 'y_domain%beg' : 0.E+00 , 'y_domain%end' : 1.E+00 ,
1267+ 'z_domain%beg' : 0.E+00 , 'z_domain%end' : 1.E+00 ,
1268+ 'bc_x%beg' : - 3 , 'bc_x%end' : - 3 ,
1269+ 'bc_y%beg' : - 3 , 'bc_y%end' : - 3 ,
1270+ 'bc_z%beg' : - 3 , 'bc_z%end' : - 3 ,
1271+ }
1272+ for patchID in range (1 , 4 ):
1273+ base_3d [f'patch_icpp({ patchID } )%geometry' ] = 9
1274+ base_3d [f'patch_icpp({ patchID } )%vel(1)' ] = 0.0
1275+ base_3d [f'patch_icpp({ patchID } )%vel(2)' ] = 0.0
1276+ base_3d [f'patch_icpp({ patchID } )%vel(3)' ] = 0.0
1277+ base_3d [f'patch_icpp({ patchID } )%x_centroid' ] = 0.5
1278+ base_3d [f'patch_icpp({ patchID } )%length_x' ] = 1
1279+ base_3d [f'patch_icpp({ patchID } )%y_centroid' ] = 0.5
1280+ base_3d [f'patch_icpp({ patchID } )%length_y' ] = 1
1281+ base_3d .update ({
1282+ 'patch_icpp(1)%z_centroid' : 0.05 , 'patch_icpp(1)%length_z' : 0.1 ,
1283+ 'patch_icpp(2)%z_centroid' : 0.45 , 'patch_icpp(2)%length_z' : 0.7 ,
1284+ 'patch_icpp(3)%z_centroid' : 0.9 , 'patch_icpp(3)%length_z' : 0.2 ,
1285+ })
1286+ stack .push ('Restart Roundtrip -> 3D' , base_3d )
1287+ cases .append (define_case_d (stack , '' , {}, restart_check = True ))
1288+ stack .pop ()
1289+
1290+ restart_roundtrip_tests ()
1291+
1292+ def kernel_golden_tests ():
1293+ """Focused golden-value tests for specific physics kernels.
1294+
1295+ Polydisperse bubbles: exercises bubble array indexing with
1296+ multiple bubble sizes and weight distributions.
1297+ """
1298+ # Polydisperse bubbles (nb=3 with poly_sigma distribution)
1299+ stack .push ('Kernel -> 1D -> Polydisperse Bubbles' , {
1300+ 'm' : 299 , 'n' : 0 , 'p' : 0 ,
1301+ 'x_domain%beg' : 0.E+00 , 'x_domain%end' : 1.E+00 ,
1302+ 'bc_x%beg' : - 3 , 'bc_x%end' : - 3 ,
1303+ 'patch_icpp(1)%geometry' : 1 , 'patch_icpp(2)%geometry' : 1 ,
1304+ 'patch_icpp(3)%geometry' : 1 ,
1305+ 'patch_icpp(1)%x_centroid' : 0.05 , 'patch_icpp(1)%length_x' : 0.1 ,
1306+ 'patch_icpp(2)%x_centroid' : 0.45 , 'patch_icpp(2)%length_x' : 0.7 ,
1307+ 'patch_icpp(3)%x_centroid' : 0.9 , 'patch_icpp(3)%length_x' : 0.2 ,
1308+ 'patch_icpp(1)%vel(1)' : 0.0 , 'patch_icpp(2)%vel(1)' : 0.0 ,
1309+ 'patch_icpp(3)%vel(1)' : 0.0 ,
1310+ 'dt' : 1e-07 ,
1311+ 'bubbles_euler' : 'T' , 'nb' : 3 , 'polydisperse' : 'T' , 'poly_sigma' : 0.3 ,
1312+ 'polytropic' : 'T' , 'bubble_model' : 2 ,
1313+ 'fluid_pp(1)%gamma' : 0.16 , 'fluid_pp(1)%pi_inf' : 3515.0 ,
1314+ 'bub_pp%R0ref' : 1.0 , 'bub_pp%p0ref' : 1.0 ,
1315+ 'bub_pp%rho0ref' : 1.0 , 'bub_pp%T0ref' : 1.0 ,
1316+ 'bub_pp%ss' : 0.07179866765358993 , 'bub_pp%pv' : 0.02308216136195411 ,
1317+ 'bub_pp%vd' : 0.2404125083932959 ,
1318+ 'bub_pp%mu_l' : 0.009954269975623244 , 'bub_pp%mu_v' : 8.758168074360729e-05 ,
1319+ 'bub_pp%mu_g' : 0.00017881922111898042 , 'bub_pp%gam_v' : 1.33 , 'bub_pp%gam_g' : 1.4 ,
1320+ 'bub_pp%M_v' : 18.02 , 'bub_pp%M_g' : 28.97 , 'bub_pp%k_v' : 0.5583395141263873 ,
1321+ 'bub_pp%k_g' : 0.7346421281308791 , 'bub_pp%R_v' : 1334.8378710170155 ,
1322+ 'bub_pp%R_g' : 830.2995663005393 ,
1323+ 'patch_icpp(1)%alpha_rho(1)' : 0.96 , 'patch_icpp(1)%alpha(1)' : 4e-02 ,
1324+ 'patch_icpp(2)%alpha_rho(1)' : 0.96 , 'patch_icpp(2)%alpha(1)' : 4e-02 ,
1325+ 'patch_icpp(3)%alpha_rho(1)' : 0.96 , 'patch_icpp(3)%alpha(1)' : 4e-02 ,
1326+ 'patch_icpp(1)%pres' : 1.0 , 'patch_icpp(2)%pres' : 1.0 , 'patch_icpp(3)%pres' : 1.0 ,
1327+ })
1328+ cases .append (define_case_d (stack , '' , {}))
1329+ stack .pop ()
1330+
1331+ kernel_golden_tests ()
1332+
11121333 # Sanity Check 1
11131334 if stack .size () != 0 :
11141335 raise common .MFCException ("list_cases: stack isn't fully pop'ed" )
0 commit comments