@@ -1016,8 +1016,8 @@ Create combined multi-panel figure with geometry, polar data, distributions, and
10161016"""
10171017function VortexStepMethod. plot_combined_analysis (
10181018 solver,
1019- body_aero:: BodyAerodynamics ,
1020- results:: Dict ;
1019+ body_aero,
1020+ results;
10211021 solver_label= " VSM" ,
10221022 angle_range= range (0 , 20 , length= 20 ),
10231023 angle_type= " angle_of_attack" ,
@@ -1035,6 +1035,12 @@ function VortexStepMethod.plot_combined_analysis(
10351035 is_save= false ,
10361036 angle_of_attack_for_spanwise_distribution= 5.0 ,
10371037)
1038+ # Normalize inputs to arrays for consistent handling
1039+ solvers = solver isa Vector ? solver : [solver]
1040+ body_aeros = body_aero isa Vector ? body_aero : [body_aero]
1041+ results_list = results isa Vector ? results : [results]
1042+ labels = solver_label isa Vector ? solver_label : [solver_label]
1043+
10381044 # Auto-detect screen size and use 80% of it
10391045 fig = try
10401046 screen_size = Makie. primary_resolution ()
@@ -1047,17 +1053,24 @@ function VortexStepMethod.plot_combined_analysis(
10471053 end
10481054 Label (fig[0 , :], title, fontsize= 20 , font= :bold )
10491055
1050- panels = body_aero. panels
1051- va = isa (body_aero. va, Tuple) ? body_aero. va[1 ] : body_aero. va
1052- # Choose results used for spanwise plots (optionally recompute at a requested AoA)
1053- results_spanwise = results
1056+ # Use first body_aero for geometry and polar data display
1057+ first_body = body_aeros[1 ]
1058+ panels = first_body. panels
1059+ va = isa (first_body. va, Tuple) ? first_body. va[1 ] : first_body. va
1060+
1061+ # Compute spanwise results for each solver
1062+ results_spanwise_list = copy (results_list)
10541063 if ! isnothing (angle_of_attack_for_spanwise_distribution)
10551064 α_span = deg2rad (angle_of_attack_for_spanwise_distribution)
10561065 β_span = deg2rad (side_slip)
1057- va_old = copy (body_aero. va)
1058- set_va! (body_aero, [cos (α_span) * cos (β_span), sin (β_span), sin (α_span)] * v_a)
1059- results_spanwise = solve (solver, body_aero, solver. sol. gamma_distribution)
1060- set_va! (body_aero, va_old)
1066+ for (i, (s, ba)) in enumerate (zip (solvers, body_aeros))
1067+ va_old = copy (ba. va)
1068+ set_va! (ba, [cos (α_span) * cos (β_span), sin (β_span),
1069+ sin (α_span)] * v_a)
1070+ results_spanwise_list[i] = solve (s, ba,
1071+ s. sol. gamma_distribution)
1072+ set_va! (ba, va_old)
1073+ end
10611074 end
10621075
10631076 # [1,1] Wing Geometry
@@ -1106,14 +1119,14 @@ function VortexStepMethod.plot_combined_analysis(
11061119 axislegend (ax_geo; position= :lt )
11071120
11081121 # [1,2] Polar Data Surfaces or Curves
1109- if body_aero . panels[1 ]. aero_model == POLAR_MATRICES
1122+ if first_body . panels[1 ]. aero_model == POLAR_MATRICES
11101123 alphas = collect (deg2rad .(- 5 : 0.3 : 40 ))
11111124 delta_tes = collect (deg2rad .(- 5 : 0.3 : 40 ))
11121125
11131126 interp_data = [
1114- (body_aero . panels[1 ]. cl_interp, " Cl" ),
1115- (body_aero . panels[1 ]. cd_interp, " Cd" ),
1116- (body_aero . panels[1 ]. cm_interp, " Cm" )
1127+ (first_body . panels[1 ]. cl_interp, " Cl" ),
1128+ (first_body . panels[1 ]. cd_interp, " Cd" ),
1129+ (first_body . panels[1 ]. cm_interp, " Cm" )
11171130 ]
11181131
11191132 for (idx, (interp, label)) in enumerate (interp_data)
@@ -1130,7 +1143,7 @@ function VortexStepMethod.plot_combined_analysis(
11301143 wireframe! (ax, delta_tes, alphas, interp_matrix;
11311144 color= :blue , linewidth= 0.5 , transparency= true )
11321145 end
1133- elseif body_aero . panels[1 ]. aero_model == POLAR_VECTORS
1146+ elseif first_body . panels[1 ]. aero_model == POLAR_VECTORS
11341147 alphas_deg = collect (- 5 : 0.5 : 40 )
11351148 alphas = deg2rad .(alphas_deg)
11361149
@@ -1147,17 +1160,17 @@ function VortexStepMethod.plot_combined_analysis(
11471160 xlabel= " α [°]" ,
11481161 ylabel= " Cm" )
11491162
1150- cl_vals = [body_aero . panels[1 ]. cl_interp (a) for a in alphas]
1151- cd_vals = [body_aero . panels[1 ]. cd_interp (a) for a in alphas]
1152- cm_vals = [body_aero . panels[1 ]. cm_interp (a) for a in alphas]
1163+ cl_vals = [first_body . panels[1 ]. cl_interp (a) for a in alphas]
1164+ cd_vals = [first_body . panels[1 ]. cd_interp (a) for a in alphas]
1165+ cm_vals = [first_body . panels[1 ]. cm_interp (a) for a in alphas]
11531166
11541167 lines! (ax_cl_curve, alphas_deg, cl_vals; color= :blue , linewidth= 2 )
11551168 lines! (ax_cd_curve, alphas_deg, cd_vals; color= :red , linewidth= 2 )
11561169 lines! (ax_cm_curve, alphas_deg, cm_vals; color= :green , linewidth= 2 )
11571170 end
11581171
11591172 # [2,1] Spanwise Distributions (3×3 grid)
1160- y_coords = [panel. aero_center[2 ] for panel in body_aero . panels]
1173+ y_coords = [panel. aero_center[2 ] for panel in first_body . panels]
11611174
11621175 aoa_span = round (angle_of_attack_for_spanwise_distribution, digits= 1 )
11631176
@@ -1181,62 +1194,66 @@ function VortexStepMethod.plot_combined_analysis(
11811194 ax_fz = Axis (fig[2 , 1 ][3 , 3 ], title= " Force z (α=$aoa_span )" ,
11821195 xlabel= " Spanwise position y[m]" , ylabel= " Fz" )
11831196
1184- cl_val = round (results_spanwise[" cl" ], digits= 2 )
1185- lines! (ax_cl, Vector (y_coords), Vector (results_spanwise[" cl_distribution" ]),
1186- label= " $solver_label CL: $cl_val " )
1187- axislegend (ax_cl, position= :lt )
1188-
1189- cd_val = round (results_spanwise[" cd" ], digits= 2 )
1190- lines! (ax_cd, Vector (y_coords), Vector (results_spanwise[" cd_distribution" ]),
1191- label= " $solver_label CD: $cd_val " )
1192- axislegend (ax_cd, position= :lt )
1193-
1194- lines! (ax_gamma, Vector (y_coords), Vector (results_spanwise[" gamma_distribution" ]),
1195- label= solver_label)
1196- axislegend (ax_gamma, position= :lt )
1197-
1198- lines! (ax_alpha_geo, Vector (y_coords), rad2deg .(Vector (results_spanwise[" alpha_geometric" ])),
1199- label= solver_label)
1200- axislegend (ax_alpha_geo, position= :lt )
1201-
1202- lines! (ax_alpha_ac, Vector (y_coords), rad2deg .(Vector (results_spanwise[" alpha_at_ac" ])),
1203- label= solver_label)
1204- axislegend (ax_alpha_ac, position= :lt )
1197+ colors = Makie. wong_colors ()
1198+ for (si, (lbl, rs)) in enumerate (zip (labels, results_spanwise_list))
1199+ color = colors[mod1 (si, length (colors))]
1200+ y_si = [panel. aero_center[2 ] for panel in body_aeros[si]. panels]
1201+
1202+ cl_val = round (rs[" cl" ], digits= 2 )
1203+ lines! (ax_cl, Vector (y_si), Vector (rs[" cl_distribution" ]);
1204+ label= " $lbl CL: $cl_val " , color)
1205+
1206+ cd_val = round (rs[" cd" ], digits= 2 )
1207+ lines! (ax_cd, Vector (y_si), Vector (rs[" cd_distribution" ]);
1208+ label= " $lbl CD: $cd_val " , color)
1209+
1210+ lines! (ax_gamma, Vector (y_si),
1211+ Vector (rs[" gamma_distribution" ]); label= lbl, color)
1212+
1213+ lines! (ax_alpha_geo, Vector (y_si),
1214+ rad2deg .(Vector (rs[" alpha_geometric" ])); label= lbl, color)
1215+
1216+ lines! (ax_alpha_ac, Vector (y_si),
1217+ rad2deg .(Vector (rs[" alpha_at_ac" ])); label= lbl, color)
1218+
1219+ lines! (ax_alpha_unc, Vector (y_si),
1220+ rad2deg .(Vector (rs[" alpha_uncorrected" ]));
1221+ label= lbl, color)
1222+
1223+ force_axes = [ax_fx, ax_fy, ax_fz]
1224+ components = [" x" , " y" , " z" ]
1225+ for (idx, (ax, comp)) in enumerate (zip (force_axes, components))
1226+ forces = rs[" F_distribution" ][idx, :]
1227+ total_force = round (rs[" F$comp " ], digits= 2 )
1228+ lines! (ax, Vector (y_si), Vector (forces);
1229+ label= " $lbl ΣF$comp : $total_force N" , color)
1230+ end
1231+ end
12051232
1206- lines! (ax_alpha_unc, Vector (y_coords),
1207- rad2deg .(Vector (results_spanwise[" alpha_uncorrected" ])), label= solver_label)
1208- axislegend (ax_alpha_unc, position= :lt )
1233+ for ax in [ax_cl, ax_cd, ax_gamma, ax_alpha_geo, ax_alpha_ac,
1234+ ax_alpha_unc, ax_fx, ax_fy, ax_fz]
1235+ axislegend (ax, position= :lt )
1236+ end
12091237
12101238 # force y-limits
12111239 ylims! (ax_alpha_geo, - 0.25 * aoa_span, 1.1 * aoa_span)
12121240
1213-
1214-
1215- force_axes = [ax_fx, ax_fy, ax_fz]
1216- components = [" x" , " y" , " z" ]
1217- for (idx, (ax, comp)) in enumerate (zip (force_axes, components))
1218- forces = results_spanwise[" F_distribution" ][idx, :]
1219- total_force = round (results_spanwise[" F$comp " ], digits= 2 )
1220- lines! (ax, Vector (y_coords), Vector (forces),
1221- label= " $solver_label ΣF$comp : $total_force N" )
1222- axislegend (ax, position= :lt )
1223- end
1224-
12251241 # [2,2] Polars (2×2 grid)
1226- polar_solver = compute_polar_with_cmy (
1227- solver,
1228- body_aero,
1229- angle_range;
1230- angle_type= angle_type,
1231- angle_of_attack= angle_of_attack,
1232- side_slip= side_slip,
1233- v_a= v_a
1234- )
1235-
1236- label_with_re = " $solver_label Re = $(round (Int64, first (polar_solver. rey)* 1e-5 )) e5"
1242+ polar_series = Tuple[]
1243+ for (si, (s, ba, lbl)) in enumerate (zip (solvers, body_aeros, labels))
1244+ polar_solver = compute_polar_with_cmy (
1245+ s, ba, angle_range;
1246+ angle_type= angle_type,
1247+ angle_of_attack= angle_of_attack,
1248+ side_slip= side_slip,
1249+ v_a= v_a
1250+ )
1251+ label_re = " $lbl Re = $(round (Int64,
1252+ first (polar_solver. rey) * 1e-5 )) e5"
1253+ push! (polar_series, (polar_solver, label_re))
1254+ end
12371255
12381256 # Load literature data (if any)
1239- polar_series = [(polar_solver, label_with_re)]
12401257 if ! isempty (literature_path_list)
12411258 for path in literature_path_list
12421259 data = readdlm (path, ' ,' )
@@ -1282,7 +1299,6 @@ function VortexStepMethod.plot_combined_analysis(
12821299 ax_polar = Axis (fig[2 , 2 ][2 , 2 ], title= " CL vs CD" ,
12831300 xlabel= " CD" , ylabel= " CL" )
12841301
1285- colors = Makie. wong_colors ()
12861302 for (idx, (pd, lbl)) in enumerate (polar_series)
12871303 color = colors[mod1 (idx, length (colors))]
12881304 marker = idx == 1 ? :star5 : :circle
0 commit comments