From e971c74e9eb263f8a565d2800251b828e8bef80f Mon Sep 17 00:00:00 2001 From: 1-Bort-1 <323661610+1-Bort-1@users.noreply.github.com> Date: Wed, 16 Sep 2026 21:03:09 +0200 Subject: [PATCH] Give untyped empty containers their element type `vertices = []`, `plots = []`, `filaments_plot = []` and the like become `Vector{Float64}[]`, `Makie.AbstractPlot[]`, `Tuple{...}[]`, in src, the Makie extension, tests and the stall example. `plot!(ax, body)` drawn as flat panels now appends each panel's plots, so every branch returns one flat `Vector{Makie.AbstractPlot}`. Refs #147 Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 3 +++ examples/stall_model.jl | 14 +++++------- ext/VortexStepMethodMakieExt.jl | 13 +++++------ src/obj_adapter/obj_geometry.jl | 4 ++-- src/panel.jl | 2 +- src/settings.jl | 2 +- test/panel/test_panel.jl | 11 ++++++++++ test/plotting/test_plotting.jl | 21 ++++++++++-------- test/ram_geometry/test_kite_geometry.jl | 10 ++++----- test/thesis_oriol_cayon.jl | 22 +++++++++---------- .../test_yaml_wing_deformation.jl | 10 +++------ 11 files changed, 60 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 783899e8..e00d58bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Changed - Requires Julia 1.12 or 1.13; 1.10 and 1.11 keep resolving v5.1.1. +- The Makie `plot!` methods for a `Panel` or a `BodyAerodynamics` return a + `Vector{Makie.AbstractPlot}` instead of a `Vector{Any}`; for a `BodyAerodynamics` + drawn as flat panels it is one flat list rather than a list per panel. ## VortexStepMethod v5.1.1 2026-09-12 diff --git a/examples/stall_model.jl b/examples/stall_model.jl index 2e27641f..1b675c3c 100644 --- a/examples/stall_model.jl +++ b/examples/stall_model.jl @@ -32,19 +32,15 @@ csv_file_path = joinpath( ) df = CSV.read(csv_file_path, DataFrame) -rib_list = [] -for row in eachrow(df) - LE = [row.LE_x, row.LE_y, row.LE_z] - TE = [row.TE_x, row.TE_y, row.TE_z] - push!(rib_list, (LE, TE, LEI_AIRFOIL_BREUKELS, - lei_poly_coeffs(row.d_tube, row.camber))) -end # Create wing geometry # n_unrefined_sections will be automatically set to the number of ribs (18 sections) CAD_wing = Wing(n_panels; spanwise_distribution) -for rib in rib_list - add_section!(CAD_wing, rib[1], rib[2], rib[3], rib[4]) +for row in eachrow(df) + LE = [row.LE_x, row.LE_y, row.LE_z] + TE = [row.TE_x, row.TE_y, row.TE_z] + add_section!(CAD_wing, LE, TE, LEI_AIRFOIL_BREUKELS, + lei_poly_coeffs(row.d_tube, row.camber)) end refine!(CAD_wing) body_aero = BodyAerodynamics([CAD_wing]) diff --git a/ext/VortexStepMethodMakieExt.jl b/ext/VortexStepMethodMakieExt.jl index 5f025b3b..01cefdaf 100644 --- a/ext/VortexStepMethodMakieExt.jl +++ b/ext/VortexStepMethodMakieExt.jl @@ -117,7 +117,7 @@ If `use_observables=true`, creates observables for dynamic updates. """ function Makie.plot!(ax, panel::VortexStepMethod.Panel; color=(:red, 0.2), R_b_w=nothing, T_b_w=nothing, use_observables=false, border_linewidth=1.5, transparency=true, kwargs...) - plots = [] + plots = Makie.AbstractPlot[] points = panel_plate_geometry(panel; R_b_w, T_b_w) if use_observables @@ -253,7 +253,7 @@ function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0 use_observables=false, airfoils=false, airfoil_color=:deepskyblue, airfoil_opacity=0.2, rib_color=:black, border_linewidth=1.5, transparency=true, kwargs...) - plots = [] + plots = Makie.AbstractPlot[] if airfoils vertices, faces, ribs = airfoil_skin_geometry(body; R_b_w, T_b_w) @@ -316,9 +316,8 @@ function Makie.plot!(ax, body::VortexStepMethod.BodyAerodynamics; color=(:red, 0 else # Static plotting (original behavior) for panel in body.panels - p = Makie.plot!(ax, panel; color, R_b_w, T_b_w, use_observables=false, - border_linewidth, transparency, kwargs...) - push!(plots, p) + append!(plots, Makie.plot!(ax, panel; color, R_b_w, T_b_w, + use_observables=false, border_linewidth, transparency, kwargs...)) end end @@ -931,8 +930,8 @@ function VortexStepMethod.plot_polars( main_title = replace(title, " " => "_") # Generate polar data - polar_data_list = [] - cm_data_list = [] + polar_data_list = Vector{Array{Float64}}[] + cm_data_list = NamedTuple{(:cmx, :cmy, :cmz), NTuple{3, Vector{Float64}}}[] labels_with_re = copy(label_list) for (i, (solver, body_aero)) in enumerate(zip(solver_list, body_aero_list)) result = VortexStepMethod.generate_polar_data( diff --git a/src/obj_adapter/obj_geometry.jl b/src/obj_adapter/obj_geometry.jl index 0a5ac73a..8697ad85 100644 --- a/src/obj_adapter/obj_geometry.jl +++ b/src/obj_adapter/obj_geometry.jl @@ -12,8 +12,8 @@ Read vertices and faces from an OBJ file. - faces: Vector of triangle vertex indices """ function read_faces(filename) - vertices = [] - faces = [] + vertices = Vector{Float64}[] + faces = Vector{Int64}[] open(filename) do file for line in eachline(file) diff --git a/src/panel.jl b/src/panel.jl index 8ddcd826..175a2a5d 100644 --- a/src/panel.jl +++ b/src/panel.jl @@ -600,7 +600,7 @@ Calculate filaments for plotting with their positions and colors. - Color string """ function calculate_filaments_for_plotting(panel::Panel) - filaments_plot = [] + filaments_plot = Tuple{Vector{Float64}, Vector{Float64}, String}[] for (i, filament) in enumerate(panel.filaments) x1 = filament.x1 diff --git a/src/settings.jl b/src/settings.jl index d1ae6ef7..a5aade8c 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -225,7 +225,7 @@ wing = Wing(settings) """ @Base.kwdef mutable struct VSMSettings condition::ConditionSettings = ConditionSettings() - wings::Vector{WingSettings} = [] + wings::Vector{WingSettings} = WingSettings[] solver_settings::SolverSettings = SolverSettings() end diff --git a/test/panel/test_panel.jl b/test/panel/test_panel.jl index eaeb6f8a..f6381c18 100644 --- a/test/panel/test_panel.jl +++ b/test/panel/test_panel.jl @@ -95,6 +95,17 @@ end @test isapprox(panel.y_airf, [0.0, 1.0, 0.0]) end + @testset "Filaments for plotting have a concrete element type" begin + section1 = Section([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) + section2 = Section([0.0, 10.0, 0.0], [1.0, 10.0, 0.0], INVISCID) + panel = create_panel(section1, section2) + panel.va = [10.0, 0.0, 0.0] + + filaments = VortexStepMethod.calculate_filaments_for_plotting(panel) + @test filaments isa Vector{Tuple{Vector{Float64}, Vector{Float64}, String}} + @test length(filaments) == length(panel.filaments) + end + @testset "Velocity Calculations" begin section1 = Section([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], INVISCID) section2 = Section([0.0, 10.0, 0.0], [1.0, 10.0, 0.0], INVISCID) diff --git a/test/plotting/test_plotting.jl b/test/plotting/test_plotting.jl index 2d6e1607..5a0476b7 100644 --- a/test/plotting/test_plotting.jl +++ b/test/plotting/test_plotting.jl @@ -284,8 +284,8 @@ end write(io_no_cs, "aoa,cl,cd\n0.0,0.10,0.010\n5.0,0.20,0.020\n") end fig_lit_no_cs = plot_polars( - Any[], - Any[], + Solver[], + BodyAerodynamics[], ["Literature no CS"]; literature_path_list=[lit_no_cs_path], is_save=false, @@ -299,8 +299,8 @@ end write(io_bad, "alpha,cl\n0.0,0.10\n5.0,0.20\n") end @test_throws ArgumentError plot_polars( - Any[], - Any[], + Solver[], + BodyAerodynamics[], ["Literature bad"]; literature_path_list=[lit_bad_path], is_save=false, @@ -316,8 +316,8 @@ end "5.0,0.5,0.02,0.01,0.004,0.005,0.006\n") end fig_moments = plot_polars( - Any[], - Any[], + Solver[], + BodyAerodynamics[], ["Literature with moments"]; literature_path_list=[cm_lit_path], show_moments=true, @@ -334,8 +334,8 @@ end "0.0,0.1,0.01\n5.0,0.5,0.02\n") end fig_no_moments = plot_polars( - Any[], - Any[], + Solver[], + BodyAerodynamics[], ["Literature no moments"]; literature_path_list=[no_cm_path], show_moments=false, @@ -453,6 +453,7 @@ end ax = Axis3(fig[1, 1]) plots = Makie.plot!(ax, body_aero; airfoils=true) @test !isempty(plots) + @test plots isa Vector{Makie.AbstractPlot} # Observable airfoil-skin plot registers the body for pose updates. fig_obs = Figure() @@ -501,7 +502,9 @@ end # border_linewidth flows through the standard (non-airfoil) panel plot. fig_lw = Figure() ax_lw = Axis3(fig_lw[1, 1]) - @test_nowarn Makie.plot!(ax_lw, plain_body; border_linewidth=3.0) + plots_lw = @test_nowarn Makie.plot!(ax_lw, plain_body; border_linewidth=3.0) + @test plots_lw isa Vector{Makie.AbstractPlot} + @test length(plots_lw) == 2 * length(plain_body.panels) end @testset "generated_slices reads the deflected .dat under its generated name" begin diff --git a/test/ram_geometry/test_kite_geometry.jl b/test/ram_geometry/test_kite_geometry.jl index 4c9fdc8d..64d0d1ec 100644 --- a/test/ram_geometry/test_kite_geometry.jl +++ b/test/ram_geometry/test_kite_geometry.jl @@ -32,6 +32,8 @@ using Serialization @test vertices[2] ≈ [1.0, 0.0, 0.0] @test vertices[3] ≈ [0.0, 1.0, 0.0] @test faces[1] == [1, 2, 3] + @test vertices isa Vector{Vector{Float64}} + @test faces isa Vector{Vector{Int64}} end @testset "Center of Mass Calculation" begin @@ -62,10 +64,8 @@ using Serialization # Create simple curved wing vertices r = 5.0 z_center = 2.0 - vertices = [] - for θ in range(-π/4, π/4, length=100) - push!(vertices, [0.0, r*sin(θ), z_center + r*cos(θ)]) - end + vertices = [[0.0, r*sin(θ), z_center + r*cos(θ)] + for θ in range(-π/4, π/4, length=100)] z, radius, gamma_tip = find_circle_center_and_radius(vertices) @@ -76,7 +76,7 @@ using Serialization r = 5.0 @testset "Interpolation Creation" begin - vertices = [] + vertices = Vector{Float64}[] z_center = 2.0 Δθ = π/2 / 1000 for θ in range(-π/4, π/4-Δθ, 1000) diff --git a/test/thesis_oriol_cayon.jl b/test/thesis_oriol_cayon.jl index 9d82d2a7..759be642 100644 --- a/test/thesis_oriol_cayon.jl +++ b/test/thesis_oriol_cayon.jl @@ -22,10 +22,10 @@ CD : Global CD function output_results(Fmag, aero_coeffs, ringvec, Uinf, controlpoints, Atot) rho = 1.225 alpha = aero_coeffs[:, 1] - F_rel = [] - F_gl = [] - Fmag_gl = [] - SideF = [] + F_rel = Vector{Vector{Float64}}[] + F_gl = Vector{Vector{Float64}}[] + Fmag_gl = Vector{Float64}[] + SideF = Float64[] Ltot = 0.0 Dtot = 0.0 SFtot = 0.0 @@ -124,12 +124,12 @@ ringvec : List of dictionaries containing the vectors that define each ring coord_L : coordinates of the aerodynamic centers of each wing panel """ function create_geometry_general(coordinates, Uinf, N, ring_geo, model) - filaments = [] - controlpoints = [] - rings = [] - wingpanels = [] - ringvec = [] - coord_L = [] + filaments = Dict{String, Any}[] + controlpoints = Dict{String, Any}[] + rings = Vector{Dict{String, Any}}[] + wingpanels = Dict{String, Vector{Float64}}[] + ringvec = Dict{String, Vector{Float64}}[] + coord_L = Vector{Float64}[] # Go through all wing panels for i in 1:N-1 @@ -279,7 +279,7 @@ function create_geometry_general(coordinates, Uinf, N, ring_geo, model) end push!(rings, filaments) - filaments = [] + filaments = Dict{String, Any}[] end coord_L = hcat(coord_L...) diff --git a/test/yaml_geometry/test_yaml_wing_deformation.jl b/test/yaml_geometry/test_yaml_wing_deformation.jl index 124b988b..73ecaa64 100644 --- a/test/yaml_geometry/test_yaml_wing_deformation.jl +++ b/test/yaml_geometry/test_yaml_wing_deformation.jl @@ -59,14 +59,10 @@ using Test body_aero = BodyAerodynamics([wing]) # Store original points for multiple panels - original_points = [] test_indices = [1, length(body_aero.panels) ÷ 2, length(body_aero.panels)] - for i in test_indices - push!(original_points, ( - LE=copy(body_aero.panels[i].LE_point_1), - TE=copy(body_aero.panels[i].TE_point_1) - )) - end + original_points = [(LE=copy(body_aero.panels[i].LE_point_1), + TE=copy(body_aero.panels[i].TE_point_1)) + for i in test_indices] # Apply spanwise-varying deformation (panel-level) n = wing.n_panels